aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2011-04-28 18:09:55 -0400
committerKeith Packard <keithp@keithp.com>2011-05-13 20:06:22 -0400
commit357555c00f8414057f0c12ee3f479f197264123d (patch)
treea3439349e6a267642199548561b53cfddca4ac04 /drivers/gpu/drm/i915
parent37808944e4d97b651de7f18a868513542de87aa0 (diff)
drm/i915: manual FDI training for Ivy Bridge
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> Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Keith Packard <keithp@keithp.com>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h10
-rw-r--r--drivers/gpu/drm/i915/intel_display.c130
2 files changed, 136 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 289adaa9c928..ea12ca01ef63 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3104,7 +3104,15 @@
3104#define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18) 3104#define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18)
3105/* Ironlake: hardwired to 1 */ 3105/* Ironlake: hardwired to 1 */
3106#define FDI_TX_PLL_ENABLE (1<<14) 3106#define FDI_TX_PLL_ENABLE (1<<14)
3107
3108/* Ivybridge has different bits for lolz */
3109#define FDI_LINK_TRAIN_PATTERN_1_IVB (0<<8)
3110#define FDI_LINK_TRAIN_PATTERN_2_IVB (1<<8)
3111#define FDI_LINK_TRAIN_PATTERN_IDLE_IVB (2<<8)
3112#define FDI_LINK_TRAIN_NONE_IVB (3<<8)
3113
3107/* both Tx and Rx */ 3114/* both Tx and Rx */
3115#define FDI_LINK_TRAIN_AUTO (1<<10)
3108#define FDI_SCRAMBLING_ENABLE (0<<7) 3116#define FDI_SCRAMBLING_ENABLE (0<<7)
3109#define FDI_SCRAMBLING_DISABLE (1<<7) 3117#define FDI_SCRAMBLING_DISABLE (1<<7)
3110 3118
@@ -3114,6 +3122,8 @@
3114#define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL) 3122#define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL)
3115#define FDI_RX_ENABLE (1<<31) 3123#define FDI_RX_ENABLE (1<<31)
3116/* train, dp width same as FDI_TX */ 3124/* train, dp width same as FDI_TX */
3125#define FDI_FS_ERRC_ENABLE (1<<27)
3126#define FDI_FE_ERRC_ENABLE (1<<26)
3117#define FDI_DP_PORT_WIDTH_X8 (7<<19) 3127#define FDI_DP_PORT_WIDTH_X8 (7<<19)
3118#define FDI_8BPC (0<<16) 3128#define FDI_8BPC (0<<16)
3119#define FDI_10BPC (1<<16) 3129#define FDI_10BPC (1<<16)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ba618d509dee..5ccd18f62e43 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2051,8 +2051,13 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
2051 /* enable normal train */ 2051 /* enable normal train */
2052 reg = FDI_TX_CTL(pipe); 2052 reg = FDI_TX_CTL(pipe);
2053 temp = I915_READ(reg); 2053 temp = I915_READ(reg);
2054 temp &= ~FDI_LINK_TRAIN_NONE; 2054 if (IS_GEN6(dev)) {
2055 temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; 2055 temp &= ~FDI_LINK_TRAIN_NONE;
2056 temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE;
2057 } else if (IS_IVYBRIDGE(dev)) {
2058 temp &= ~FDI_LINK_TRAIN_NONE_IVB;
2059 temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE;
2060 }
2056 I915_WRITE(reg, temp); 2061 I915_WRITE(reg, temp);
2057 2062
2058 reg = FDI_RX_CTL(pipe); 2063 reg = FDI_RX_CTL(pipe);
@@ -2069,6 +2074,11 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc)
2069 /* wait one idle pattern time */ 2074 /* wait one idle pattern time */
2070 POSTING_READ(reg); 2075 POSTING_READ(reg);
2071 udelay(1000); 2076 udelay(1000);
2077
2078 /* IVB wants error correction enabled */
2079 if (IS_IVYBRIDGE(dev))
2080 I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE |
2081 FDI_FE_ERRC_ENABLE);
2072} 2082}
2073 2083
2074/* The FDI link training functions for ILK/Ibexpeak. */ 2084/* The FDI link training functions for ILK/Ibexpeak. */
@@ -2296,7 +2306,116 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)
2296 DRM_DEBUG_KMS("FDI train done.\n"); 2306 DRM_DEBUG_KMS("FDI train done.\n");
2297} 2307}
2298 2308
2299static void ironlake_fdi_enable(struct drm_crtc *crtc) 2309/* Manual link training for Ivy Bridge A0 parts */
2310static void ivb_manual_fdi_link_train(struct drm_crtc *crtc)
2311{
2312 struct drm_device *dev = crtc->dev;
2313 struct drm_i915_private *dev_priv = dev->dev_private;
2314 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
2315 int pipe = intel_crtc->pipe;
2316 u32 reg, temp, i;
2317
2318 /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
2319 for train result */
2320 reg = FDI_RX_IMR(pipe);
2321 temp = I915_READ(reg);
2322 temp &= ~FDI_RX_SYMBOL_LOCK;
2323 temp &= ~FDI_RX_BIT_LOCK;
2324 I915_WRITE(reg, temp);
2325
2326 POSTING_READ(reg);
2327 udelay(150);
2328
2329 /* enable CPU FDI TX and PCH FDI RX */
2330 reg = FDI_TX_CTL(pipe);
2331 temp = I915_READ(reg);
2332 temp &= ~(7 << 19);
2333 temp |= (intel_crtc->fdi_lanes - 1) << 19;
2334 temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB);
2335 temp |= FDI_LINK_TRAIN_PATTERN_1_IVB;
2336 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
2337 temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
2338 I915_WRITE(reg, temp | FDI_TX_ENABLE);
2339
2340 reg = FDI_RX_CTL(pipe);
2341 temp = I915_READ(reg);
2342 temp &= ~FDI_LINK_TRAIN_AUTO;
2343 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
2344 temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
2345 I915_WRITE(reg, temp | FDI_RX_ENABLE);
2346
2347 POSTING_READ(reg);
2348 udelay(150);
2349
2350 for (i = 0; i < 4; i++ ) {
2351 reg = FDI_TX_CTL(pipe);
2352 temp = I915_READ(reg);
2353 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
2354 temp |= snb_b_fdi_train_param[i];
2355 I915_WRITE(reg, temp);
2356
2357 POSTING_READ(reg);
2358 udelay(500);
2359
2360 reg = FDI_RX_IIR(pipe);
2361 temp = I915_READ(reg);
2362 DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
2363
2364 if (temp & FDI_RX_BIT_LOCK ||
2365 (I915_READ(reg) & FDI_RX_BIT_LOCK)) {
2366 I915_WRITE(reg, temp | FDI_RX_BIT_LOCK);
2367 DRM_DEBUG_KMS("FDI train 1 done.\n");
2368 break;
2369 }
2370 }
2371 if (i == 4)
2372 DRM_ERROR("FDI train 1 fail!\n");
2373
2374 /* Train 2 */
2375 reg = FDI_TX_CTL(pipe);
2376 temp = I915_READ(reg);
2377 temp &= ~FDI_LINK_TRAIN_NONE_IVB;
2378 temp |= FDI_LINK_TRAIN_PATTERN_2_IVB;
2379 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
2380 temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B;
2381 I915_WRITE(reg, temp);
2382
2383 reg = FDI_RX_CTL(pipe);
2384 temp = I915_READ(reg);
2385 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
2386 temp |= FDI_LINK_TRAIN_PATTERN_2_CPT;
2387 I915_WRITE(reg, temp);
2388
2389 POSTING_READ(reg);
2390 udelay(150);
2391
2392 for (i = 0; i < 4; i++ ) {
2393 reg = FDI_TX_CTL(pipe);
2394 temp = I915_READ(reg);
2395 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK;
2396 temp |= snb_b_fdi_train_param[i];
2397 I915_WRITE(reg, temp);
2398
2399 POSTING_READ(reg);
2400 udelay(500);
2401
2402 reg = FDI_RX_IIR(pipe);
2403 temp = I915_READ(reg);
2404 DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp);
2405
2406 if (temp & FDI_RX_SYMBOL_LOCK) {
2407 I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK);
2408 DRM_DEBUG_KMS("FDI train 2 done.\n");
2409 break;
2410 }
2411 }
2412 if (i == 4)
2413 DRM_ERROR("FDI train 2 fail!\n");
2414
2415 DRM_DEBUG_KMS("FDI train done.\n");
2416}
2417
2418static void ironlake_fdi_pll_enable(struct drm_crtc *crtc)
2300{ 2419{
2301 struct drm_device *dev = crtc->dev; 2420 struct drm_device *dev = crtc->dev;
2302 struct drm_i915_private *dev_priv = dev->dev_private; 2421 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2559,7 +2678,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
2559 is_pch_port = intel_crtc_driving_pch(crtc); 2678 is_pch_port = intel_crtc_driving_pch(crtc);
2560 2679
2561 if (is_pch_port) 2680 if (is_pch_port)
2562 ironlake_fdi_enable(crtc); 2681 ironlake_fdi_pll_enable(crtc);
2563 else 2682 else
2564 ironlake_fdi_disable(crtc); 2683 ironlake_fdi_disable(crtc);
2565 2684
@@ -7438,6 +7557,9 @@ static void intel_init_display(struct drm_device *dev)
7438 dev_priv->display.update_wm = NULL; 7557 dev_priv->display.update_wm = NULL;
7439 } 7558 }
7440 dev_priv->display.fdi_link_train = gen6_fdi_link_train; 7559 dev_priv->display.fdi_link_train = gen6_fdi_link_train;
7560 } else if (IS_IVYBRIDGE(dev)) {
7561 /* FIXME: detect B0+ stepping and use auto training */
7562 dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train;
7441 } else 7563 } else
7442 dev_priv->display.update_wm = NULL; 7564 dev_priv->display.update_wm = NULL;
7443 } else if (IS_PINEVIEW(dev)) { 7565 } else if (IS_PINEVIEW(dev)) {