Message ID | 1303861134-8762-12-git-send-email-jbarnes@virtuousgeek.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, 26 Apr 2011 16:38:49 -0700, Jesse Barnes <jbarnes@virtuousgeek.org> wrote: > A0 stepping chips need to use manual training, but the bits have all > moved. So fix things up so we can at least train FDI for VGA links. This patch should be before the auto-train patch so that we don't have a broken driver between them. > > Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> > --- > drivers/gpu/drm/i915/i915_reg.h | 10 +++ > drivers/gpu/drm/i915/intel_display.c | 129 +++++++++++++++++++++++++++++++++- > 2 files changed, 136 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index b77bd49..03c99ed 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -3105,7 +3105,15 @@ > #define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18) > /* Ironlake: hardwired to 1 */ > #define FDI_TX_PLL_ENABLE (1<<14) > + > +/* Ivybridge has different bits for lolz */ > +#define FDI_LINK_TRAIN_PATTERN_1_IVB (0<<8) > +#define FDI_LINK_TRAIN_PATTERN_2_IVB (1<<8) > +#define FDI_LINK_TRAIN_PATTERN_IDLE_IVB (2<<8) > +#define FDI_LINK_TRAIN_NONE_IVB (3<<8) > + > /* both Tx and Rx */ > +#define FDI_LINK_TRAIN_AUTO (1<<10) > #define FDI_SCRAMBLING_ENABLE (0<<7) > #define FDI_SCRAMBLING_DISABLE (1<<7) > /* Ivybridge */ > @@ -3117,6 +3125,8 @@ > #define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL) > #define FDI_RX_ENABLE (1<<31) > /* train, dp width same as FDI_TX */ > +#define FDI_FS_ERRC_ENABLE (1<<27) > +#define FDI_FE_ERRC_ENABLE (1<<26) > #define FDI_DP_PORT_WIDTH_X8 (7<<19) > #define FDI_8BPC (0<<16) > #define FDI_10BPC (1<<16) > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index db46e4f..866abe5 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c > @@ -2047,8 +2047,13 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) > /* enable normal train */ > reg = FDI_TX_CTL(pipe); > temp = I915_READ(reg); > - temp &= ~FDI_LINK_TRAIN_NONE; > - temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; > + if (IS_GEN6(dev)) { > + temp &= ~FDI_LINK_TRAIN_NONE; > + temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; > + } else if (IS_IVYBRIDGE(dev)) { > + temp &= ~FDI_LINK_TRAIN_NONE_IVB; > + temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; > + } > I915_WRITE(reg, temp); > > reg = FDI_RX_CTL(pipe); > @@ -2065,6 +2070,11 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) > /* wait one idle pattern time */ > POSTING_READ(reg); > udelay(1000); > + > + /* IVB wants error correction enabled */ > + if (IS_IVYBRIDGE(dev)) > + I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE | > + FDI_FE_ERRC_ENABLE); > } > > /* The FDI link training functions for ILK/Ibexpeak. */ > @@ -2292,6 +2302,115 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) > DRM_DEBUG_KMS("FDI train done.\n"); > } > > +/* Manual link training for Ivy Bridge A0 parts */ > +static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) > +{ > + struct drm_device *dev = crtc->dev; > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); > + int pipe = intel_crtc->pipe; > + u32 reg, temp, i; > + > + /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit > + for train result */ > + reg = FDI_RX_IMR(pipe); > + temp = I915_READ(reg); > + temp &= ~FDI_RX_SYMBOL_LOCK; > + temp &= ~FDI_RX_BIT_LOCK; > + I915_WRITE(reg, temp); > + > + POSTING_READ(reg); > + udelay(150); > + > + /* enable CPU FDI TX and PCH FDI RX */ > + reg = FDI_TX_CTL(pipe); > + temp = I915_READ(reg); > + temp &= ~(7 << 19); > + temp |= (intel_crtc->fdi_lanes - 1) << 19; > + temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB); > + temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; > + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; > + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; > + I915_WRITE(reg, temp | FDI_TX_ENABLE); > + > + reg = FDI_RX_CTL(pipe); > + temp = I915_READ(reg); > + temp &= ~FDI_LINK_TRAIN_AUTO; > + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; > + temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; > + I915_WRITE(reg, temp | FDI_RX_ENABLE); > + > + POSTING_READ(reg); > + udelay(150); > + > + for (i = 0; i < 4; i++ ) { > + reg = FDI_TX_CTL(pipe); > + temp = I915_READ(reg); > + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; > + temp |= snb_b_fdi_train_param[i]; > + I915_WRITE(reg, temp); > + > + POSTING_READ(reg); > + udelay(500); > + > + reg = FDI_RX_IIR(pipe); > + temp = I915_READ(reg); > + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); > + > + if (temp & FDI_RX_BIT_LOCK || > + (I915_READ(reg) & FDI_RX_BIT_LOCK)) { > + I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); > + DRM_DEBUG_KMS("FDI train 1 done.\n"); > + break; > + } > + } > + if (i == 4) > + DRM_ERROR("FDI train 1 fail!\n"); > + > + /* Train 2 */ > + reg = FDI_TX_CTL(pipe); > + temp = I915_READ(reg); > + temp &= ~FDI_LINK_TRAIN_NONE_IVB; > + temp |= FDI_LINK_TRAIN_PATTERN_2_IVB; > + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; > + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; > + I915_WRITE(reg, temp); > + > + reg = FDI_RX_CTL(pipe); > + temp = I915_READ(reg); > + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; > + temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; > + I915_WRITE(reg, temp); > + > + POSTING_READ(reg); > + udelay(150); > + > + for (i = 0; i < 4; i++ ) { > + reg = FDI_TX_CTL(pipe); > + temp = I915_READ(reg); > + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; > + temp |= snb_b_fdi_train_param[i]; > + I915_WRITE(reg, temp); > + > + POSTING_READ(reg); > + udelay(500); > + > + reg = FDI_RX_IIR(pipe); > + temp = I915_READ(reg); > + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); > + > + if (temp & FDI_RX_SYMBOL_LOCK) { > + I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); > + DRM_DEBUG_KMS("FDI train 2 done.\n"); > + break; > + } > + } > + if (i == 4) > + DRM_ERROR("FDI train 2 fail!\n"); > + > + DRM_DEBUG_KMS("FDI train done.\n"); > +} > + > /* On Ivybridge we can use auto training */ > static void ivb_fdi_link_train(struct drm_crtc *crtc) > { > @@ -7367,7 +7486,11 @@ static void intel_init_display(struct drm_device *dev) > } > dev_priv->display.train_fdi = gen6_fdi_link_train; > } else if (IS_IVYBRIDGE(dev)) { > - dev_priv->display.train_fdi = ivb_fdi_link_train; > + /* FIXME: detect B0+ stepping and use auto training */ > + if (0) > + dev_priv->display.train_fdi = ivb_fdi_link_train; > + else > + dev_priv->display.train_fdi = ivb_manual_fdi_link_train; > } else > dev_priv->display.update_wm = NULL; > } else if (IS_PINEVIEW(dev)) { > -- > 1.7.4.1 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
On Wed, 27 Apr 2011 08:10:29 -0700 Keith Packard <keithp@keithp.com> wrote: > On Tue, 26 Apr 2011 16:38:49 -0700, Jesse Barnes <jbarnes@virtuousgeek.org> wrote: > > A0 stepping chips need to use manual training, but the bits have all > > moved. So fix things up so we can at least train FDI for VGA links. > > This patch should be before the auto-train patch so that we don't have > a broken driver between them. Ok, will re-order. Jesse
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b77bd49..03c99ed 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3105,7 +3105,15 @@ #define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18) /* Ironlake: hardwired to 1 */ #define FDI_TX_PLL_ENABLE (1<<14) + +/* Ivybridge has different bits for lolz */ +#define FDI_LINK_TRAIN_PATTERN_1_IVB (0<<8) +#define FDI_LINK_TRAIN_PATTERN_2_IVB (1<<8) +#define FDI_LINK_TRAIN_PATTERN_IDLE_IVB (2<<8) +#define FDI_LINK_TRAIN_NONE_IVB (3<<8) + /* both Tx and Rx */ +#define FDI_LINK_TRAIN_AUTO (1<<10) #define FDI_SCRAMBLING_ENABLE (0<<7) #define FDI_SCRAMBLING_DISABLE (1<<7) /* Ivybridge */ @@ -3117,6 +3125,8 @@ #define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL) #define FDI_RX_ENABLE (1<<31) /* train, dp width same as FDI_TX */ +#define FDI_FS_ERRC_ENABLE (1<<27) +#define FDI_FE_ERRC_ENABLE (1<<26) #define FDI_DP_PORT_WIDTH_X8 (7<<19) #define FDI_8BPC (0<<16) #define FDI_10BPC (1<<16) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index db46e4f..866abe5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2047,8 +2047,13 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) /* enable normal train */ reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); - temp &= ~FDI_LINK_TRAIN_NONE; - temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; + if (IS_GEN6(dev)) { + temp &= ~FDI_LINK_TRAIN_NONE; + temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; + } else if (IS_IVYBRIDGE(dev)) { + temp &= ~FDI_LINK_TRAIN_NONE_IVB; + temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; + } I915_WRITE(reg, temp); reg = FDI_RX_CTL(pipe); @@ -2065,6 +2070,11 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) /* wait one idle pattern time */ POSTING_READ(reg); udelay(1000); + + /* IVB wants error correction enabled */ + if (IS_IVYBRIDGE(dev)) + I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE | + FDI_FE_ERRC_ENABLE); } /* The FDI link training functions for ILK/Ibexpeak. */ @@ -2292,6 +2302,115 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) DRM_DEBUG_KMS("FDI train done.\n"); } +/* Manual link training for Ivy Bridge A0 parts */ +static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + u32 reg, temp, i; + + /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit + for train result */ + reg = FDI_RX_IMR(pipe); + temp = I915_READ(reg); + temp &= ~FDI_RX_SYMBOL_LOCK; + temp &= ~FDI_RX_BIT_LOCK; + I915_WRITE(reg, temp); + + POSTING_READ(reg); + udelay(150); + + /* enable CPU FDI TX and PCH FDI RX */ + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~(7 << 19); + temp |= (intel_crtc->fdi_lanes - 1) << 19; + temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB); + temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; + I915_WRITE(reg, temp | FDI_TX_ENABLE); + + reg = FDI_RX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_AUTO; + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; + I915_WRITE(reg, temp | FDI_RX_ENABLE); + + POSTING_READ(reg); + udelay(150); + + for (i = 0; i < 4; i++ ) { + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= snb_b_fdi_train_param[i]; + I915_WRITE(reg, temp); + + POSTING_READ(reg); + udelay(500); + + reg = FDI_RX_IIR(pipe); + temp = I915_READ(reg); + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); + + if (temp & FDI_RX_BIT_LOCK || + (I915_READ(reg) & FDI_RX_BIT_LOCK)) { + I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); + DRM_DEBUG_KMS("FDI train 1 done.\n"); + break; + } + } + if (i == 4) + DRM_ERROR("FDI train 1 fail!\n"); + + /* Train 2 */ + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_NONE_IVB; + temp |= FDI_LINK_TRAIN_PATTERN_2_IVB; + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; + I915_WRITE(reg, temp); + + reg = FDI_RX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; + temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; + I915_WRITE(reg, temp); + + POSTING_READ(reg); + udelay(150); + + for (i = 0; i < 4; i++ ) { + reg = FDI_TX_CTL(pipe); + temp = I915_READ(reg); + temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; + temp |= snb_b_fdi_train_param[i]; + I915_WRITE(reg, temp); + + POSTING_READ(reg); + udelay(500); + + reg = FDI_RX_IIR(pipe); + temp = I915_READ(reg); + DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); + + if (temp & FDI_RX_SYMBOL_LOCK) { + I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); + DRM_DEBUG_KMS("FDI train 2 done.\n"); + break; + } + } + if (i == 4) + DRM_ERROR("FDI train 2 fail!\n"); + + DRM_DEBUG_KMS("FDI train done.\n"); +} + /* On Ivybridge we can use auto training */ static void ivb_fdi_link_train(struct drm_crtc *crtc) { @@ -7367,7 +7486,11 @@ static void intel_init_display(struct drm_device *dev) } dev_priv->display.train_fdi = gen6_fdi_link_train; } else if (IS_IVYBRIDGE(dev)) { - dev_priv->display.train_fdi = ivb_fdi_link_train; + /* FIXME: detect B0+ stepping and use auto training */ + if (0) + dev_priv->display.train_fdi = ivb_fdi_link_train; + else + dev_priv->display.train_fdi = ivb_manual_fdi_link_train; } else dev_priv->display.update_wm = NULL; } else if (IS_PINEVIEW(dev)) {
A0 stepping chips need to use manual training, but the bits have all moved. So fix things up so we can at least train FDI for VGA links. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> --- drivers/gpu/drm/i915/i915_reg.h | 10 +++ drivers/gpu/drm/i915/intel_display.c | 129 +++++++++++++++++++++++++++++++++- 2 files changed, 136 insertions(+), 3 deletions(-)