[Intel-gfx] [PATCH 11/16] drm/i915: manual FDI training for Ivy Bridge
Keith Packard
keithp at keithp.com
Wed Apr 27 17:10:29 CEST 2011
On Tue, 26 Apr 2011 16:38:49 -0700, Jesse Barnes <jbarnes at 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 at 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
keith.packard at intel.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20110427/9558beca/attachment.sig>
More information about the Intel-gfx
mailing list