drm/radeon/kms: deal with connectors sourced to the same encoder
authorAlex Deucher <alexdeucher@gmail.com>
Tue, 17 Nov 2009 20:44:01 +0000 (15:44 -0500)
committerDave Airlie <airlied@redhat.com>
Wed, 2 Dec 2009 01:36:44 +0000 (11:36 +1000)
Some systems have multiple connectors connected to the same encoder;
e.g., DVI and HDMI connected to the same encoder with the same ddc
line. Since we expose connectors as xrandr outputs, randr treats them
separately which results in it trying to source the same encoder to
different crtcs. If we have an HDMI and DVI-D port on the same encoder,
pick the one to be considered connected based on the edid (HDMI if edid
indicates HDMI, DVI otherwise).

Should fix fdo bug 25150

Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/radeon/radeon_connectors.c

index 93f6a970b51d805f59bf8b07b1b1fbcbe9d3bfac..ec2f3ffc42c1073c0828e0eb3fb9ba015b38d001 100644 (file)
@@ -735,6 +735,39 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
                                ret = connector_status_disconnected;
                        } 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.
+                        */
+                       if (radeon_connector->shared_ddc && connector_status_connected) {
+                               struct drm_device *dev = connector->dev;
+                               struct drm_connector *list_connector;
+                               struct radeon_connector *list_radeon_connector;
+                               list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
+                                       if (connector == list_connector)
+                                               continue;
+                                       list_radeon_connector = to_radeon_connector(list_connector);
+                                       if (radeon_connector->devices == list_radeon_connector->devices) {
+                                               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)) {
+                                                               kfree(radeon_connector->edid);
+                                                               radeon_connector->edid = NULL;
+                                                               ret = connector_status_disconnected;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
                }
        }