drm/i915: prefer VBT modes for SVDO-LVDS over EDID
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 10 Jun 2013 07:47:58 +0000 (09:47 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 10 Jun 2013 08:13:34 +0000 (10:13 +0200)
In

commit 53d3b4d7778daf15900867336c85d3f8dd70600c
Author: Egbert Eich <eich@suse.de>
Date:   Tue Jun 4 17:13:21 2013 +0200

    drm/i915/sdvo: Use &intel_sdvo->ddc instead of intel_sdvo->i2c for DDC

Egbert Eich fixed a long-standing bug where we simply used a
non-working i2c controller to read the EDID for SDVO-LVDS panels.
Unfortunately some machines seem to not be able to cope with the mode
provided in the EDID. Specifically they seem to not be able to cope
with a 4x pixel mutliplier instead of a 2x one, which seems to have
been worked around by slightly changing the panels native mode in the
VBT so that the dotclock is just barely above 50MHz.

Since it took forever to notice the breakage it's fairly safe to
assume that at least for SDVO-LVDS panels the VBT contains fairly sane
data. So just switch around the order and use VBT modes first.

v2: Also add EDID modes just in case, and spell Egbert correctly.

v3: Elaborate a bit more about what's going on on Chris' machine.

Cc: Egbert Eich <eich@suse.de>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65524
Cc: stable@vger.kernel.org
Reported-and-tested-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_sdvo.c

index f44aa75..d4ea6c2 100644 (file)
@@ -1777,10 +1777,13 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
         * arranged in priority order.
         */
        intel_ddc_get_modes(connector, &intel_sdvo->ddc);
-       if (list_empty(&connector->probed_modes) == false)
-               goto end;
 
-       /* Fetch modes from VBT */
+       /*
+        * Fetch modes from VBT. For SDVO prefer the VBT mode since some
+        * SDVO->LVDS transcoders can't cope with the EDID mode. Since
+        * drm_mode_probed_add adds the mode at the head of the list we add it
+        * last.
+        */
        if (dev_priv->sdvo_lvds_vbt_mode != NULL) {
                newmode = drm_mode_duplicate(connector->dev,
                                             dev_priv->sdvo_lvds_vbt_mode);
@@ -1792,7 +1795,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
                }
        }
 
-end:
        list_for_each_entry(newmode, &connector->probed_modes, head) {
                if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
                        intel_sdvo->sdvo_lvds_fixed_mode =