diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2015-05-05 10:17:34 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-05-21 17:07:45 -0400 |
commit | 1612c8bd4cef20dd06e8622bb8ab9bbe9f90c0e5 (patch) | |
tree | c4bfdf1a397a069bcdc6ef4629cea4dd72065d93 /drivers/gpu/drm/i915/intel_sdvo.c | |
parent | e8504ee293f62b380b55b727d2da7aa429db8f8d (diff) |
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_sdvo.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_sdvo.c | 41 |
1 files changed, 16 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e3e9c98eaf52..4a876914f212 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
@@ -1437,6 +1437,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder) | |||
1437 | { | 1437 | { |
1438 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; | 1438 | struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; |
1439 | struct intel_sdvo *intel_sdvo = to_sdvo(encoder); | 1439 | struct intel_sdvo *intel_sdvo = to_sdvo(encoder); |
1440 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | ||
1440 | u32 temp; | 1441 | u32 temp; |
1441 | 1442 | ||
1442 | intel_sdvo_set_active_outputs(intel_sdvo, 0); | 1443 | intel_sdvo_set_active_outputs(intel_sdvo, 0); |
@@ -1445,32 +1446,22 @@ static void intel_disable_sdvo(struct intel_encoder *encoder) | |||
1445 | DRM_MODE_DPMS_OFF); | 1446 | DRM_MODE_DPMS_OFF); |
1446 | 1447 | ||
1447 | temp = I915_READ(intel_sdvo->sdvo_reg); | 1448 | temp = I915_READ(intel_sdvo->sdvo_reg); |
1448 | if ((temp & SDVO_ENABLE) != 0) { | ||
1449 | /* HW workaround for IBX, we need to move the port to | ||
1450 | * transcoder A before disabling it. */ | ||
1451 | if (HAS_PCH_IBX(encoder->base.dev)) { | ||
1452 | struct drm_crtc *crtc = encoder->base.crtc; | ||
1453 | int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1; | ||
1454 | |||
1455 | if (temp & SDVO_PIPE_B_SELECT) { | ||
1456 | temp &= ~SDVO_PIPE_B_SELECT; | ||
1457 | I915_WRITE(intel_sdvo->sdvo_reg, temp); | ||
1458 | POSTING_READ(intel_sdvo->sdvo_reg); | ||
1459 | |||
1460 | /* Again we need to write this twice. */ | ||
1461 | I915_WRITE(intel_sdvo->sdvo_reg, temp); | ||
1462 | POSTING_READ(intel_sdvo->sdvo_reg); | ||
1463 | |||
1464 | /* Transcoder selection bits only update | ||
1465 | * effectively on vblank. */ | ||
1466 | if (crtc) | ||
1467 | intel_wait_for_vblank(encoder->base.dev, pipe); | ||
1468 | else | ||
1469 | msleep(50); | ||
1470 | } | ||
1471 | } | ||
1472 | 1449 | ||
1473 | intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE); | 1450 | temp &= ~SDVO_ENABLE; |
1451 | intel_sdvo_write_sdvox(intel_sdvo, temp); | ||
1452 | |||
1453 | /* | ||
1454 | * HW workaround for IBX, we need to move the port | ||
1455 | * to transcoder A after disabling it to allow the | ||
1456 | * matching DP port to be enabled on transcoder A. | ||
1457 | */ | ||
1458 | if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) { | ||
1459 | temp &= ~SDVO_PIPE_B_SELECT; | ||
1460 | temp |= SDVO_ENABLE; | ||
1461 | intel_sdvo_write_sdvox(intel_sdvo, temp); | ||
1462 | |||
1463 | temp &= ~SDVO_ENABLE; | ||
1464 | intel_sdvo_write_sdvox(intel_sdvo, temp); | ||
1474 | } | 1465 | } |
1475 | } | 1466 | } |
1476 | 1467 | ||