drm/i915: correct intel_dp_get_config() function for DevCPT
authorXiong Zhang <xiong.y.zhang@intel.com>
Fri, 28 Jun 2013 04:59:06 +0000 (12:59 +0800)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 1 Jul 2013 09:14:59 +0000 (11:14 +0200)
On DevCPT, the control register for Transcoder DP Sync Polarity is
TRANS_DP_CTL, not DP_CTL.
Without this patch, Many call trace occur on CPT machine with DP monitor.
The call trace is like: *ERROR* mismatch in adjusted_mode.flags(expected X,found X)

v2: use intel-crtc to simple patch, suggested by Daniel.

Signed-off-by: Xiong Zhang <xiong.y.zhang@intel.com>
[danvet: Extend the encoder->get_config comment to specify that we now
also depend upon intel_encoder->base.crtc being correct. Also bikeshed
s/intel_crtc/crtc/.]
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65287
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h

index 24a44ede867d56e045220fe7d42667abc382f5a2..b739712340131dae2e35f56613fae22f2ca819f0 100644 (file)
@@ -1324,20 +1324,35 @@ static void intel_dp_get_config(struct intel_encoder *encoder,
                                struct intel_crtc_config *pipe_config)
 {
        struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
        u32 tmp, flags = 0;
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       enum port port = dp_to_dig_port(intel_dp)->port;
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 
-       tmp = I915_READ(intel_dp->output_reg);
+       if ((port == PORT_A) || !HAS_PCH_CPT(dev)) {
+               tmp = I915_READ(intel_dp->output_reg);
+               if (tmp & DP_SYNC_HS_HIGH)
+                       flags |= DRM_MODE_FLAG_PHSYNC;
+               else
+                       flags |= DRM_MODE_FLAG_NHSYNC;
 
-       if (tmp & DP_SYNC_HS_HIGH)
-               flags |= DRM_MODE_FLAG_PHSYNC;
-       else
-               flags |= DRM_MODE_FLAG_NHSYNC;
+               if (tmp & DP_SYNC_VS_HIGH)
+                       flags |= DRM_MODE_FLAG_PVSYNC;
+               else
+                       flags |= DRM_MODE_FLAG_NVSYNC;
+       } else {
+               tmp = I915_READ(TRANS_DP_CTL(crtc->pipe));
+               if (tmp & TRANS_DP_HSYNC_ACTIVE_HIGH)
+                       flags |= DRM_MODE_FLAG_PHSYNC;
+               else
+                       flags |= DRM_MODE_FLAG_NHSYNC;
 
-       if (tmp & DP_SYNC_VS_HIGH)
-               flags |= DRM_MODE_FLAG_PVSYNC;
-       else
-               flags |= DRM_MODE_FLAG_NVSYNC;
+               if (tmp & TRANS_DP_VSYNC_ACTIVE_HIGH)
+                       flags |= DRM_MODE_FLAG_PVSYNC;
+               else
+                       flags |= DRM_MODE_FLAG_NVSYNC;
+       }
 
        pipe_config->adjusted_mode.flags |= flags;
 }
index 9ddbe3b49fefa4410c6e782a25cc58af9db13940..c8c9b6f48230489b0cccdf37413e5b4d8fbb28d7 100644 (file)
@@ -141,7 +141,8 @@ struct intel_encoder {
        bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
        /* Reconstructs the equivalent mode flags for the current hardware
         * state. This must be called _after_ display->get_pipe_config has
-        * pre-filled the pipe config. */
+        * pre-filled the pipe config. Note that intel_encoder->base.crtc must
+        * be set correctly before calling this function. */
        void (*get_config)(struct intel_encoder *,
                           struct intel_crtc_config *pipe_config);
        int crtc_mask;