diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2013-08-19 14:04:55 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-08-23 08:52:21 -0400 |
commit | 139ccd3fb12b3d17a773d2d61140f955a47fa470 (patch) | |
tree | d81128418f933475207916dabe3d7c5037e47dd0 /drivers/gpu/drm/i915/intel_display.c | |
parent | 8637b407cf1740c52a01b9fc0cf506f31e225151 (diff) |
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: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=51983
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.c | 142 |
1 files changed, 72 insertions, 70 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e600e1cfb6ea..7a40427823c7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -2597,7 +2597,7 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) | |||
2597 | struct drm_i915_private *dev_priv = dev->dev_private; | 2597 | struct drm_i915_private *dev_priv = dev->dev_private; |
2598 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 2598 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2599 | int pipe = intel_crtc->pipe; | 2599 | int pipe = intel_crtc->pipe; |
2600 | u32 reg, temp, i; | 2600 | u32 reg, temp, i, j; |
2601 | 2601 | ||
2602 | /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit | 2602 | /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit |
2603 | for train result */ | 2603 | for train result */ |
@@ -2613,97 +2613,99 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) | |||
2613 | DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n", | 2613 | DRM_DEBUG_KMS("FDI_RX_IIR before link train 0x%x\n", |
2614 | I915_READ(FDI_RX_IIR(pipe))); | 2614 | I915_READ(FDI_RX_IIR(pipe))); |
2615 | 2615 | ||
2616 | /* enable CPU FDI TX and PCH FDI RX */ | 2616 | /* Try each vswing and preemphasis setting twice before moving on */ |
2617 | reg = FDI_TX_CTL(pipe); | 2617 | for (j = 0; j < ARRAY_SIZE(snb_b_fdi_train_param) * 2; j++) { |
2618 | temp = I915_READ(reg); | 2618 | /* disable first in case we need to retry */ |
2619 | temp &= ~FDI_DP_PORT_WIDTH_MASK; | 2619 | reg = FDI_TX_CTL(pipe); |
2620 | temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); | 2620 | temp = I915_READ(reg); |
2621 | temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB); | 2621 | temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB); |
2622 | temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; | 2622 | temp &= ~FDI_TX_ENABLE; |
2623 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | 2623 | I915_WRITE(reg, temp); |
2624 | temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; | ||
2625 | temp |= FDI_COMPOSITE_SYNC; | ||
2626 | I915_WRITE(reg, temp | FDI_TX_ENABLE); | ||
2627 | |||
2628 | I915_WRITE(FDI_RX_MISC(pipe), | ||
2629 | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); | ||
2630 | |||
2631 | reg = FDI_RX_CTL(pipe); | ||
2632 | temp = I915_READ(reg); | ||
2633 | temp &= ~FDI_LINK_TRAIN_AUTO; | ||
2634 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2635 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | ||
2636 | temp |= FDI_COMPOSITE_SYNC; | ||
2637 | I915_WRITE(reg, temp | FDI_RX_ENABLE); | ||
2638 | 2624 | ||
2639 | POSTING_READ(reg); | 2625 | reg = FDI_RX_CTL(pipe); |
2640 | udelay(150); | 2626 | temp = I915_READ(reg); |
2627 | temp &= ~FDI_LINK_TRAIN_AUTO; | ||
2628 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2629 | temp &= ~FDI_RX_ENABLE; | ||
2630 | I915_WRITE(reg, temp); | ||
2641 | 2631 | ||
2642 | for (i = 0; i < 4; i++) { | 2632 | /* enable CPU FDI TX and PCH FDI RX */ |
2643 | reg = FDI_TX_CTL(pipe); | 2633 | reg = FDI_TX_CTL(pipe); |
2644 | temp = I915_READ(reg); | 2634 | temp = I915_READ(reg); |
2635 | temp &= ~FDI_DP_PORT_WIDTH_MASK; | ||
2636 | temp |= FDI_DP_PORT_WIDTH(intel_crtc->config.fdi_lanes); | ||
2637 | temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; | ||
2645 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | 2638 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; |
2646 | temp |= snb_b_fdi_train_param[i]; | 2639 | temp |= snb_b_fdi_train_param[j/2]; |
2647 | I915_WRITE(reg, temp); | 2640 | temp |= FDI_COMPOSITE_SYNC; |
2641 | I915_WRITE(reg, temp | FDI_TX_ENABLE); | ||
2648 | 2642 | ||
2649 | POSTING_READ(reg); | 2643 | I915_WRITE(FDI_RX_MISC(pipe), |
2650 | udelay(500); | 2644 | FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); |
2651 | 2645 | ||
2652 | reg = FDI_RX_IIR(pipe); | 2646 | reg = FDI_RX_CTL(pipe); |
2653 | temp = I915_READ(reg); | 2647 | temp = I915_READ(reg); |
2654 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); | 2648 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; |
2655 | 2649 | temp |= FDI_COMPOSITE_SYNC; | |
2656 | if (temp & FDI_RX_BIT_LOCK || | 2650 | I915_WRITE(reg, temp | FDI_RX_ENABLE); |
2657 | (I915_READ(reg) & FDI_RX_BIT_LOCK)) { | ||
2658 | I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); | ||
2659 | DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", i); | ||
2660 | break; | ||
2661 | } | ||
2662 | } | ||
2663 | if (i == 4) | ||
2664 | DRM_ERROR("FDI train 1 fail!\n"); | ||
2665 | 2651 | ||
2666 | /* Train 2 */ | 2652 | POSTING_READ(reg); |
2667 | reg = FDI_TX_CTL(pipe); | 2653 | udelay(1); /* should be 0.5us */ |
2668 | temp = I915_READ(reg); | ||
2669 | temp &= ~FDI_LINK_TRAIN_NONE_IVB; | ||
2670 | temp |= FDI_LINK_TRAIN_PATTERN_2_IVB; | ||
2671 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | ||
2672 | temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; | ||
2673 | I915_WRITE(reg, temp); | ||
2674 | 2654 | ||
2675 | reg = FDI_RX_CTL(pipe); | 2655 | for (i = 0; i < 4; i++) { |
2676 | temp = I915_READ(reg); | 2656 | reg = FDI_RX_IIR(pipe); |
2677 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | 2657 | temp = I915_READ(reg); |
2678 | temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; | 2658 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); |
2679 | I915_WRITE(reg, temp); | ||
2680 | 2659 | ||
2681 | POSTING_READ(reg); | 2660 | if (temp & FDI_RX_BIT_LOCK || |
2682 | udelay(150); | 2661 | (I915_READ(reg) & FDI_RX_BIT_LOCK)) { |
2662 | I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); | ||
2663 | DRM_DEBUG_KMS("FDI train 1 done, level %i.\n", | ||
2664 | i); | ||
2665 | break; | ||
2666 | } | ||
2667 | udelay(1); /* should be 0.5us */ | ||
2668 | } | ||
2669 | if (i == 4) { | ||
2670 | DRM_DEBUG_KMS("FDI train 1 fail on vswing %d\n", j / 2); | ||
2671 | continue; | ||
2672 | } | ||
2683 | 2673 | ||
2684 | for (i = 0; i < 4; i++) { | 2674 | /* Train 2 */ |
2685 | reg = FDI_TX_CTL(pipe); | 2675 | reg = FDI_TX_CTL(pipe); |
2686 | temp = I915_READ(reg); | 2676 | temp = I915_READ(reg); |
2687 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | 2677 | temp &= ~FDI_LINK_TRAIN_NONE_IVB; |
2688 | temp |= snb_b_fdi_train_param[i]; | 2678 | temp |= FDI_LINK_TRAIN_PATTERN_2_IVB; |
2679 | I915_WRITE(reg, temp); | ||
2680 | |||
2681 | reg = FDI_RX_CTL(pipe); | ||
2682 | temp = I915_READ(reg); | ||
2683 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | ||
2684 | temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; | ||
2689 | I915_WRITE(reg, temp); | 2685 | I915_WRITE(reg, temp); |
2690 | 2686 | ||
2691 | POSTING_READ(reg); | 2687 | POSTING_READ(reg); |
2692 | udelay(500); | 2688 | udelay(2); /* should be 1.5us */ |
2693 | 2689 | ||
2694 | reg = FDI_RX_IIR(pipe); | 2690 | for (i = 0; i < 4; i++) { |
2695 | temp = I915_READ(reg); | 2691 | reg = FDI_RX_IIR(pipe); |
2696 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); | 2692 | temp = I915_READ(reg); |
2693 | DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); | ||
2697 | 2694 | ||
2698 | if (temp & FDI_RX_SYMBOL_LOCK) { | 2695 | if (temp & FDI_RX_SYMBOL_LOCK || |
2699 | I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); | 2696 | (I915_READ(reg) & FDI_RX_SYMBOL_LOCK)) { |
2700 | DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", i); | 2697 | I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); |
2701 | break; | 2698 | DRM_DEBUG_KMS("FDI train 2 done, level %i.\n", |
2699 | i); | ||
2700 | goto train_done; | ||
2701 | } | ||
2702 | udelay(2); /* should be 1.5us */ | ||
2702 | } | 2703 | } |
2704 | if (i == 4) | ||
2705 | DRM_DEBUG_KMS("FDI train 2 fail on vswing %d\n", j / 2); | ||
2703 | } | 2706 | } |
2704 | if (i == 4) | ||
2705 | DRM_ERROR("FDI train 2 fail!\n"); | ||
2706 | 2707 | ||
2708 | train_done: | ||
2707 | DRM_DEBUG_KMS("FDI train done.\n"); | 2709 | DRM_DEBUG_KMS("FDI train done.\n"); |
2708 | } | 2710 | } |
2709 | 2711 | ||