diff options
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 130 |
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 | ||
2299 | static void ironlake_fdi_enable(struct drm_crtc *crtc) | 2309 | /* Manual link training for Ivy Bridge A0 parts */ |
2310 | static 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 | |||
2418 | static 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)) { |