drm/i915: Honour LVDS sync polarity from EDID
authorBryan Freed <bfreed@google.com>
Wed, 12 Jan 2011 21:43:19 +0000 (13:43 -0800)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 19 Jan 2011 13:12:16 +0000 (13:12 +0000)
The i915 driver normally assumes the video bios has configured several
of the LVDS panel registers, and it just inherits the values. If the
vbios has not run, several of these will need to be setup. So we need to
check that the LVDS sync polarity is correctly configured per any
available modelines (e.g. EDID) and adjust if not, issuing a warning as
we do.

Signed-off-by: Mark Hayter <mdhayter@chromium.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c

index 810cfa866413b721662d833316ab3e78c65f6c77..4c71f5692dae862da314e85859b3dafa76d8dcea 100644 (file)
 #define   LVDS_PIPEB_SELECT            (1 << 30)
 /* LVDS dithering flag on 965/g4x platform */
 #define   LVDS_ENABLE_DITHER           (1 << 25)
+/* LVDS sync polarity flags. Set to invert (i.e. negative) */
+#define   LVDS_VSYNC_POLARITY          (1 << 21)
+#define   LVDS_HSYNC_POLARITY          (1 << 20)
+
 /* Enable border for unscaled (or aspect-scaled) display */
 #define   LVDS_BORDER_ENABLE           (1 << 15)
 /*
index a90d65dad811b9a802d2d714dcedfdb582cfd76d..2c7e90f12657ae01e113ee1094f1a322d29ec74d 100644 (file)
@@ -4304,6 +4304,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        int ret;
        struct fdi_m_n m_n = {0};
        u32 reg, temp;
+       u32 lvds_sync = 0;
        int target_clock;
 
        drm_vblank_pre_modeset(dev, pipe);
@@ -4755,6 +4756,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
                        else
                                temp &= ~LVDS_ENABLE_DITHER;
                }
+               if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+                       lvds_sync |= LVDS_HSYNC_POLARITY;
+               if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+                       lvds_sync |= LVDS_VSYNC_POLARITY;
+               if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY))
+                   != lvds_sync) {
+                       char flags[2] = "-+";
+                       DRM_INFO("Changing LVDS panel from "
+                                "(%chsync, %cvsync) to (%chsync, %cvsync)\n",
+                                flags[!(temp & LVDS_HSYNC_POLARITY)],
+                                flags[!(temp & LVDS_VSYNC_POLARITY)],
+                                flags[!(lvds_sync & LVDS_HSYNC_POLARITY)],
+                                flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]);
+                       temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+                       temp |= lvds_sync;
+               }
                I915_WRITE(reg, temp);
        }