]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/gpu/drm/radeon/radeon_connectors.c
drm/radeon/kms: add missing scratch update in dp_detect
[net-next-2.6.git] / drivers / gpu / drm / radeon / radeon_connectors.c
index 41286c98b80d3cf41ec54564697b8c07bc503e7d..1a5ee392e9c796ad7db3d8056b3fbf870dab4074 100644 (file)
@@ -312,6 +312,20 @@ int radeon_connector_set_property(struct drm_connector *connector, struct drm_pr
                }
        }
 
+       if (property == rdev->mode_info.underscan_property) {
+               /* need to find digital encoder on connector */
+               encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
+               if (!encoder)
+                       return 0;
+
+               radeon_encoder = to_radeon_encoder(encoder);
+
+               if (radeon_encoder->underscan_type != val) {
+                       radeon_encoder->underscan_type = val;
+                       radeon_property_change_mode(&radeon_encoder->base);
+               }
+       }
+
        if (property == rdev->mode_info.tv_std_property) {
                encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC);
                if (!encoder) {
@@ -504,8 +518,6 @@ static void radeon_connector_destroy(struct drm_connector *connector)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
-       if (radeon_connector->ddc_bus)
-               radeon_i2c_destroy(radeon_connector->ddc_bus);
        if (radeon_connector->edid)
                kfree(radeon_connector->edid);
        kfree(radeon_connector->con_priv);
@@ -941,8 +953,6 @@ static void radeon_dp_connector_destroy(struct drm_connector *connector)
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
 
-       if (radeon_connector->ddc_bus)
-               radeon_i2c_destroy(radeon_connector->ddc_bus);
        if (radeon_connector->edid)
                kfree(radeon_connector->edid);
        if (radeon_dig_connector->dp_i2c_bus)
@@ -967,27 +977,29 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        enum drm_connector_status ret = connector_status_disconnected;
        struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
-       u8 sink_type;
 
        if (radeon_connector->edid) {
                kfree(radeon_connector->edid);
                radeon_connector->edid = NULL;
        }
 
-       sink_type = radeon_dp_getsinktype(radeon_connector);
-       if ((sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
-           (sink_type == CONNECTOR_OBJECT_ID_eDP)) {
-               if (radeon_dp_getdpcd(radeon_connector)) {
-                       radeon_dig_connector->dp_sink_type = sink_type;
+       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+               /* eDP is always DP */
+               radeon_dig_connector->dp_sink_type = CONNECTOR_OBJECT_ID_DISPLAYPORT;
+               if (radeon_dp_getdpcd(radeon_connector))
                        ret = connector_status_connected;
-               }
        } else {
-               if (radeon_ddc_probe(radeon_connector)) {
-                       radeon_dig_connector->dp_sink_type = sink_type;
-                       ret = connector_status_connected;
+               radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
+               if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) {
+                       if (radeon_dp_getdpcd(radeon_connector))
+                               ret = connector_status_connected;
+               } else {
+                       if (radeon_ddc_probe(radeon_connector))
+                               ret = connector_status_connected;
                }
        }
 
+       radeon_connector_update_scratch_regs(connector, ret);
        return ret;
 }
 
@@ -1027,10 +1039,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                          uint32_t supported_device,
                          int connector_type,
                          struct radeon_i2c_bus_rec *i2c_bus,
-                         bool linkb,
                          uint32_t igp_lane_info,
                          uint16_t connector_object_id,
-                         struct radeon_hpd *hpd)
+                         struct radeon_hpd *hpd,
+                         struct radeon_router *router)
 {
        struct radeon_device *rdev = dev->dev_private;
        struct drm_connector *connector;
@@ -1055,6 +1067,11 @@ radeon_add_atom_connector(struct drm_device *dev,
                                radeon_connector->shared_ddc = true;
                                shared_ddc = true;
                        }
+                       if (radeon_connector->router_bus && router->valid &&
+                           (radeon_connector->router.router_id == router->router_id)) {
+                               radeon_connector->shared_ddc = false;
+                               shared_ddc = false;
+                       }
                }
        }
 
