]> 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 f58f8bd8f77b0c7f2fc984130d83cfbb3a40c591..1a5ee392e9c796ad7db3d8056b3fbf870dab4074 100644 (file)
@@ -214,7 +214,7 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode
                mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
                drm_mode_set_name(mode);
 
-               DRM_DEBUG("Adding native panel mode %s\n", mode->name);
+               DRM_DEBUG_KMS("Adding native panel mode %s\n", mode->name);
        } else if (native_mode->hdisplay != 0 &&
                   native_mode->vdisplay != 0) {
                /* mac laptops without an edid */
@@ -226,7 +226,7 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode
                 */
                mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
                mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
-               DRM_DEBUG("Adding cvt approximation of native panel mode %s\n", mode->name);
+               DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
        }
        return mode;
 }
@@ -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);
@@ -522,7 +534,7 @@ static int radeon_lvds_set_property(struct drm_connector *connector,
        struct radeon_encoder *radeon_encoder;
        enum radeon_rmx_type rmx_type;
 
-       DRM_DEBUG("\n");
+       DRM_DEBUG_KMS("\n");
        if (property != dev->mode_config.scaling_mode_property)
                return 0;
 
@@ -771,14 +783,14 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
                        } else
                                ret = connector_status_connected;
 
-                       /* multiple connectors on the same encoder with the same ddc line
-                        * This tends to be HDMI and DVI on the same encoder with the
-                        * same ddc line.  If the edid says HDMI, consider the HDMI port
-                        * connected and the DVI port disconnected.  If the edid doesn't
-                        * say HDMI, vice versa.
+                       /* This gets complicated.  We have boards with VGA + HDMI with a
+                        * shared DDC line and we have boards with DVI-D + HDMI with a shared
+                        * DDC line.  The latter is more complex because with DVI<->HDMI adapters
+                        * you don't really know what's connected to which port as both are digital.
                         */
                        if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {
                                struct drm_device *dev = connector->dev;
+                               struct radeon_device *rdev = dev->dev_private;
                                struct drm_connector *list_connector;
                                struct radeon_connector *list_radeon_connector;
                                list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
@@ -788,15 +800,10 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
                                        if (list_radeon_connector->shared_ddc &&
                                            (list_radeon_connector->ddc_bus->rec.i2c_id ==
                                             radeon_connector->ddc_bus->rec.i2c_id)) {
-                                               if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
-                                                       if (connector->connector_type == DRM_MODE_CONNECTOR_DVID) {
-                                                               kfree(radeon_connector->edid);
-                                                               radeon_connector->edid = NULL;
-                                                               ret = connector_status_disconnected;
-                                                       }
-                                               } else {
-                                                       if ((connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) ||
-                                                           (connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) {
+                                               /* cases where both connectors are digital */
+                                               if (list_connector->connector_type != DRM_MODE_CONNECTOR_VGA) {
+                                                       /* hpd is our only option in this case */
+                                                       if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
                                                                kfree(radeon_connector->edid);
                                                                radeon_connector->edid = NULL;
                                                                ret = connector_status_disconnected;
@@ -946,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)
@@ -972,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;
 }
 
@@ -1032,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;
@@ -1060,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;
+                       }
                }
        }
 
@@ -1074,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;
                }
@@ -1087,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;
                }
@@ -1101,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;
                }
@@ -1121,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,
@@ -1133,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:
@@ -1153,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);
@@ -1166,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;
                }
@@ -1177,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:
@@ -1191,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;
                }
@@ -1214,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
@@ -1225,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);
 }
@@ -1273,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;
                }
@@ -1281,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;
                }
@@ -1295,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;
                }
@@ -1333,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;
                }
@@ -1350,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
@@ -1360,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);
 }