Commit 139ccd3f authored by Jesse Barnes's avatar Jesse Barnes Committed by Daniel Vetter

drm/i915: make IVB FDI training match spec v3

The existing code was trying different vswing and preemphasis settings
in the wrong place, and wasn't trying them enough.  So add a loop to
walk through them, properly disabling FDI TX and RX in between if a
failure is detected.

v2: remove unneeded reg writes, add delays around bit lock checks (Jesse)
v3: fix TX and RX disable per spec (Paulo)
    fix delays per spec (Paulo)
    make RX symbol lock check match TX bit lock check (Paulo)
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: default avatarPaulo Zanoni <paulo.r.zanoni@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51983Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 8637b407
...@@ -2597,7 +2597,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) ...@@ -2597,7 +2597,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
u32 reg, temp, i; u32 reg, temp, i, j;
/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
for train result */ for train result */
...@@ -2613,15 +2613,30 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) ...@@ -2613,15 +2613,30 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n", DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n",
I915_READ(FDI_RX_IIR(pipe))); I915_READ(FDI_RX_IIR(pipe)));
/* Try each vswing and preemphasis setting twice before moving on */
for (j = 0; j < ARRAY_SIZE(snb_b_fdi_train_param) * 2; j++) {
/* disable first in case we need to retry */
reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
temp &= ~FDI_TX_ENABLE;
I915_WRITE(reg, temp);
reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_AUTO;
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp &= ~FDI_RX_ENABLE;
I915_WRITE(reg, temp);
/* enable CPU FDI TX and PCH FDI RX */ /* enable CPU FDI TX and PCH FDI RX */
reg = FDI_TX_CTL(pipe); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg); temp = I915_READ(reg);
temp &= ~FDI_DP_PORT_WIDTH_MASK; temp &= ~FDI_DP_PORT_WIDTH_MASK;
temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes);
temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; temp |= snb_b_fdi_train_param[j/2];
temp |= FDI_COMPOSITE_SYNC; temp |= FDI_COMPOSITE_SYNC;
I915_WRITE(reg, temp | FDI_TX_ENABLE); I915_WRITE(reg, temp | FDI_TX_ENABLE);
...@@ -2630,25 +2645,14 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) ...@@ -2630,25 +2645,14 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
reg = FDI_RX_CTL(pipe); reg = FDI_RX_CTL(pipe);
temp = I915_READ(reg); temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_AUTO;
temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
temp |= FDI_COMPOSITE_SYNC; temp |= FDI_COMPOSITE_SYNC;
I915_WRITE(reg, temp | FDI_RX_ENABLE); I915_WRITE(reg, temp | FDI_RX_ENABLE);
POSTING_READ(reg); POSTING_READ(reg);
udelay(150); udelay(1); /* should be 0.5us */
for (i = 0; i < 4; i++) { 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); reg = FDI_RX_IIR(pipe);
temp = I915_READ(reg); temp = I915_READ(reg);
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
...@@ -2656,20 +2660,22 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) ...@@ -2656,20 +2660,22 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
if (temp & FDI_RX_BIT_LOCK || if (temp & FDI_RX_BIT_LOCK ||
(I915_READ(reg) & FDI_RX_BIT_LOCK)) { (I915_READ(reg) & FDI_RX_BIT_LOCK)) {
I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", i); DRM_DEBUG_KMS("FDI train 1 done, level %i.\n",
i);
break; break;
} }
udelay(1); /* should be 0.5us */
}
if (i == 4) {
DRM_DEBUG_KMS("FDI train 1 fail on vswing %d\n", j / 2);
continue;
} }
if (i == 4)
DRM_ERROR("FDI train 1 fail!\n");
/* Train 2 */ /* Train 2 */
reg = FDI_TX_CTL(pipe); reg = FDI_TX_CTL(pipe);
temp = I915_READ(reg); temp = I915_READ(reg);
temp &= ~FDI_LINK_TRAIN_NONE_IVB; temp &= ~FDI_LINK_TRAIN_NONE_IVB;
temp |= FDI_LINK_TRAIN_PATTERN_2_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); I915_WRITE(reg, temp);
reg = FDI_RX_CTL(pipe); reg = FDI_RX_CTL(pipe);
...@@ -2679,31 +2685,27 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) ...@@ -2679,31 +2685,27 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
I915_WRITE(reg, temp); I915_WRITE(reg, temp);
POSTING_READ(reg); POSTING_READ(reg);
udelay(150); udelay(2); /* should be 1.5us */
for (i = 0; i < 4; i++) { 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); reg = FDI_RX_IIR(pipe);
temp = I915_READ(reg); temp = I915_READ(reg);
DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
if (temp & FDI_RX_SYMBOL_LOCK) { if (temp & FDI_RX_SYMBOL_LOCK ||
(I915_READ(reg) & FDI_RX_SYMBOL_LOCK)) {
I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", i); DRM_DEBUG_KMS("FDI train 2 done, level %i.\n",
break; i);
goto train_done;
} }
udelay(2); /* should be 1.5us */
} }
if (i == 4) if (i == 4)
DRM_ERROR("FDI train 2 fail!\n"); DRM_DEBUG_KMS("FDI train 2 fail on vswing %d\n", j / 2);
}
train_done:
DRM_DEBUG_KMS("FDI train done.\n"); DRM_DEBUG_KMS("FDI train done.\n");
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment