aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2013-08-19 14:04:55 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-08-23 08:52:21 -0400
commit139ccd3fb12b3d17a773d2d61140f955a47fa470 (patch)
treed81128418f933475207916dabe3d7c5037e47dd0 /drivers/gpu/drm/i915/intel_display.c
parent8637b407cf1740c52a01b9fc0cf506f31e225151 (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.c142
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
2708train_done:
2707 DRM_DEBUG_KMS("FDI train done.\n"); 2709 DRM_DEBUG_KMS("FDI train done.\n");
2708} 2710}
2709 2711