1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2021 Intel Corporation 4 */ 5 6 #include <drm/drm_print.h> 7 8 #include "intel_de.h" 9 #include "intel_display_regs.h" 10 #include "intel_display_types.h" 11 #include "intel_display_utils.h" 12 #include "intel_panel.h" 13 #include "intel_pch_refclk.h" 14 #include "intel_sbi.h" 15 #include "intel_sbi_regs.h" 16 17 static void lpt_fdi_reset_mphy(struct intel_display *display) 18 { 19 int ret; 20 21 intel_de_rmw(display, SOUTH_CHICKEN2, 0, FDI_MPHY_IOSFSB_RESET_CTL); 22 23 ret = intel_de_wait_for_set_us(display, SOUTH_CHICKEN2, 24 FDI_MPHY_IOSFSB_RESET_STATUS, 100); 25 if (ret) 26 drm_err(display->drm, "FDI mPHY reset assert timeout\n"); 27 28 intel_de_rmw(display, SOUTH_CHICKEN2, FDI_MPHY_IOSFSB_RESET_CTL, 0); 29 30 ret = intel_de_wait_for_clear_us(display, SOUTH_CHICKEN2, 31 FDI_MPHY_IOSFSB_RESET_STATUS, 100); 32 if (ret) 33 drm_err(display->drm, "FDI mPHY reset de-assert timeout\n"); 34 } 35 36 /* WaMPhyProgramming:hsw */ 37 static void lpt_fdi_program_mphy(struct intel_display *display) 38 { 39 u32 tmp; 40 41 lpt_fdi_reset_mphy(display); 42 43 tmp = intel_sbi_read(display, 0x8008, SBI_MPHY); 44 tmp &= ~(0xFF << 24); 45 tmp |= (0x12 << 24); 46 intel_sbi_write(display, 0x8008, tmp, SBI_MPHY); 47 48 tmp = intel_sbi_read(display, 0x2008, SBI_MPHY); 49 tmp |= (1 << 11); 50 intel_sbi_write(display, 0x2008, tmp, SBI_MPHY); 51 52 tmp = intel_sbi_read(display, 0x2108, SBI_MPHY); 53 tmp |= (1 << 11); 54 intel_sbi_write(display, 0x2108, tmp, SBI_MPHY); 55 56 tmp = intel_sbi_read(display, 0x206C, SBI_MPHY); 57 tmp |= (1 << 24) | (1 << 21) | (1 << 18); 58 intel_sbi_write(display, 0x206C, tmp, SBI_MPHY); 59 60 tmp = intel_sbi_read(display, 0x216C, SBI_MPHY); 61 tmp |= (1 << 24) | (1 << 21) | (1 << 18); 62 intel_sbi_write(display, 0x216C, tmp, SBI_MPHY); 63 64 tmp = intel_sbi_read(display, 0x2080, SBI_MPHY); 65 tmp &= ~(7 << 13); 66 tmp |= (5 << 13); 67 intel_sbi_write(display, 0x2080, tmp, SBI_MPHY); 68 69 tmp = intel_sbi_read(display, 0x2180, SBI_MPHY); 70 tmp &= ~(7 << 13); 71 tmp |= (5 << 13); 72 intel_sbi_write(display, 0x2180, tmp, SBI_MPHY); 73 74 tmp = intel_sbi_read(display, 0x208C, SBI_MPHY); 75 tmp &= ~0xFF; 76 tmp |= 0x1C; 77 intel_sbi_write(display, 0x208C, tmp, SBI_MPHY); 78 79 tmp = intel_sbi_read(display, 0x218C, SBI_MPHY); 80 tmp &= ~0xFF; 81 tmp |= 0x1C; 82 intel_sbi_write(display, 0x218C, tmp, SBI_MPHY); 83 84 tmp = intel_sbi_read(display, 0x2098, SBI_MPHY); 85 tmp &= ~(0xFF << 16); 86 tmp |= (0x1C << 16); 87 intel_sbi_write(display, 0x2098, tmp, SBI_MPHY); 88 89 tmp = intel_sbi_read(display, 0x2198, SBI_MPHY); 90 tmp &= ~(0xFF << 16); 91 tmp |= (0x1C << 16); 92 intel_sbi_write(display, 0x2198, tmp, SBI_MPHY); 93 94 tmp = intel_sbi_read(display, 0x20C4, SBI_MPHY); 95 tmp |= (1 << 27); 96 intel_sbi_write(display, 0x20C4, tmp, SBI_MPHY); 97 98 tmp = intel_sbi_read(display, 0x21C4, SBI_MPHY); 99 tmp |= (1 << 27); 100 intel_sbi_write(display, 0x21C4, tmp, SBI_MPHY); 101 102 tmp = intel_sbi_read(display, 0x20EC, SBI_MPHY); 103 tmp &= ~(0xF << 28); 104 tmp |= (4 << 28); 105 intel_sbi_write(display, 0x20EC, tmp, SBI_MPHY); 106 107 tmp = intel_sbi_read(display, 0x21EC, SBI_MPHY); 108 tmp &= ~(0xF << 28); 109 tmp |= (4 << 28); 110 intel_sbi_write(display, 0x21EC, tmp, SBI_MPHY); 111 } 112 113 void lpt_disable_iclkip(struct intel_display *display) 114 { 115 u32 temp; 116 117 intel_de_write(display, PIXCLK_GATE, PIXCLK_GATE_GATE); 118 119 intel_sbi_lock(display); 120 121 temp = intel_sbi_read(display, SBI_SSCCTL6, SBI_ICLK); 122 temp |= SBI_SSCCTL_DISABLE; 123 intel_sbi_write(display, SBI_SSCCTL6, temp, SBI_ICLK); 124 125 intel_sbi_unlock(display); 126 } 127 128 struct iclkip_params { 129 u32 iclk_virtual_root_freq; 130 u32 iclk_pi_range; 131 u32 divsel, phaseinc, auxdiv, phasedir, desired_divisor; 132 }; 133 134 static void iclkip_params_init(struct iclkip_params *p) 135 { 136 memset(p, 0, sizeof(*p)); 137 138 p->iclk_virtual_root_freq = 172800 * 1000; 139 p->iclk_pi_range = 64; 140 } 141 142 static int lpt_iclkip_freq(struct iclkip_params *p) 143 { 144 return DIV_ROUND_CLOSEST(p->iclk_virtual_root_freq, 145 p->desired_divisor << p->auxdiv); 146 } 147 148 static void lpt_compute_iclkip(struct iclkip_params *p, int clock) 149 { 150 iclkip_params_init(p); 151 152 /* The iCLK virtual clock root frequency is in MHz, 153 * but the adjusted_mode->crtc_clock in KHz. To get the 154 * divisors, it is necessary to divide one by another, so we 155 * convert the virtual clock precision to KHz here for higher 156 * precision. 157 */ 158 for (p->auxdiv = 0; p->auxdiv < 2; p->auxdiv++) { 159 p->desired_divisor = DIV_ROUND_CLOSEST(p->iclk_virtual_root_freq, 160 clock << p->auxdiv); 161 p->divsel = (p->desired_divisor / p->iclk_pi_range) - 2; 162 p->phaseinc = p->desired_divisor % p->iclk_pi_range; 163 164 /* 165 * Near 20MHz is a corner case which is 166 * out of range for the 7-bit divisor 167 */ 168 if (p->divsel <= 0x7f) 169 break; 170 } 171 } 172 173 int lpt_iclkip(const struct intel_crtc_state *crtc_state) 174 { 175 struct iclkip_params p; 176 177 lpt_compute_iclkip(&p, crtc_state->hw.adjusted_mode.crtc_clock); 178 179 return lpt_iclkip_freq(&p); 180 } 181 182 /* Program iCLKIP clock to the desired frequency */ 183 void lpt_program_iclkip(const struct intel_crtc_state *crtc_state) 184 { 185 struct intel_display *display = to_intel_display(crtc_state); 186 int clock = crtc_state->hw.adjusted_mode.crtc_clock; 187 struct iclkip_params p; 188 u32 temp; 189 190 lpt_disable_iclkip(display); 191 192 lpt_compute_iclkip(&p, clock); 193 drm_WARN_ON(display->drm, lpt_iclkip_freq(&p) != clock); 194 195 /* This should not happen with any sane values */ 196 drm_WARN_ON(display->drm, SBI_SSCDIVINTPHASE_DIVSEL(p.divsel) & 197 ~SBI_SSCDIVINTPHASE_DIVSEL_MASK); 198 drm_WARN_ON(display->drm, SBI_SSCDIVINTPHASE_DIR(p.phasedir) & 199 ~SBI_SSCDIVINTPHASE_INCVAL_MASK); 200 201 drm_dbg_kms(display->drm, 202 "iCLKIP clock: found settings for %dKHz refresh rate: auxdiv=%x, divsel=%x, phasedir=%x, phaseinc=%x\n", 203 clock, p.auxdiv, p.divsel, p.phasedir, p.phaseinc); 204 205 intel_sbi_lock(display); 206 207 /* Program SSCDIVINTPHASE6 */ 208 temp = intel_sbi_read(display, SBI_SSCDIVINTPHASE6, SBI_ICLK); 209 temp &= ~SBI_SSCDIVINTPHASE_DIVSEL_MASK; 210 temp |= SBI_SSCDIVINTPHASE_DIVSEL(p.divsel); 211 temp &= ~SBI_SSCDIVINTPHASE_INCVAL_MASK; 212 temp |= SBI_SSCDIVINTPHASE_INCVAL(p.phaseinc); 213 temp |= SBI_SSCDIVINTPHASE_DIR(p.phasedir); 214 temp |= SBI_SSCDIVINTPHASE_PROPAGATE; 215 intel_sbi_write(display, SBI_SSCDIVINTPHASE6, temp, SBI_ICLK); 216 217 /* Program SSCAUXDIV */ 218 temp = intel_sbi_read(display, SBI_SSCAUXDIV6, SBI_ICLK); 219 temp &= ~SBI_SSCAUXDIV_FINALDIV2SEL(1); 220 temp |= SBI_SSCAUXDIV_FINALDIV2SEL(p.auxdiv); 221 intel_sbi_write(display, SBI_SSCAUXDIV6, temp, SBI_ICLK); 222 223 /* Enable modulator and associated divider */ 224 temp = intel_sbi_read(display, SBI_SSCCTL6, SBI_ICLK); 225 temp &= ~SBI_SSCCTL_DISABLE; 226 intel_sbi_write(display, SBI_SSCCTL6, temp, SBI_ICLK); 227 228 intel_sbi_unlock(display); 229 230 /* Wait for initialization time */ 231 udelay(24); 232 233 intel_de_write(display, PIXCLK_GATE, PIXCLK_GATE_UNGATE); 234 } 235 236 int lpt_get_iclkip(struct intel_display *display) 237 { 238 struct iclkip_params p; 239 u32 temp; 240 241 if ((intel_de_read(display, PIXCLK_GATE) & PIXCLK_GATE_UNGATE) == 0) 242 return 0; 243 244 iclkip_params_init(&p); 245 246 intel_sbi_lock(display); 247 248 temp = intel_sbi_read(display, SBI_SSCCTL6, SBI_ICLK); 249 if (temp & SBI_SSCCTL_DISABLE) { 250 intel_sbi_unlock(display); 251 return 0; 252 } 253 254 temp = intel_sbi_read(display, SBI_SSCDIVINTPHASE6, SBI_ICLK); 255 p.divsel = (temp & SBI_SSCDIVINTPHASE_DIVSEL_MASK) >> 256 SBI_SSCDIVINTPHASE_DIVSEL_SHIFT; 257 p.phaseinc = (temp & SBI_SSCDIVINTPHASE_INCVAL_MASK) >> 258 SBI_SSCDIVINTPHASE_INCVAL_SHIFT; 259 260 temp = intel_sbi_read(display, SBI_SSCAUXDIV6, SBI_ICLK); 261 p.auxdiv = (temp & SBI_SSCAUXDIV_FINALDIV2SEL_MASK) >> 262 SBI_SSCAUXDIV_FINALDIV2SEL_SHIFT; 263 264 intel_sbi_unlock(display); 265 266 p.desired_divisor = (p.divsel + 2) * p.iclk_pi_range + p.phaseinc; 267 268 return lpt_iclkip_freq(&p); 269 } 270 271 /* Implements 3 different sequences from BSpec chapter "Display iCLK 272 * Programming" based on the parameters passed: 273 * - Sequence to enable CLKOUT_DP 274 * - Sequence to enable CLKOUT_DP without spread 275 * - Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O 276 */ 277 static void lpt_enable_clkout_dp(struct intel_display *display, 278 bool with_spread, bool with_fdi) 279 { 280 u32 reg, tmp; 281 282 if (drm_WARN(display->drm, with_fdi && !with_spread, 283 "FDI requires downspread\n")) 284 with_spread = true; 285 if (drm_WARN(display->drm, HAS_PCH_LPT_LP(display) && 286 with_fdi, "LP PCH doesn't have FDI\n")) 287 with_fdi = false; 288 289 intel_sbi_lock(display); 290 291 tmp = intel_sbi_read(display, SBI_SSCCTL, SBI_ICLK); 292 tmp &= ~SBI_SSCCTL_DISABLE; 293 tmp |= SBI_SSCCTL_PATHALT; 294 intel_sbi_write(display, SBI_SSCCTL, tmp, SBI_ICLK); 295 296 udelay(24); 297 298 if (with_spread) { 299 tmp = intel_sbi_read(display, SBI_SSCCTL, SBI_ICLK); 300 tmp &= ~SBI_SSCCTL_PATHALT; 301 intel_sbi_write(display, SBI_SSCCTL, tmp, SBI_ICLK); 302 303 if (with_fdi) 304 lpt_fdi_program_mphy(display); 305 } 306 307 reg = HAS_PCH_LPT_LP(display) ? SBI_GEN0 : SBI_DBUFF0; 308 tmp = intel_sbi_read(display, reg, SBI_ICLK); 309 tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; 310 intel_sbi_write(display, reg, tmp, SBI_ICLK); 311 312 intel_sbi_unlock(display); 313 } 314 315 /* Sequence to disable CLKOUT_DP */ 316 void lpt_disable_clkout_dp(struct intel_display *display) 317 { 318 u32 reg, tmp; 319 320 intel_sbi_lock(display); 321 322 reg = HAS_PCH_LPT_LP(display) ? SBI_GEN0 : SBI_DBUFF0; 323 tmp = intel_sbi_read(display, reg, SBI_ICLK); 324 tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; 325 intel_sbi_write(display, reg, tmp, SBI_ICLK); 326 327 tmp = intel_sbi_read(display, SBI_SSCCTL, SBI_ICLK); 328 if (!(tmp & SBI_SSCCTL_DISABLE)) { 329 if (!(tmp & SBI_SSCCTL_PATHALT)) { 330 tmp |= SBI_SSCCTL_PATHALT; 331 intel_sbi_write(display, SBI_SSCCTL, tmp, SBI_ICLK); 332 udelay(32); 333 } 334 tmp |= SBI_SSCCTL_DISABLE; 335 intel_sbi_write(display, SBI_SSCCTL, tmp, SBI_ICLK); 336 } 337 338 intel_sbi_unlock(display); 339 } 340 341 #define BEND_IDX(steps) ((50 + (steps)) / 5) 342 343 static const u16 sscdivintphase[] = { 344 [BEND_IDX( 50)] = 0x3B23, 345 [BEND_IDX( 45)] = 0x3B23, 346 [BEND_IDX( 40)] = 0x3C23, 347 [BEND_IDX( 35)] = 0x3C23, 348 [BEND_IDX( 30)] = 0x3D23, 349 [BEND_IDX( 25)] = 0x3D23, 350 [BEND_IDX( 20)] = 0x3E23, 351 [BEND_IDX( 15)] = 0x3E23, 352 [BEND_IDX( 10)] = 0x3F23, 353 [BEND_IDX( 5)] = 0x3F23, 354 [BEND_IDX( 0)] = 0x0025, 355 [BEND_IDX( -5)] = 0x0025, 356 [BEND_IDX(-10)] = 0x0125, 357 [BEND_IDX(-15)] = 0x0125, 358 [BEND_IDX(-20)] = 0x0225, 359 [BEND_IDX(-25)] = 0x0225, 360 [BEND_IDX(-30)] = 0x0325, 361 [BEND_IDX(-35)] = 0x0325, 362 [BEND_IDX(-40)] = 0x0425, 363 [BEND_IDX(-45)] = 0x0425, 364 [BEND_IDX(-50)] = 0x0525, 365 }; 366 367 /* 368 * Bend CLKOUT_DP 369 * steps -50 to 50 inclusive, in steps of 5 370 * < 0 slow down the clock, > 0 speed up the clock, 0 == no bend (135MHz) 371 * change in clock period = -(steps / 10) * 5.787 ps 372 */ 373 static void lpt_bend_clkout_dp(struct intel_display *display, int steps) 374 { 375 u32 tmp; 376 int idx = BEND_IDX(steps); 377 378 if (drm_WARN_ON(display->drm, steps % 5 != 0)) 379 return; 380 381 if (drm_WARN_ON(display->drm, idx >= ARRAY_SIZE(sscdivintphase))) 382 return; 383 384 intel_sbi_lock(display); 385 386 if (steps % 10 != 0) 387 tmp = 0xAAAAAAAB; 388 else 389 tmp = 0x00000000; 390 intel_sbi_write(display, SBI_SSCDITHPHASE, tmp, SBI_ICLK); 391 392 tmp = intel_sbi_read(display, SBI_SSCDIVINTPHASE, SBI_ICLK); 393 tmp &= 0xffff0000; 394 tmp |= sscdivintphase[idx]; 395 intel_sbi_write(display, SBI_SSCDIVINTPHASE, tmp, SBI_ICLK); 396 397 intel_sbi_unlock(display); 398 } 399 400 #undef BEND_IDX 401 402 static bool spll_uses_pch_ssc(struct intel_display *display) 403 { 404 u32 fuse_strap = intel_de_read(display, FUSE_STRAP); 405 u32 ctl = intel_de_read(display, SPLL_CTL); 406 407 if ((ctl & SPLL_PLL_ENABLE) == 0) 408 return false; 409 410 if ((ctl & SPLL_REF_MASK) == SPLL_REF_MUXED_SSC && 411 (fuse_strap & HSW_CPU_SSC_ENABLE) == 0) 412 return true; 413 414 if (display->platform.broadwell && 415 (ctl & SPLL_REF_MASK) == SPLL_REF_PCH_SSC_BDW) 416 return true; 417 418 return false; 419 } 420 421 static bool wrpll_uses_pch_ssc(struct intel_display *display, enum intel_dpll_id id) 422 { 423 u32 fuse_strap = intel_de_read(display, FUSE_STRAP); 424 u32 ctl = intel_de_read(display, WRPLL_CTL(id)); 425 426 if ((ctl & WRPLL_PLL_ENABLE) == 0) 427 return false; 428 429 if ((ctl & WRPLL_REF_MASK) == WRPLL_REF_PCH_SSC) 430 return true; 431 432 if ((display->platform.broadwell || display->platform.haswell_ult) && 433 (ctl & WRPLL_REF_MASK) == WRPLL_REF_MUXED_SSC_BDW && 434 (fuse_strap & HSW_CPU_SSC_ENABLE) == 0) 435 return true; 436 437 return false; 438 } 439 440 static void lpt_init_pch_refclk(struct intel_display *display) 441 { 442 struct intel_encoder *encoder; 443 bool has_fdi = false; 444 445 for_each_intel_encoder(display->drm, encoder) { 446 switch (encoder->type) { 447 case INTEL_OUTPUT_ANALOG: 448 has_fdi = true; 449 break; 450 default: 451 break; 452 } 453 } 454 455 /* 456 * The BIOS may have decided to use the PCH SSC 457 * reference so we must not disable it until the 458 * relevant PLLs have stopped relying on it. We'll 459 * just leave the PCH SSC reference enabled in case 460 * any active PLL is using it. It will get disabled 461 * after runtime suspend if we don't have FDI. 462 * 463 * TODO: Move the whole reference clock handling 464 * to the modeset sequence proper so that we can 465 * actually enable/disable/reconfigure these things 466 * safely. To do that we need to introduce a real 467 * clock hierarchy. That would also allow us to do 468 * clock bending finally. 469 */ 470 display->dpll.pch_ssc_use = 0; 471 472 if (spll_uses_pch_ssc(display)) { 473 drm_dbg_kms(display->drm, "SPLL using PCH SSC\n"); 474 display->dpll.pch_ssc_use |= BIT(DPLL_ID_SPLL); 475 } 476 477 if (wrpll_uses_pch_ssc(display, DPLL_ID_WRPLL1)) { 478 drm_dbg_kms(display->drm, "WRPLL1 using PCH SSC\n"); 479 display->dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL1); 480 } 481 482 if (wrpll_uses_pch_ssc(display, DPLL_ID_WRPLL2)) { 483 drm_dbg_kms(display->drm, "WRPLL2 using PCH SSC\n"); 484 display->dpll.pch_ssc_use |= BIT(DPLL_ID_WRPLL2); 485 } 486 487 if (display->dpll.pch_ssc_use) 488 return; 489 490 if (has_fdi) { 491 lpt_bend_clkout_dp(display, 0); 492 lpt_enable_clkout_dp(display, true, true); 493 } else { 494 lpt_disable_clkout_dp(display); 495 } 496 } 497 498 static void ilk_init_pch_refclk(struct intel_display *display) 499 { 500 struct intel_encoder *encoder; 501 struct intel_dpll *pll; 502 int i; 503 u32 val, final; 504 bool has_lvds = false; 505 bool has_cpu_edp = false; 506 bool has_panel = false; 507 bool has_ck505 = false; 508 bool can_ssc = false; 509 bool using_ssc_source = false; 510 511 /* We need to take the global config into account */ 512 for_each_intel_encoder(display->drm, encoder) { 513 switch (encoder->type) { 514 case INTEL_OUTPUT_LVDS: 515 has_panel = true; 516 has_lvds = true; 517 break; 518 case INTEL_OUTPUT_EDP: 519 has_panel = true; 520 if (encoder->port == PORT_A) 521 has_cpu_edp = true; 522 break; 523 default: 524 break; 525 } 526 } 527 528 if (HAS_PCH_IBX(display)) { 529 has_ck505 = display->vbt.display_clock_mode; 530 can_ssc = has_ck505; 531 } else { 532 has_ck505 = false; 533 can_ssc = true; 534 } 535 536 /* Check if any DPLLs are using the SSC source */ 537 for_each_dpll(display, pll, i) { 538 u32 temp; 539 540 temp = intel_de_read(display, PCH_DPLL(pll->info->id)); 541 542 if (!(temp & DPLL_VCO_ENABLE)) 543 continue; 544 545 if ((temp & PLL_REF_INPUT_MASK) == 546 PLLB_REF_INPUT_SPREADSPECTRUMIN) { 547 using_ssc_source = true; 548 break; 549 } 550 } 551 552 drm_dbg_kms(display->drm, 553 "has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n", 554 has_panel, has_lvds, has_ck505, using_ssc_source); 555 556 /* Ironlake: try to setup display ref clock before DPLL 557 * enabling. This is only under driver's control after 558 * PCH B stepping, previous chipset stepping should be 559 * ignoring this setting. 560 */ 561 val = intel_de_read(display, PCH_DREF_CONTROL); 562 563 /* As we must carefully and slowly disable/enable each source in turn, 564 * compute the final state we want first and check if we need to 565 * make any changes at all. 566 */ 567 final = val; 568 final &= ~DREF_NONSPREAD_SOURCE_MASK; 569 if (has_ck505) 570 final |= DREF_NONSPREAD_CK505_ENABLE; 571 else 572 final |= DREF_NONSPREAD_SOURCE_ENABLE; 573 574 final &= ~DREF_SSC_SOURCE_MASK; 575 final &= ~DREF_CPU_SOURCE_OUTPUT_MASK; 576 final &= ~DREF_SSC1_ENABLE; 577 578 if (has_panel) { 579 final |= DREF_SSC_SOURCE_ENABLE; 580 581 if (intel_panel_use_ssc(display) && can_ssc) 582 final |= DREF_SSC1_ENABLE; 583 584 if (has_cpu_edp) { 585 if (intel_panel_use_ssc(display) && can_ssc) 586 final |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; 587 else 588 final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; 589 } else { 590 final |= DREF_CPU_SOURCE_OUTPUT_DISABLE; 591 } 592 } else if (using_ssc_source) { 593 final |= DREF_SSC_SOURCE_ENABLE; 594 final |= DREF_SSC1_ENABLE; 595 } 596 597 if (final == val) 598 return; 599 600 /* Always enable nonspread source */ 601 val &= ~DREF_NONSPREAD_SOURCE_MASK; 602 603 if (has_ck505) 604 val |= DREF_NONSPREAD_CK505_ENABLE; 605 else 606 val |= DREF_NONSPREAD_SOURCE_ENABLE; 607 608 if (has_panel) { 609 val &= ~DREF_SSC_SOURCE_MASK; 610 val |= DREF_SSC_SOURCE_ENABLE; 611 612 /* SSC must be turned on before enabling the CPU output */ 613 if (intel_panel_use_ssc(display) && can_ssc) { 614 drm_dbg_kms(display->drm, "Using SSC on panel\n"); 615 val |= DREF_SSC1_ENABLE; 616 } else { 617 val &= ~DREF_SSC1_ENABLE; 618 } 619 620 /* Get SSC going before enabling the outputs */ 621 intel_de_write(display, PCH_DREF_CONTROL, val); 622 intel_de_posting_read(display, PCH_DREF_CONTROL); 623 udelay(200); 624 625 val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; 626 627 /* Enable CPU source on CPU attached eDP */ 628 if (has_cpu_edp) { 629 if (intel_panel_use_ssc(display) && can_ssc) { 630 drm_dbg_kms(display->drm, 631 "Using SSC on eDP\n"); 632 val |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; 633 } else { 634 val |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; 635 } 636 } else { 637 val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; 638 } 639 640 intel_de_write(display, PCH_DREF_CONTROL, val); 641 intel_de_posting_read(display, PCH_DREF_CONTROL); 642 udelay(200); 643 } else { 644 drm_dbg_kms(display->drm, "Disabling CPU source output\n"); 645 646 val &= ~DREF_CPU_SOURCE_OUTPUT_MASK; 647 648 /* Turn off CPU output */ 649 val |= DREF_CPU_SOURCE_OUTPUT_DISABLE; 650 651 intel_de_write(display, PCH_DREF_CONTROL, val); 652 intel_de_posting_read(display, PCH_DREF_CONTROL); 653 udelay(200); 654 655 if (!using_ssc_source) { 656 drm_dbg_kms(display->drm, "Disabling SSC source\n"); 657 658 /* Turn off the SSC source */ 659 val &= ~DREF_SSC_SOURCE_MASK; 660 val |= DREF_SSC_SOURCE_DISABLE; 661 662 /* Turn off SSC1 */ 663 val &= ~DREF_SSC1_ENABLE; 664 665 intel_de_write(display, PCH_DREF_CONTROL, val); 666 intel_de_posting_read(display, PCH_DREF_CONTROL); 667 udelay(200); 668 } 669 } 670 671 drm_WARN_ON(display->drm, val != final); 672 } 673 674 /* 675 * Initialize reference clocks when the driver loads 676 */ 677 void intel_init_pch_refclk(struct intel_display *display) 678 { 679 if (HAS_PCH_IBX(display) || HAS_PCH_CPT(display)) 680 ilk_init_pch_refclk(display); 681 else if (HAS_PCH_LPT(display)) 682 lpt_init_pch_refclk(display); 683 } 684