@@ -1069,12 +1086,18 @@ radeon_add_atom_connector(struct drm_device *dev,
        radeon_connector->shared_ddc = shared_ddc;
        radeon_connector->connector_object_id = connector_object_id;
        radeon_connector->hpd = *hpd;
+       radeon_connector->router = *router;
+       if (router->valid) {
+               radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
+               if (!radeon_connector->router_bus)
+                       goto failed;
+       }
        switch (connector_type) {
        case DRM_MODE_CONNECTOR_VGA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1082,13 +1105,15 @@ radeon_add_atom_connector(struct drm_device *dev,
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.load_detect_property,
                                              1);
+               /* no HPD on analog connectors */
+               radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                connector->polled = DRM_CONNECTOR_POLL_CONNECT;
                break;
        case DRM_MODE_CONNECTOR_DVIA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1096,19 +1121,20 @@ radeon_add_atom_connector(struct drm_device *dev,
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.load_detect_property,
                                              1);
+               /* no HPD on analog connectors */
+               radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                break;
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_DVID:
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
-               radeon_dig_connector->linkb = linkb;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
                drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1116,6 +1142,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.coherent_mode_property,
                                              1);
+               if (ASIC_IS_AVIVO(rdev))
+                       drm_connector_attach_property(&radeon_connector->base,
+                                                     rdev->mode_info.underscan_property,
+                                                     UNDERSCAN_AUTO);
                if (connector_type == DRM_MODE_CONNECTOR_DVII) {
                        radeon_connector->dac_load_detect = true;
                        drm_connector_attach_property(&radeon_connector->base,
@@ -1128,19 +1158,22 @@ radeon_add_atom_connector(struct drm_device *dev,
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
-               radeon_dig_connector->linkb = linkb;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
                drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.coherent_mode_property,
                                              1);
+               if (ASIC_IS_AVIVO(rdev))
+                       drm_connector_attach_property(&radeon_connector->base,
+                                                     rdev->mode_info.underscan_property,
+                                                     UNDERSCAN_AUTO);
                subpixel_order = SubPixelHorizontalRGB;
                break;
        case DRM_MODE_CONNECTOR_DisplayPort:
@@ -1148,7 +1181,6 @@ radeon_add_atom_connector(struct drm_device *dev,
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
-               radeon_dig_connector->linkb = linkb;
                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);
@@ -1161,10 +1193,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                                radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
                        if (!radeon_dig_connector->dp_i2c_bus)
                                goto failed;
-                       if (connector_type == DRM_MODE_CONNECTOR_eDP)
-                               radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "eDP");
-                       else
-                               radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1172,6 +1201,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.coherent_mode_property,
                                              1);
+               if (ASIC_IS_AVIVO(rdev))
+                       drm_connector_attach_property(&radeon_connector->base,
+                                                     rdev->mode_info.underscan_property,
+                                                     UNDERSCAN_AUTO);
                break;
        case DRM_MODE_CONNECTOR_SVIDEO:
        case DRM_MODE_CONNECTOR_Composite:
@@ -1186,19 +1219,20 @@ radeon_add_atom_connector(struct drm_device *dev,
                        drm_connector_attach_property(&radeon_connector->base,
                                                      rdev->mode_info.tv_std_property,
                                                      radeon_atombios_get_tv_info(rdev));
+                       /* no HPD on analog connectors */
+                       radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                }
                break;
        case DRM_MODE_CONNECTOR_LVDS:
                radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
                if (!radeon_dig_connector)
                        goto failed;
-               radeon_dig_connector->linkb = linkb;
                radeon_dig_connector->igp_lane_info = igp_lane_info;
                radeon_connector->con_priv = radeon_dig_connector;
                drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1209,7 +1243,7 @@ radeon_add_atom_connector(struct drm_device *dev,
                break;
        }
 
-       if (hpd->hpd == RADEON_HPD_NONE) {
+       if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
                if (i2c_bus->valid)
                        connector->polled = DRM_CONNECTOR_POLL_CONNECT;
        } else
@@ -1220,8 +1254,6 @@ radeon_add_atom_connector(struct drm_device *dev,
        return;
 
 failed:
-       if (radeon_connector->ddc_bus)
-               radeon_i2c_destroy(radeon_connector->ddc_bus);
        drm_connector_cleanup(connector);
        kfree(connector);
 }
@@ -1268,7 +1300,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1276,13 +1308,15 @@ radeon_add_legacy_connector(struct drm_device *dev,
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.load_detect_property,
                                              1);
+               /* no HPD on analog connectors */
+               radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                connector->polled = DRM_CONNECTOR_POLL_CONNECT;
                break;
        case DRM_MODE_CONNECTOR_DVIA:
                drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1290,13 +1324,15 @@ radeon_add_legacy_connector(struct drm_device *dev,
                drm_connector_attach_property(&radeon_connector->base,
                                              rdev->mode_info.load_detect_property,
                                              1);
+               /* no HPD on analog connectors */
+               radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                break;
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_DVID:
                drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1328,13 +1364,15 @@ radeon_add_legacy_connector(struct drm_device *dev,
                        drm_connector_attach_property(&radeon_connector->base,
                                                      rdev->mode_info.tv_std_property,
                                                      radeon_combios_get_tv_info(rdev));
+                       /* no HPD on analog connectors */
+                       radeon_connector->hpd.hpd = RADEON_HPD_NONE;
                }
                break;
        case DRM_MODE_CONNECTOR_LVDS:
                drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
                drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs);
                if (i2c_bus->valid) {
-                       radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS");
+                       radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
                        if (!radeon_connector->ddc_bus)
                                goto failed;
                }
@@ -1345,7 +1383,7 @@ radeon_add_legacy_connector(struct drm_device *dev,
                break;
        }
 
-       if (hpd->hpd == RADEON_HPD_NONE) {
+       if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
                if (i2c_bus->valid)
                        connector->polled = DRM_CONNECTOR_POLL_CONNECT;
        } else
@@ -1355,8 +1393,6 @@ radeon_add_legacy_connector(struct drm_device *dev,
        return;
 
 failed:
-       if (radeon_connector->ddc_bus)
-               radeon_i2c_destroy(radeon_connector->ddc_bus);
        drm_connector_cleanup(connector);
        kfree(connector);
 }