]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - drivers/gpu/drm/i915/intel_dp.c
drm/i915: Fix the IBX transcoder B workarounds
[mirror_ubuntu-zesty-kernel.git] / drivers / gpu / drm / i915 / intel_dp.c
index d86e1f95166609d331724544523c4be01c780565..abd442af41272c30b1e7719a32ca53c49a50760b 100644 (file)
@@ -3843,6 +3843,7 @@ static void
 intel_dp_link_down(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       struct intel_crtc *crtc = to_intel_crtc(intel_dig_port->base.base.crtc);
        enum port port = intel_dig_port->port;
        struct drm_device *dev = intel_dig_port->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -3859,34 +3860,38 @@ intel_dp_link_down(struct intel_dp *intel_dp)
        if ((IS_GEN7(dev) && port == PORT_A) ||
            (HAS_PCH_CPT(dev) && port != PORT_A)) {
                DP &= ~DP_LINK_TRAIN_MASK_CPT;
-               I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE_CPT);
+               DP |= DP_LINK_TRAIN_PAT_IDLE_CPT;
        } else {
                if (IS_CHERRYVIEW(dev))
                        DP &= ~DP_LINK_TRAIN_MASK_CHV;
                else
                        DP &= ~DP_LINK_TRAIN_MASK;
-               I915_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE);
+               DP |= DP_LINK_TRAIN_PAT_IDLE;
        }
+       I915_WRITE(intel_dp->output_reg, DP);
        POSTING_READ(intel_dp->output_reg);
 
-       if (HAS_PCH_IBX(dev) &&
-           I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
-               /* Hardware workaround: leaving our transcoder select
-                * set to transcoder B while it's off will prevent the
-                * corresponding HDMI output on transcoder A.
-                *
-                * Combine this with another hardware workaround:
-                * transcoder select bit can only be cleared while the
-                * port is enabled.
-                */
-               DP &= ~DP_PIPEB_SELECT;
+       DP &= ~(DP_PORT_EN | DP_AUDIO_OUTPUT_ENABLE);
+       I915_WRITE(intel_dp->output_reg, DP);
+       POSTING_READ(intel_dp->output_reg);
+
+       /*
+        * HW workaround for IBX, we need to move the port
+        * to transcoder A after disabling it to allow the
+        * matching HDMI port to be enabled on transcoder A.
+        */
+       if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) {
+               /* always enable with pattern 1 (as per spec) */
+               DP &= ~(DP_PIPEB_SELECT | DP_LINK_TRAIN_MASK);
+               DP |= DP_PORT_EN | DP_LINK_TRAIN_PAT_1;
+               I915_WRITE(intel_dp->output_reg, DP);
+               POSTING_READ(intel_dp->output_reg);
+
+               DP &= ~DP_PORT_EN;
                I915_WRITE(intel_dp->output_reg, DP);
                POSTING_READ(intel_dp->output_reg);
        }
 
-       DP &= ~DP_AUDIO_OUTPUT_ENABLE;
-       I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
-       POSTING_READ(intel_dp->output_reg);
        msleep(intel_dp->panel_power_down_delay);
 }