summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/intel_dp.c
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2015-05-05 17:17:34 +0300
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-05-22 00:07:45 +0300
commit1612c8bd4cef20dd06e8622bb8ab9bbe9f90c0e5 (patch)
treec4bfdf1a397a069bcdc6ef4629cea4dd72065d93 /drivers/gpu/drm/i915/intel_dp.c
parente8504ee293f62b380b55b727d2da7aa429db8f8d (diff)
downloadlinux-1612c8bd4cef20dd06e8622bb8ab9bbe9f90c0e5.tar.xz
drm/i915: Fix the IBX transcoder B workarounds
Currently the IBX transcoder B workarounds are not working correctly. Well, the HDMI one seems to be working somewhat, but the DP one is definitely busted. After a bit of experimentation it looks like the best way to make this work is first disable the port on transcoder B, and then re-enable it transcoder A, and immediately disable it again. We can also clean up the code by noting that we can't be called without a valid crtc. And also note that port A on ILK does not need the workaround, so let's check for that one too. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dp.c')
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d86e1f951666..abd442af4127 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -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);
}