1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2020 Intel Corporation 4 */ 5 #include "intel_atomic.h" 6 #include "intel_display_types.h" 7 #include "intel_fdi.h" 8 9 /* units of 100MHz */ 10 static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state) 11 { 12 if (crtc_state->hw.enable && crtc_state->has_pch_encoder) 13 return crtc_state->fdi_lanes; 14 15 return 0; 16 } 17 18 static int ilk_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, 19 struct intel_crtc_state *pipe_config) 20 { 21 struct drm_i915_private *dev_priv = to_i915(dev); 22 struct drm_atomic_state *state = pipe_config->uapi.state; 23 struct intel_crtc *other_crtc; 24 struct intel_crtc_state *other_crtc_state; 25 26 drm_dbg_kms(&dev_priv->drm, 27 "checking fdi config on pipe %c, lanes %i\n", 28 pipe_name(pipe), pipe_config->fdi_lanes); 29 if (pipe_config->fdi_lanes > 4) { 30 drm_dbg_kms(&dev_priv->drm, 31 "invalid fdi lane config on pipe %c: %i lanes\n", 32 pipe_name(pipe), pipe_config->fdi_lanes); 33 return -EINVAL; 34 } 35 36 if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { 37 if (pipe_config->fdi_lanes > 2) { 38 drm_dbg_kms(&dev_priv->drm, 39 "only 2 lanes on haswell, required: %i lanes\n", 40 pipe_config->fdi_lanes); 41 return -EINVAL; 42 } else { 43 return 0; 44 } 45 } 46 47 if (INTEL_NUM_PIPES(dev_priv) == 2) 48 return 0; 49 50 /* Ivybridge 3 pipe is really complicated */ 51 switch (pipe) { 52 case PIPE_A: 53 return 0; 54 case PIPE_B: 55 if (pipe_config->fdi_lanes <= 2) 56 return 0; 57 58 other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_C); 59 other_crtc_state = 60 intel_atomic_get_crtc_state(state, other_crtc); 61 if (IS_ERR(other_crtc_state)) 62 return PTR_ERR(other_crtc_state); 63 64 if (pipe_required_fdi_lanes(other_crtc_state) > 0) { 65 drm_dbg_kms(&dev_priv->drm, 66 "invalid shared fdi lane config on pipe %c: %i lanes\n", 67 pipe_name(pipe), pipe_config->fdi_lanes); 68 return -EINVAL; 69 } 70 return 0; 71 case PIPE_C: 72 if (pipe_config->fdi_lanes > 2) { 73 drm_dbg_kms(&dev_priv->drm, 74 "only 2 lanes on pipe %c: required %i lanes\n", 75 pipe_name(pipe), pipe_config->fdi_lanes); 76 return -EINVAL; 77 } 78 79 other_crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_B); 80 other_crtc_state = 81 intel_atomic_get_crtc_state(state, other_crtc); 82 if (IS_ERR(other_crtc_state)) 83 return PTR_ERR(other_crtc_state); 84 85 if (pipe_required_fdi_lanes(other_crtc_state) > 2) { 86 drm_dbg_kms(&dev_priv->drm, 87 "fdi link B uses too many lanes to enable link C\n"); 88 return -EINVAL; 89 } 90 return 0; 91 default: 92 BUG(); 93 } 94 } 95 96 int ilk_fdi_compute_config(struct intel_crtc *intel_crtc, 97 struct intel_crtc_state *pipe_config) 98 { 99 struct drm_device *dev = intel_crtc->base.dev; 100 struct drm_i915_private *i915 = to_i915(dev); 101 const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; 102 int lane, link_bw, fdi_dotclock, ret; 103 bool needs_recompute = false; 104 105 retry: 106 /* FDI is a binary signal running at ~2.7GHz, encoding 107 * each output octet as 10 bits. The actual frequency 108 * is stored as a divider into a 100MHz clock, and the 109 * mode pixel clock is stored in units of 1KHz. 110 * Hence the bw of each lane in terms of the mode signal 111 * is: 112 */ 113 link_bw = intel_fdi_link_freq(i915, pipe_config); 114 115 fdi_dotclock = adjusted_mode->crtc_clock; 116 117 lane = ilk_get_lanes_required(fdi_dotclock, link_bw, 118 pipe_config->pipe_bpp); 119 120 pipe_config->fdi_lanes = lane; 121 122 intel_link_compute_m_n(pipe_config->pipe_bpp, lane, fdi_dotclock, 123 link_bw, &pipe_config->fdi_m_n, false, false); 124 125 ret = ilk_check_fdi_lanes(dev, intel_crtc->pipe, pipe_config); 126 if (ret == -EDEADLK) 127 return ret; 128 129 if (ret == -EINVAL && pipe_config->pipe_bpp > 6*3) { 130 pipe_config->pipe_bpp -= 2*3; 131 drm_dbg_kms(&i915->drm, 132 "fdi link bw constraint, reducing pipe bpp to %i\n", 133 pipe_config->pipe_bpp); 134 needs_recompute = true; 135 pipe_config->bw_constrained = true; 136 137 goto retry; 138 } 139 140 if (needs_recompute) 141 return I915_DISPLAY_CONFIG_RETRY; 142 143 return ret; 144 } 145 146 void intel_fdi_normal_train(struct intel_crtc *crtc) 147 { 148 struct drm_device *dev = crtc->base.dev; 149 struct drm_i915_private *dev_priv = to_i915(dev); 150 enum pipe pipe = crtc->pipe; 151 i915_reg_t reg; 152 u32 temp; 153 154 /* enable normal train */ 155 reg = FDI_TX_CTL(pipe); 156 temp = intel_de_read(dev_priv, reg); 157 if (IS_IVYBRIDGE(dev_priv)) { 158 temp &= ~FDI_LINK_TRAIN_NONE_IVB; 159 temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; 160 } else { 161 temp &= ~FDI_LINK_TRAIN_NONE; 162 temp |= FDI_LINK_TRAIN_NONE | FDI_TX_ENHANCE_FRAME_ENABLE; 163 } 164 intel_de_write(dev_priv, reg, temp); 165 166 reg = FDI_RX_CTL(pipe); 167 temp = intel_de_read(dev_priv, reg); 168 if (HAS_PCH_CPT(dev_priv)) { 169 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; 170 temp |= FDI_LINK_TRAIN_NORMAL_CPT; 171 } else { 172 temp &= ~FDI_LINK_TRAIN_NONE; 173 temp |= FDI_LINK_TRAIN_NONE; 174 } 175 intel_de_write(dev_priv, reg, temp | FDI_RX_ENHANCE_FRAME_ENABLE); 176 177 /* wait one idle pattern time */ 178 intel_de_posting_read(dev_priv, reg); 179 udelay(1000); 180 181 /* IVB wants error correction enabled */ 182 if (IS_IVYBRIDGE(dev_priv)) 183 intel_de_write(dev_priv, reg, 184 intel_de_read(dev_priv, reg) | FDI_FS_ERRC_ENABLE | FDI_FE_ERRC_ENABLE); 185 } 186 187 /* The FDI link training functions for ILK/Ibexpeak. */ 188 static void ilk_fdi_link_train(struct intel_crtc *crtc, 189 const struct intel_crtc_state *crtc_state) 190 { 191 struct drm_device *dev = crtc->base.dev; 192 struct drm_i915_private *dev_priv = to_i915(dev); 193 enum pipe pipe = crtc->pipe; 194 i915_reg_t reg; 195 u32 temp, tries; 196 197 /* FDI needs bits from pipe first */ 198 assert_pipe_enabled(dev_priv, crtc_state->cpu_transcoder); 199 200 /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit 201 for train result */ 202 reg = FDI_RX_IMR(pipe); 203 temp = intel_de_read(dev_priv, reg); 204 temp &= ~FDI_RX_SYMBOL_LOCK; 205 temp &= ~FDI_RX_BIT_LOCK; 206 intel_de_write(dev_priv, reg, temp); 207 intel_de_read(dev_priv, reg); 208 udelay(150); 209 210 /* enable CPU FDI TX and PCH FDI RX */ 211 reg = FDI_TX_CTL(pipe); 212 temp = intel_de_read(dev_priv, reg); 213 temp &= ~FDI_DP_PORT_WIDTH_MASK; 214 temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes); 215 temp &= ~FDI_LINK_TRAIN_NONE; 216 temp |= FDI_LINK_TRAIN_PATTERN_1; 217 intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE); 218 219 reg = FDI_RX_CTL(pipe); 220 temp = intel_de_read(dev_priv, reg); 221 temp &= ~FDI_LINK_TRAIN_NONE; 222 temp |= FDI_LINK_TRAIN_PATTERN_1; 223 intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE); 224 225 intel_de_posting_read(dev_priv, reg); 226 udelay(150); 227 228 /* Ironlake workaround, enable clock pointer after FDI enable*/ 229 intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe), 230 FDI_RX_PHASE_SYNC_POINTER_OVR); 231 intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe), 232 FDI_RX_PHASE_SYNC_POINTER_OVR | FDI_RX_PHASE_SYNC_POINTER_EN); 233 234 reg = FDI_RX_IIR(pipe); 235 for (tries = 0; tries < 5; tries++) { 236 temp = intel_de_read(dev_priv, reg); 237 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp); 238 239 if ((temp & FDI_RX_BIT_LOCK)) { 240 drm_dbg_kms(&dev_priv->drm, "FDI train 1 done.\n"); 241 intel_de_write(dev_priv, reg, temp | FDI_RX_BIT_LOCK); 242 break; 243 } 244 } 245 if (tries == 5) 246 drm_err(&dev_priv->drm, "FDI train 1 fail!\n"); 247 248 /* Train 2 */ 249 reg = FDI_TX_CTL(pipe); 250 temp = intel_de_read(dev_priv, reg); 251 temp &= ~FDI_LINK_TRAIN_NONE; 252 temp |= FDI_LINK_TRAIN_PATTERN_2; 253 intel_de_write(dev_priv, reg, temp); 254 255 reg = FDI_RX_CTL(pipe); 256 temp = intel_de_read(dev_priv, reg); 257 temp &= ~FDI_LINK_TRAIN_NONE; 258 temp |= FDI_LINK_TRAIN_PATTERN_2; 259 intel_de_write(dev_priv, reg, temp); 260 261 intel_de_posting_read(dev_priv, reg); 262 udelay(150); 263 264 reg = FDI_RX_IIR(pipe); 265 for (tries = 0; tries < 5; tries++) { 266 temp = intel_de_read(dev_priv, reg); 267 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp); 268 269 if (temp & FDI_RX_SYMBOL_LOCK) { 270 intel_de_write(dev_priv, reg, 271 temp | FDI_RX_SYMBOL_LOCK); 272 drm_dbg_kms(&dev_priv->drm, "FDI train 2 done.\n"); 273 break; 274 } 275 } 276 if (tries == 5) 277 drm_err(&dev_priv->drm, "FDI train 2 fail!\n"); 278 279 drm_dbg_kms(&dev_priv->drm, "FDI train done\n"); 280 281 } 282 283 static const int snb_b_fdi_train_param[] = { 284 FDI_LINK_TRAIN_400MV_0DB_SNB_B, 285 FDI_LINK_TRAIN_400MV_6DB_SNB_B, 286 FDI_LINK_TRAIN_600MV_3_5DB_SNB_B, 287 FDI_LINK_TRAIN_800MV_0DB_SNB_B, 288 }; 289 290 /* The FDI link training functions for SNB/Cougarpoint. */ 291 static void gen6_fdi_link_train(struct intel_crtc *crtc, 292 const struct intel_crtc_state *crtc_state) 293 { 294 struct drm_device *dev = crtc->base.dev; 295 struct drm_i915_private *dev_priv = to_i915(dev); 296 enum pipe pipe = crtc->pipe; 297 i915_reg_t reg; 298 u32 temp, i, retry; 299 300 /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit 301 for train result */ 302 reg = FDI_RX_IMR(pipe); 303 temp = intel_de_read(dev_priv, reg); 304 temp &= ~FDI_RX_SYMBOL_LOCK; 305 temp &= ~FDI_RX_BIT_LOCK; 306 intel_de_write(dev_priv, reg, temp); 307 308 intel_de_posting_read(dev_priv, reg); 309 udelay(150); 310 311 /* enable CPU FDI TX and PCH FDI RX */ 312 reg = FDI_TX_CTL(pipe); 313 temp = intel_de_read(dev_priv, reg); 314 temp &= ~FDI_DP_PORT_WIDTH_MASK; 315 temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes); 316 temp &= ~FDI_LINK_TRAIN_NONE; 317 temp |= FDI_LINK_TRAIN_PATTERN_1; 318 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; 319 /* SNB-B */ 320 temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; 321 intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE); 322 323 intel_de_write(dev_priv, FDI_RX_MISC(pipe), 324 FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); 325 326 reg = FDI_RX_CTL(pipe); 327 temp = intel_de_read(dev_priv, reg); 328 if (HAS_PCH_CPT(dev_priv)) { 329 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; 330 temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; 331 } else { 332 temp &= ~FDI_LINK_TRAIN_NONE; 333 temp |= FDI_LINK_TRAIN_PATTERN_1; 334 } 335 intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE); 336 337 intel_de_posting_read(dev_priv, reg); 338 udelay(150); 339 340 for (i = 0; i < 4; i++) { 341 reg = FDI_TX_CTL(pipe); 342 temp = intel_de_read(dev_priv, reg); 343 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; 344 temp |= snb_b_fdi_train_param[i]; 345 intel_de_write(dev_priv, reg, temp); 346 347 intel_de_posting_read(dev_priv, reg); 348 udelay(500); 349 350 for (retry = 0; retry < 5; retry++) { 351 reg = FDI_RX_IIR(pipe); 352 temp = intel_de_read(dev_priv, reg); 353 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp); 354 if (temp & FDI_RX_BIT_LOCK) { 355 intel_de_write(dev_priv, reg, 356 temp | FDI_RX_BIT_LOCK); 357 drm_dbg_kms(&dev_priv->drm, 358 "FDI train 1 done.\n"); 359 break; 360 } 361 udelay(50); 362 } 363 if (retry < 5) 364 break; 365 } 366 if (i == 4) 367 drm_err(&dev_priv->drm, "FDI train 1 fail!\n"); 368 369 /* Train 2 */ 370 reg = FDI_TX_CTL(pipe); 371 temp = intel_de_read(dev_priv, reg); 372 temp &= ~FDI_LINK_TRAIN_NONE; 373 temp |= FDI_LINK_TRAIN_PATTERN_2; 374 if (IS_GEN(dev_priv, 6)) { 375 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; 376 /* SNB-B */ 377 temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; 378 } 379 intel_de_write(dev_priv, reg, temp); 380 381 reg = FDI_RX_CTL(pipe); 382 temp = intel_de_read(dev_priv, reg); 383 if (HAS_PCH_CPT(dev_priv)) { 384 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; 385 temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; 386 } else { 387 temp &= ~FDI_LINK_TRAIN_NONE; 388 temp |= FDI_LINK_TRAIN_PATTERN_2; 389 } 390 intel_de_write(dev_priv, reg, temp); 391 392 intel_de_posting_read(dev_priv, reg); 393 udelay(150); 394 395 for (i = 0; i < 4; i++) { 396 reg = FDI_TX_CTL(pipe); 397 temp = intel_de_read(dev_priv, reg); 398 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; 399 temp |= snb_b_fdi_train_param[i]; 400 intel_de_write(dev_priv, reg, temp); 401 402 intel_de_posting_read(dev_priv, reg); 403 udelay(500); 404 405 for (retry = 0; retry < 5; retry++) { 406 reg = FDI_RX_IIR(pipe); 407 temp = intel_de_read(dev_priv, reg); 408 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp); 409 if (temp & FDI_RX_SYMBOL_LOCK) { 410 intel_de_write(dev_priv, reg, 411 temp | FDI_RX_SYMBOL_LOCK); 412 drm_dbg_kms(&dev_priv->drm, 413 "FDI train 2 done.\n"); 414 break; 415 } 416 udelay(50); 417 } 418 if (retry < 5) 419 break; 420 } 421 if (i == 4) 422 drm_err(&dev_priv->drm, "FDI train 2 fail!\n"); 423 424 drm_dbg_kms(&dev_priv->drm, "FDI train done.\n"); 425 } 426 427 /* Manual link training for Ivy Bridge A0 parts */ 428 static void ivb_manual_fdi_link_train(struct intel_crtc *crtc, 429 const struct intel_crtc_state *crtc_state) 430 { 431 struct drm_device *dev = crtc->base.dev; 432 struct drm_i915_private *dev_priv = to_i915(dev); 433 enum pipe pipe = crtc->pipe; 434 i915_reg_t reg; 435 u32 temp, i, j; 436 437 /* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit 438 for train result */ 439 reg = FDI_RX_IMR(pipe); 440 temp = intel_de_read(dev_priv, reg); 441 temp &= ~FDI_RX_SYMBOL_LOCK; 442 temp &= ~FDI_RX_BIT_LOCK; 443 intel_de_write(dev_priv, reg, temp); 444 445 intel_de_posting_read(dev_priv, reg); 446 udelay(150); 447 448 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR before link train 0x%x\n", 449 intel_de_read(dev_priv, FDI_RX_IIR(pipe))); 450 451 /* Try each vswing and preemphasis setting twice before moving on */ 452 for (j = 0; j < ARRAY_SIZE(snb_b_fdi_train_param) * 2; j++) { 453 /* disable first in case we need to retry */ 454 reg = FDI_TX_CTL(pipe); 455 temp = intel_de_read(dev_priv, reg); 456 temp &= ~(FDI_LINK_TRAIN_AUTO | FDI_LINK_TRAIN_NONE_IVB); 457 temp &= ~FDI_TX_ENABLE; 458 intel_de_write(dev_priv, reg, temp); 459 460 reg = FDI_RX_CTL(pipe); 461 temp = intel_de_read(dev_priv, reg); 462 temp &= ~FDI_LINK_TRAIN_AUTO; 463 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; 464 temp &= ~FDI_RX_ENABLE; 465 intel_de_write(dev_priv, reg, temp); 466 467 /* enable CPU FDI TX and PCH FDI RX */ 468 reg = FDI_TX_CTL(pipe); 469 temp = intel_de_read(dev_priv, reg); 470 temp &= ~FDI_DP_PORT_WIDTH_MASK; 471 temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes); 472 temp |= FDI_LINK_TRAIN_PATTERN_1_IVB; 473 temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; 474 temp |= snb_b_fdi_train_param[j/2]; 475 temp |= FDI_COMPOSITE_SYNC; 476 intel_de_write(dev_priv, reg, temp | FDI_TX_ENABLE); 477 478 intel_de_write(dev_priv, FDI_RX_MISC(pipe), 479 FDI_RX_TP1_TO_TP2_48 | FDI_RX_FDI_DELAY_90); 480 481 reg = FDI_RX_CTL(pipe); 482 temp = intel_de_read(dev_priv, reg); 483 temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; 484 temp |= FDI_COMPOSITE_SYNC; 485 intel_de_write(dev_priv, reg, temp | FDI_RX_ENABLE); 486 487 intel_de_posting_read(dev_priv, reg); 488 udelay(1); /* should be 0.5us */ 489 490 for (i = 0; i < 4; i++) { 491 reg = FDI_RX_IIR(pipe); 492 temp = intel_de_read(dev_priv, reg); 493 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp); 494 495 if (temp & FDI_RX_BIT_LOCK || 496 (intel_de_read(dev_priv, reg) & FDI_RX_BIT_LOCK)) { 497 intel_de_write(dev_priv, reg, 498 temp | FDI_RX_BIT_LOCK); 499 drm_dbg_kms(&dev_priv->drm, 500 "FDI train 1 done, level %i.\n", 501 i); 502 break; 503 } 504 udelay(1); /* should be 0.5us */ 505 } 506 if (i == 4) { 507 drm_dbg_kms(&dev_priv->drm, 508 "FDI train 1 fail on vswing %d\n", j / 2); 509 continue; 510 } 511 512 /* Train 2 */ 513 reg = FDI_TX_CTL(pipe); 514 temp = intel_de_read(dev_priv, reg); 515 temp &= ~FDI_LINK_TRAIN_NONE_IVB; 516 temp |= FDI_LINK_TRAIN_PATTERN_2_IVB; 517 intel_de_write(dev_priv, reg, temp); 518 519 reg = FDI_RX_CTL(pipe); 520 temp = intel_de_read(dev_priv, reg); 521 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; 522 temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; 523 intel_de_write(dev_priv, reg, temp); 524 525 intel_de_posting_read(dev_priv, reg); 526 udelay(2); /* should be 1.5us */ 527 528 for (i = 0; i < 4; i++) { 529 reg = FDI_RX_IIR(pipe); 530 temp = intel_de_read(dev_priv, reg); 531 drm_dbg_kms(&dev_priv->drm, "FDI_RX_IIR 0x%x\n", temp); 532 533 if (temp & FDI_RX_SYMBOL_LOCK || 534 (intel_de_read(dev_priv, reg) & FDI_RX_SYMBOL_LOCK)) { 535 intel_de_write(dev_priv, reg, 536 temp | FDI_RX_SYMBOL_LOCK); 537 drm_dbg_kms(&dev_priv->drm, 538 "FDI train 2 done, level %i.\n", 539 i); 540 goto train_done; 541 } 542 udelay(2); /* should be 1.5us */ 543 } 544 if (i == 4) 545 drm_dbg_kms(&dev_priv->drm, 546 "FDI train 2 fail on vswing %d\n", j / 2); 547 } 548 549 train_done: 550 drm_dbg_kms(&dev_priv->drm, "FDI train done.\n"); 551 } 552 553 void ilk_fdi_pll_enable(const struct intel_crtc_state *crtc_state) 554 { 555 struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->uapi.crtc); 556 struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); 557 enum pipe pipe = intel_crtc->pipe; 558 i915_reg_t reg; 559 u32 temp; 560 561 /* enable PCH FDI RX PLL, wait warmup plus DMI latency */ 562 reg = FDI_RX_CTL(pipe); 563 temp = intel_de_read(dev_priv, reg); 564 temp &= ~(FDI_DP_PORT_WIDTH_MASK | (0x7 << 16)); 565 temp |= FDI_DP_PORT_WIDTH(crtc_state->fdi_lanes); 566 temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11; 567 intel_de_write(dev_priv, reg, temp | FDI_RX_PLL_ENABLE); 568 569 intel_de_posting_read(dev_priv, reg); 570 udelay(200); 571 572 /* Switch from Rawclk to PCDclk */ 573 temp = intel_de_read(dev_priv, reg); 574 intel_de_write(dev_priv, reg, temp | FDI_PCDCLK); 575 576 intel_de_posting_read(dev_priv, reg); 577 udelay(200); 578 579 /* Enable CPU FDI TX PLL, always on for Ironlake */ 580 reg = FDI_TX_CTL(pipe); 581 temp = intel_de_read(dev_priv, reg); 582 if ((temp & FDI_TX_PLL_ENABLE) == 0) { 583 intel_de_write(dev_priv, reg, temp | FDI_TX_PLL_ENABLE); 584 585 intel_de_posting_read(dev_priv, reg); 586 udelay(100); 587 } 588 } 589 590 void ilk_fdi_pll_disable(struct intel_crtc *intel_crtc) 591 { 592 struct drm_device *dev = intel_crtc->base.dev; 593 struct drm_i915_private *dev_priv = to_i915(dev); 594 enum pipe pipe = intel_crtc->pipe; 595 i915_reg_t reg; 596 u32 temp; 597 598 /* Switch from PCDclk to Rawclk */ 599 reg = FDI_RX_CTL(pipe); 600 temp = intel_de_read(dev_priv, reg); 601 intel_de_write(dev_priv, reg, temp & ~FDI_PCDCLK); 602 603 /* Disable CPU FDI TX PLL */ 604 reg = FDI_TX_CTL(pipe); 605 temp = intel_de_read(dev_priv, reg); 606 intel_de_write(dev_priv, reg, temp & ~FDI_TX_PLL_ENABLE); 607 608 intel_de_posting_read(dev_priv, reg); 609 udelay(100); 610 611 reg = FDI_RX_CTL(pipe); 612 temp = intel_de_read(dev_priv, reg); 613 intel_de_write(dev_priv, reg, temp & ~FDI_RX_PLL_ENABLE); 614 615 /* Wait for the clocks to turn off. */ 616 intel_de_posting_read(dev_priv, reg); 617 udelay(100); 618 } 619 620 void ilk_fdi_disable(struct intel_crtc *crtc) 621 { 622 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 623 enum pipe pipe = crtc->pipe; 624 i915_reg_t reg; 625 u32 temp; 626 627 /* disable CPU FDI tx and PCH FDI rx */ 628 reg = FDI_TX_CTL(pipe); 629 temp = intel_de_read(dev_priv, reg); 630 intel_de_write(dev_priv, reg, temp & ~FDI_TX_ENABLE); 631 intel_de_posting_read(dev_priv, reg); 632 633 reg = FDI_RX_CTL(pipe); 634 temp = intel_de_read(dev_priv, reg); 635 temp &= ~(0x7 << 16); 636 temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11; 637 intel_de_write(dev_priv, reg, temp & ~FDI_RX_ENABLE); 638 639 intel_de_posting_read(dev_priv, reg); 640 udelay(100); 641 642 /* Ironlake workaround, disable clock pointer after downing FDI */ 643 if (HAS_PCH_IBX(dev_priv)) 644 intel_de_write(dev_priv, FDI_RX_CHICKEN(pipe), 645 FDI_RX_PHASE_SYNC_POINTER_OVR); 646 647 /* still set train pattern 1 */ 648 reg = FDI_TX_CTL(pipe); 649 temp = intel_de_read(dev_priv, reg); 650 temp &= ~FDI_LINK_TRAIN_NONE; 651 temp |= FDI_LINK_TRAIN_PATTERN_1; 652 intel_de_write(dev_priv, reg, temp); 653 654 reg = FDI_RX_CTL(pipe); 655 temp = intel_de_read(dev_priv, reg); 656 if (HAS_PCH_CPT(dev_priv)) { 657 temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; 658 temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; 659 } else { 660 temp &= ~FDI_LINK_TRAIN_NONE; 661 temp |= FDI_LINK_TRAIN_PATTERN_1; 662 } 663 /* BPC in FDI rx is consistent with that in PIPECONF */ 664 temp &= ~(0x07 << 16); 665 temp |= (intel_de_read(dev_priv, PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11; 666 intel_de_write(dev_priv, reg, temp); 667 668 intel_de_posting_read(dev_priv, reg); 669 udelay(100); 670 } 671 672 void 673 intel_fdi_init_hook(struct drm_i915_private *dev_priv) 674 { 675 if (IS_GEN(dev_priv, 5)) { 676 dev_priv->display.fdi_link_train = ilk_fdi_link_train; 677 } else if (IS_GEN(dev_priv, 6)) { 678 dev_priv->display.fdi_link_train = gen6_fdi_link_train; 679 } else if (IS_IVYBRIDGE(dev_priv)) { 680 /* FIXME: detect B0+ stepping and use auto training */ 681 dev_priv->display.fdi_link_train = ivb_manual_fdi_link_train; 682 } 683 } 684