drm/radeon: handle vfct with multiple vbios images
[pandora-kernel.git] / drivers / gpu / drm / radeon / radeon_connectors.c
index fb8db7a..40633f3 100644 (file)
@@ -79,10 +79,21 @@ void radeon_connector_hotplug(struct drm_connector *connector)
                if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
                        int saved_dpms = connector->dpms;
                        /* Only turn off the display if it's physically disconnected */
-                       if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd))
+                       if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
                                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-                       else if (radeon_dp_needs_link_train(radeon_connector))
+                       } else if (radeon_dp_needs_link_train(radeon_connector)) {
+                               /* Don't try to start link training before we
+                                * have the dpcd */
+                               if (!radeon_dp_getdpcd(radeon_connector))
+                                       return;
+
+                               /* set it to OFF so that drm_helper_connector_dpms()
+                                * won't return immediately since the current state
+                                * is ON at this point.
+                                */
+                               connector->dpms = DRM_MODE_DPMS_OFF;
                                drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+                       }
                        connector->dpms = saved_dpms;
                }
        }
@@ -683,7 +694,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force)
                ret = connector_status_disconnected;
 
        if (radeon_connector->ddc_bus)
-               dret = radeon_ddc_probe(radeon_connector);
+               dret = radeon_ddc_probe(radeon_connector, false);
        if (dret) {
                radeon_connector->detected_by_load = false;
                if (radeon_connector->edid) {
@@ -865,7 +876,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
        bool dret = false;
 
        if (radeon_connector->ddc_bus)
-               dret = radeon_ddc_probe(radeon_connector);
+               dret = radeon_ddc_probe(radeon_connector, false);
        if (dret) {
                radeon_connector->detected_by_load = false;
                if (radeon_connector->edid) {
@@ -1240,7 +1251,7 @@ bool radeon_connector_is_dp12_capable(struct drm_connector *connector)
        struct radeon_device *rdev = dev->dev_private;
 
        if (ASIC_IS_DCE5(rdev) &&
-           (rdev->clock.dp_extclk >= 53900) &&
+           (rdev->clock.default_dispclk >= 53900) &&
            radeon_connector_encoder_is_hbr2(connector)) {
                return true;
        }
@@ -1293,7 +1304,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                if (encoder) {
                        /* setup ddc on the bridge */
                        radeon_atom_ext_encoder_setup_ddc(encoder);
-                       if (radeon_ddc_probe(radeon_connector)) /* try DDC */
+                       /* bridge chips are always aux */
+                       if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */
                                ret = connector_status_connected;
                        else if (radeon_connector->dac_load_detect) { /* try load detection */
                                struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
@@ -1311,7 +1323,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                                if (radeon_dp_getdpcd(radeon_connector))
                                        ret = connector_status_connected;
                        } else {
-                               if (radeon_ddc_probe(radeon_connector))
+                               /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */
+                               if (radeon_ddc_probe(radeon_connector, false))
                                        ret = connector_status_connected;
                        }
                }
@@ -1379,6 +1392,24 @@ struct drm_connector_funcs radeon_dp_connector_funcs = {
        .force = radeon_dvi_force,
 };
 
+static const struct drm_connector_funcs radeon_edp_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = radeon_dp_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .set_property = radeon_lvds_set_property,
+       .destroy = radeon_dp_connector_destroy,
+       .force = radeon_dvi_force,
+};
+
+static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = {
+       .dpms = drm_helper_connector_dpms,
+       .detect = radeon_dp_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .set_property = radeon_lvds_set_property,
+       .destroy = radeon_dp_connector_destroy,
+       .force = radeon_dvi_force,
+};
+
 void
 radeon_add_atom_connector(struct drm_device *dev,
                          uint32_t connector_id,
@@ -1470,8 +1501,6 @@ radeon_add_atom_connector(struct drm_device *dev,
                        goto failed;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
-               drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
-               drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
                if (i2c_bus->valid) {
                        /* add DP i2c bus */
                        if (connector_type == DRM_MODE_CONNECTOR_eDP)
@@ -1488,6 +1517,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                case DRM_MODE_CONNECTOR_VGA:
                case DRM_MODE_CONNECTOR_DVIA:
                default:
+                       drm_connector_init(dev, &radeon_connector->base,
+                                          &radeon_dp_connector_funcs, connector_type);
+                       drm_connector_helper_add(&radeon_connector->base,
+                                                &radeon_dp_connector_helper_funcs);
                        connector->interlace_allowed = true;
                        connector->doublescan_allowed = true;
                        radeon_connector->dac_load_detect = true;
@@ -1500,6 +1533,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                case DRM_MODE_CONNECTOR_HDMIA:
                case DRM_MODE_CONNECTOR_HDMIB:
                case DRM_MODE_CONNECTOR_DisplayPort:
+                       drm_connector_init(dev, &radeon_connector->base,
+                                          &radeon_dp_connector_funcs, connector_type);
+                       drm_connector_helper_add(&radeon_connector->base,
+                                                &radeon_dp_connector_helper_funcs);
                        drm_connector_attach_property(&radeon_connector->base,
                                                      rdev->mode_info.underscan_property,
                                                      UNDERSCAN_OFF);
@@ -1524,6 +1561,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                        break;
                case DRM_MODE_CONNECTOR_LVDS:
                case DRM_MODE_CONNECTOR_eDP:
+                       drm_connector_init(dev, &radeon_connector->base,
+                                          &radeon_lvds_bridge_connector_funcs, connector_type);
+                       drm_connector_helper_add(&radeon_connector->base,
+                                                &radeon_dp_connector_helper_funcs);
                        drm_connector_attach_property(&radeon_connector->base,
                                                      dev->mode_config.scaling_mode_property,
                                                      DRM_MODE_SCALE_FULLSCREEN);
@@ -1548,7 +1589,6 @@ radeon_add_atom_connector(struct drm_device *dev,
                                                      1);
                        /* no HPD on analog connectors */
                        radeon_connector->hpd.hpd = RADEON_HPD_NONE;
-                       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
                        connector->interlace_allowed = true;
                        connector->doublescan_allowed = true;
                        break;
@@ -1687,7 +1727,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                                goto failed;
                        radeon_dig_connector->igp_lane_info = igp_lane_info;
                        radeon_connector->con_priv = radeon_dig_connector;
-                       drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type);
+                       drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type);
                        drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs);
                        if (i2c_bus->valid) {
                                /* add DP i2c bus */
@@ -1746,8 +1786,10 @@ radeon_add_atom_connector(struct drm_device *dev,
        }
 
        if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
-               if (i2c_bus->valid)
-                       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+               if (i2c_bus->valid) {
+                       connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+                                           DRM_CONNECTOR_POLL_DISCONNECT;
+               }
        } else
                connector->polled = DRM_CONNECTOR_POLL_HPD;
 
@@ -1819,7 +1861,6 @@ radeon_add_legacy_connector(struct drm_device *dev,
                                              1);
                /* no HPD on analog connectors */
                radeon_connector->hpd.hpd = RADEON_HPD_NONE;
-               connector->polled = DRM_CONNECTOR_POLL_CONNECT;
                connector->interlace_allowed = true;
                connector->doublescan_allowed = true;
                break;
@@ -1904,10 +1945,13 @@ radeon_add_legacy_connector(struct drm_device *dev,
        }
 
        if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
-               if (i2c_bus->valid)
-                       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+               if (i2c_bus->valid) {
+                       connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+                                           DRM_CONNECTOR_POLL_DISCONNECT;
+               }
        } else
                connector->polled = DRM_CONNECTOR_POLL_HPD;
+
        connector->display_info.subpixel_order = subpixel_order;
        drm_sysfs_connector_add(connector);
        if (connector_type == DRM_MODE_CONNECTOR_LVDS) {