aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-11-01 04:15:30 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-11-11 17:51:30 -0500
commit23670b322c100c8fb2aa0c3d281ed10af428f664 (patch)
tree1e6f20a735d950d37d95fa657f5a995a659c5a84 /drivers/gpu/drm/i915/intel_display.c
parent8f5718a6d9a29bf1f51910c6b32bd0244f905303 (diff)
drm/i915: CPT+ pch transcoder workaround
We need to set the timing override chicken bit after fdi link training has completed and before we enable the transcoder. We also have to clear that bit again after disabling the pch transcoder. See "Graphics BSpec: vol4g North Display Engine Registers [IVB], Display Mode Set Sequence" and "Graphics BSpec: vol4h South Display Engine Registers [CPT, PPT], South Display Engine Transcoder and FDI Control, Transcoder Debug and DFT, TRANS_CHICKEN_2" bit 31: "Workaround : Enable the override prior to enabling the transcoder. Disable the override after disabling the transcoder." While at it, use the _PIPE macro for the other TRANS_DP register. v2: Keep the w/a as-is, but kill the original (but wrongly placed) workaround introduced in commit 3bcf603f6d5d18bd9d076dc280de71f48add4101 Author: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Wed Jul 27 11:51:40 2011 -0700 drm/i915: apply timing generator bug workaround on CPT and PPT and commit d4270e57efe9e2536798c59e1ed2fd0a1e5cdfcf Author: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Tue Oct 11 10:43:02 2011 -0700 drm/i915: export a CPT mode set verification function Note that this old code has unconditionally set the w/a, which might explain why fdi link training sometimes silently fails, and especially why the auto-train did not seem to work properly. v3: Paulo Zanoni pointed out that this workaround is also required on the LPT PCH. And Arthur Ranyan confirmed that this workaround is requierd for all ports on the pch, not just DP: The important part is that the bit is set whenever the pch transcoder is enabled, and that it is _not_ set while the fdi link is trained. It is also important that the pch transcoder is fully disabled, i.e. we have to wait for bit 30 to clear before clearing the w/a bit. Hence move to workaround into enable/disable_transcoder, where the pch transcoder gets enabled/disabled. v4: Whitespace changes dropped. v5: Don't run the w/a on IBX, we only need it on CPT/PPT and LPT. v6: - resolve conflicts with Paulo's big hsw vga rework - s/!IBX/CPT since hsw paths are now all separate, and Paulo's patch to implement the equivalent w/a for LPT is already merged. Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Paulo Zanoni <przanoni@gmail.com> Cc: Arthur Ranyan <arthur.j.runyan@intel.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> (v5) Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v5) Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 25a3ed693460..4be95e882d58 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1673,9 +1673,9 @@ static void intel_disable_pch_pll(struct intel_crtc *intel_crtc)
1673static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, 1673static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
1674 enum pipe pipe) 1674 enum pipe pipe)
1675{ 1675{
1676 int reg; 1676 struct drm_device *dev = dev_priv->dev;
1677 u32 val, pipeconf_val;
1678 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; 1677 struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
1678 uint32_t reg, val, pipeconf_val;
1679 1679
1680 /* PCH only available on ILK+ */ 1680 /* PCH only available on ILK+ */
1681 BUG_ON(dev_priv->info->gen < 5); 1681 BUG_ON(dev_priv->info->gen < 5);
@@ -1689,6 +1689,15 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,
1689 assert_fdi_tx_enabled(dev_priv, pipe); 1689 assert_fdi_tx_enabled(dev_priv, pipe);
1690 assert_fdi_rx_enabled(dev_priv, pipe); 1690 assert_fdi_rx_enabled(dev_priv, pipe);
1691 1691
1692 if (HAS_PCH_CPT(dev)) {
1693 /* Workaround: Set the timing override bit before enabling the
1694 * pch transcoder. */
1695 reg = TRANS_CHICKEN2(pipe);
1696 val = I915_READ(reg);
1697 val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
1698 I915_WRITE(reg, val);
1699 }
1700
1692 reg = TRANSCONF(pipe); 1701 reg = TRANSCONF(pipe);
1693 val = I915_READ(reg); 1702 val = I915_READ(reg);
1694 pipeconf_val = I915_READ(PIPECONF(pipe)); 1703 pipeconf_val = I915_READ(PIPECONF(pipe));
@@ -1731,7 +1740,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
1731 1740
1732 /* Workaround: set timing override bit. */ 1741 /* Workaround: set timing override bit. */
1733 val = I915_READ(_TRANSA_CHICKEN2); 1742 val = I915_READ(_TRANSA_CHICKEN2);
1734 val |= TRANS_AUTOTRAIN_GEN_STALL_DIS; 1743 val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
1735 I915_WRITE(_TRANSA_CHICKEN2, val); 1744 I915_WRITE(_TRANSA_CHICKEN2, val);
1736 1745
1737 val = TRANS_ENABLE; 1746 val = TRANS_ENABLE;
@@ -1751,8 +1760,8 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,
1751static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, 1760static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
1752 enum pipe pipe) 1761 enum pipe pipe)
1753{ 1762{
1754 int reg; 1763 struct drm_device *dev = dev_priv->dev;
1755 u32 val; 1764 uint32_t reg, val;
1756 1765
1757 /* FDI relies on the transcoder */ 1766 /* FDI relies on the transcoder */
1758 assert_fdi_tx_disabled(dev_priv, pipe); 1767 assert_fdi_tx_disabled(dev_priv, pipe);
@@ -1768,6 +1777,14 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv,
1768 /* wait for PCH transcoder off, transcoder state */ 1777 /* wait for PCH transcoder off, transcoder state */
1769 if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50)) 1778 if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
1770 DRM_ERROR("failed to disable transcoder %d\n", pipe); 1779 DRM_ERROR("failed to disable transcoder %d\n", pipe);
1780
1781 if (!HAS_PCH_IBX(dev)) {
1782 /* Workaround: Clear the timing override chicken bit again. */
1783 reg = TRANS_CHICKEN2(pipe);
1784 val = I915_READ(reg);
1785 val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
1786 I915_WRITE(reg, val);
1787 }
1771} 1788}
1772 1789
1773static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) 1790static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
@@ -1783,7 +1800,7 @@ static void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv)
1783 1800
1784 /* Workaround: clear timing override bit. */ 1801 /* Workaround: clear timing override bit. */
1785 val = I915_READ(_TRANSA_CHICKEN2); 1802 val = I915_READ(_TRANSA_CHICKEN2);
1786 val &= ~TRANS_AUTOTRAIN_GEN_STALL_DIS; 1803 val &= ~TRANS_CHICKEN2_TIMING_OVERRIDE;
1787 I915_WRITE(_TRANSA_CHICKEN2, val); 1804 I915_WRITE(_TRANSA_CHICKEN2, val);
1788} 1805}
1789 1806
@@ -3327,16 +3344,12 @@ prepare: /* separate function? */
3327void intel_cpt_verify_modeset(struct drm_device *dev, int pipe) 3344void intel_cpt_verify_modeset(struct drm_device *dev, int pipe)
3328{ 3345{
3329 struct drm_i915_private *dev_priv = dev->dev_private; 3346 struct drm_i915_private *dev_priv = dev->dev_private;
3330 int dslreg = PIPEDSL(pipe), tc2reg = TRANS_CHICKEN2(pipe); 3347 int dslreg = PIPEDSL(pipe);
3331 u32 temp; 3348 u32 temp;
3332 3349
3333 temp = I915_READ(dslreg); 3350 temp = I915_READ(dslreg);
3334 udelay(500); 3351 udelay(500);
3335 if (wait_for(I915_READ(dslreg) != temp, 5)) { 3352 if (wait_for(I915_READ(dslreg) != temp, 5)) {
3336 /* Without this, mode sets may fail silently on FDI */
3337 I915_WRITE(tc2reg, TRANS_AUTOTRAIN_GEN_STALL_DIS);
3338 udelay(250);
3339 I915_WRITE(tc2reg, 0);
3340 if (wait_for(I915_READ(dslreg) != temp, 5)) 3353 if (wait_for(I915_READ(dslreg) != temp, 5))
3341 DRM_ERROR("mode set failed: pipe %d stuck\n", pipe); 3354 DRM_ERROR("mode set failed: pipe %d stuck\n", pipe);
3342 } 3355 }