1 /* 2 * Copyright 2006-2018, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Alexander von Gluck IV, kallisti5@unixzen.com 8 * Adrien Destugues, pulkomandy@pulkomandy.tk 9 */ 10 11 12 #include "pll.h" 13 14 #include <math.h> 15 #include <stdio.h> 16 #include <string.h> 17 18 #include <Debug.h> 19 20 #include <create_display_modes.h> 21 #include <ddc.h> 22 #include <edid.h> 23 #include <validate_display_mode.h> 24 25 #include "accelerant_protos.h" 26 #include "accelerant.h" 27 #include "utility.h" 28 29 30 #undef TRACE 31 #define TRACE_MODE 32 #ifdef TRACE_MODE 33 # define TRACE(x...) _sPrintf("intel_extreme: " x) 34 #else 35 # define TRACE(x...) 36 #endif 37 38 #define ERROR(x...) _sPrintf("intel_extreme: " x) 39 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 40 41 42 // PLL limits, taken from programming manual when available, and from Linux KMS 43 // drivers otherwise. However, note that we use the values of N+2, M1+2 and 44 // M2+2 here, the - 2 being applied when we write the values to the registers. 45 46 static pll_limits kLimits85x = { 47 // p, p1, p2, n, m, m1, m2 48 { 4, 2, 2, 5, 96, 20, 8}, 49 {128, 33, 4, 18, 140, 28, 18}, 50 165000, 930000, 1400000 51 }; 52 53 // TODO according to the docs, the limits for 9xx anf G45 should be the same. 54 // For Iron Lake, a new set of timings is introduced along with the FDI system, 55 // and carried on to later cards with just one further change (to the P2 cutoff 56 // frequency) in Sandy Bridge. 57 // 58 // So, it makes no sense to have separate limits and algorithm for 9xx and G45. 59 60 static pll_limits kLimits9xxSdvo = { 61 // p, p1, p2, n, m, m1, m2 62 { 5, 1, 5, 5, 70, 12, 7}, // min 63 { 80, 8, 10, 10, 120, 22, 11}, // max 64 200000, 1400000, 2800000 65 }; 66 67 static pll_limits kLimits9xxLvds = { 68 // p, p1, p2, n, m, m1, m2 69 { 7, 1, 7, 1, 70, 8, 3}, // min 70 { 98, 8, 14, 6, 120, 18, 7}, // max 71 112000, 1400000, 2800000 72 }; 73 74 // Limits for G45 cards taken from g45_vlo3_register_0_0_0.pdf, page 46 75 // Note that n here is actually n+2, but m1 and m2 are as in the datasheet. 76 77 static pll_limits kLimitsG4xSdvo = { 78 // p, p1, p2, n, m, m1, m2 79 { 5, 1, 5, 5, 70, 12, 7}, // min 80 { 80, 8, 10, 10, 120, 22, 11}, // max 81 270000, 1400000, 2800000 82 }; 83 84 #if 0 85 static pll_limits kLimitsG4xHdmi = { 86 // p, p1, p2, n, m, m1, m2 87 { 5, 1, 5, 5, 70, 12, 7}, // min 88 { 80, 8, 10, 10, 120, 22, 11}, // max 89 165000, 1400000, 2800000 90 }; 91 #endif 92 93 static pll_limits kLimitsG4xLvdsSingle = { 94 // p, p1, p2, n, m, m1, m2 95 { 7, 1, 14, 5, 70, 12, 7}, // min 96 { 98, 8, 14, 10, 120, 22, 11}, // max 97 0, 1400000, 2800000 98 }; 99 100 static pll_limits kLimitsG4xLvdsDual = { 101 // p, p1, p2, n, m, m1, m2 102 { 14, 2, 7, 5, 70, 12, 7}, // min 103 { 42, 6, 7, 10, 120, 22, 11}, // max 104 0, 1400000, 2800000 105 }; 106 107 static pll_limits kLimitsIlkDac = { 108 // p, p1, p2, n, m, m1, m2 109 { 5, 1, 5, 3, 79, 14, 7}, // min 110 { 80, 8, 10, 8, 118, 24, 11}, // max 111 225000, 1760000, 3510000 112 }; 113 114 static pll_limits kLimitsIlkLvdsSingle = { 115 // p, p1, p2, n, m, m1, m2 116 { 28, 2, 14, 3, 79, 14, 7}, // min 117 {112, 8, 14, 8, 118, 24, 11}, // max 118 225000, 1760000, 3510000 119 }; 120 121 static pll_limits kLimitsIlkLvdsDual = { 122 // p, p1, p2, n, m, m1, m2 123 { 14, 2, 7, 3, 79, 14, 7}, // min 124 { 56, 8, 7, 8, 127, 24, 11}, // max 125 225000, 1760000, 3510000 126 }; 127 128 // 100Mhz RefClock 129 static pll_limits kLimitsIlkLvdsSingle100 = { 130 // p, p1, p2, n, m, m1, m2 131 { 28, 2, 14, 3, 79, 14, 7}, // min 132 {112, 8, 14, 8, 126, 24, 11}, // max 133 225000, 1760000, 3510000 134 }; 135 136 static pll_limits kLimitsIlkLvdsDual100 = { 137 // p, p1, p2, n, m, m1, m2 138 { 14, 2, 7, 3, 79, 14, 7}, // min 139 { 42, 6, 7, 8, 126, 24, 11}, // max 140 225000, 1760000, 3510000 141 }; 142 143 // TODO From haswell onwards, a completely different PLL design is used 144 // (intel_gfx-prm-osrc-hsw-display_0.pdf, page 268 for VGA). It uses a "virtual 145 // root frequency" and one just has to set a single divider (integer and 146 // fractional parts), so it makes no sense to reuse the same code and limit 147 // structures there. 148 // 149 // For other display connections, the clock is handled differently, as there is 150 // no need for a precise timing to send things in sync with the display. 151 #if 0 152 static pll_limits kLimitsChv = { 153 // p, p1, p2, n, m, m1, m2 154 { 0, 2, 1, 1, 79, 2, 24 << 22}, // min 155 { 0, 4, 14, 1, 127, 2, 175 << 22}, // max 156 0, 4800000, 6480000 157 }; 158 159 static pll_limits kLimitsVlv = { 160 // p, p1, p2, n, m, m1, m2 161 { 0, 2, 2, 1, 79, 2, 11}, // min 162 { 0, 3, 20, 7, 127, 3, 156}, // max 163 0, 4000000, 6000000 164 }; 165 166 static pll_limits kLimitsBxt = { 167 // p, p1, p2, n, m, m1, m2 168 { 0, 2, 1, 1, 0, 2, 2 << 22}, // min 169 { 0, 4, 20, 1, 0, 2, 255 << 22}, // max 170 0, 4800000, 6700000 171 }; 172 #endif 173 174 static pll_limits kLimitsPinSdvo = { 175 // p, p1, p2, n, m, m1, m2 176 { 5, 1, 5, 3, 2, 0, 0}, // min 177 { 80, 8, 10, 6, 256, 0, 254}, // max 178 200000, 1700000, 3500000 179 }; 180 181 static pll_limits kLimitsPinLvds = { 182 // p, p1, p2, n, m, m1, m2 183 { 7, 1, 14, 3, 2, 0, 0}, // min 184 {112, 8, 14, 6, 256, 0, 254}, // max 185 112000, 1700000, 3500000 186 }; 187 188 189 static bool 190 lvds_dual_link(display_mode* current) 191 { 192 float requestedPixelClock = current->timing.pixel_clock / 1000.0f; 193 if (requestedPixelClock > 112.999) 194 return true; 195 196 // TODO: Force dual link on MacBookPro6,2 MacBookPro8,2 MacBookPro9,1 197 198 return ((read32(INTEL_DIGITAL_LVDS_PORT) & LVDS_CLKB_POWER_MASK) 199 == LVDS_CLKB_POWER_UP); 200 } 201 202 203 bool 204 valid_pll_divisors(pll_divisors* divisors, pll_limits* limits) 205 { 206 pll_info &info = gInfo->shared_info->pll_info; 207 uint32 vco = info.reference_frequency * divisors->m / divisors->n; 208 uint32 frequency = vco / divisors->p; 209 210 if (divisors->p < limits->min.p || divisors->p > limits->max.p 211 || divisors->m < limits->min.m || divisors->m > limits->max.m 212 || vco < limits->min_vco || vco > limits->max_vco 213 || frequency < info.min_frequency || frequency > info.max_frequency) 214 return false; 215 216 return true; 217 } 218 219 220 static void 221 compute_pll_p2(display_mode* current, pll_divisors* divisors, 222 pll_limits* limits, bool isLVDS) 223 { 224 if (isLVDS) { 225 if (lvds_dual_link(current)) { 226 // fast DAC timing via 2 channels (dual link LVDS) 227 divisors->p2 = limits->min.p2; 228 } else { 229 // slow DAC timing 230 divisors->p2 = limits->max.p2; 231 } 232 } else { 233 if (current->timing.pixel_clock < limits->dot_limit) { 234 // slow DAC timing 235 divisors->p2 = limits->max.p2; 236 } else { 237 // fast DAC timing 238 divisors->p2 = limits->min.p2; 239 } 240 } 241 } 242 243 244 // TODO we can simplify this computation, with the way the dividers are set, we 245 // know that all values in the valid range for M are reachable. M1 allows to 246 // generate any multiple of 5 in the range and M2 allows to reach the 4 next 247 // values. Therefore, we don't need to loop over the range of values for M1 and 248 // M2 separately, we could instead just loop over possible values for M. 249 // For this to work, the logic of this function must be reversed: for a given M, 250 // it should give the resulting M1 and M2 values for programming the registers. 251 static uint32 252 compute_pll_m(pll_divisors* divisors) 253 { 254 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV) 255 || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) { 256 return divisors->m1 * divisors->m2; 257 } 258 259 // Pineview, m1 is reserved 260 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) 261 return divisors->m2; 262 263 return 5 * divisors->m1 + divisors->m2; 264 } 265 266 267 static uint32 268 compute_pll_p(pll_divisors* divisors) 269 { 270 return divisors->p1 * divisors->p2; 271 } 272 273 274 static void 275 compute_dpll_g4x(display_mode* current, pll_divisors* divisors, bool isLVDS) 276 { 277 float requestedPixelClock = current->timing.pixel_clock / 1000.0f; 278 float referenceClock 279 = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; 280 281 TRACE("%s: required MHz: %g, reference clock: %g\n", __func__, 282 requestedPixelClock, referenceClock); 283 284 pll_limits limits; 285 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x)) { 286 // TODO: Pass port type via video_configuration 287 if (isLVDS) { 288 if (lvds_dual_link(current)) 289 memcpy(&limits, &kLimitsG4xLvdsDual, sizeof(pll_limits)); 290 else 291 memcpy(&limits, &kLimitsG4xLvdsSingle, sizeof(pll_limits)); 292 //} else if (type == INTEL_PORT_TYPE_HDMI) { 293 // memcpy(&limits, &kLimitsG4xHdmi, sizeof(pll_limits)); 294 } else 295 memcpy(&limits, &kLimitsG4xSdvo, sizeof(pll_limits)); 296 } else { 297 // There must be a PCH, so this is ivy bridge or later 298 if (isLVDS) { 299 if (lvds_dual_link(current)) { 300 if (referenceClock == 100.0) 301 memcpy(&limits, &kLimitsIlkLvdsDual100, sizeof(pll_limits)); 302 else 303 memcpy(&limits, &kLimitsIlkLvdsDual, sizeof(pll_limits)); 304 } else { 305 if (referenceClock == 100.0) { 306 memcpy(&limits, &kLimitsIlkLvdsSingle100, 307 sizeof(pll_limits)); 308 } else { 309 memcpy(&limits, &kLimitsIlkLvdsSingle, sizeof(pll_limits)); 310 } 311 } 312 } else { 313 memcpy(&limits, &kLimitsIlkDac, sizeof(pll_limits)); 314 } 315 } 316 317 compute_pll_p2(current, divisors, &limits, isLVDS); 318 319 TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", " 320 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 321 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.p, 322 limits.min.p1, limits.min.p2, limits.min.n, limits.min.m, 323 limits.min.m1, limits.min.m2); 324 TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", " 325 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 326 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.p, 327 limits.max.p1, limits.max.p2, limits.max.n, limits.max.m, 328 limits.max.m1, limits.max.m2); 329 330 float best = requestedPixelClock; 331 pll_divisors bestDivisors; 332 333 for (divisors->n = limits.min.n; divisors->n <= limits.max.n; 334 divisors->n++) { 335 for (divisors->m1 = limits.max.m1; divisors->m1 >= limits.min.m1; 336 divisors->m1--) { 337 for (divisors->m2 = limits.max.m2; divisors->m2 >= limits.min.m2; 338 divisors->m2--) { 339 for (divisors->p1 = limits.max.p1; 340 divisors->p1 >= limits.min.p1; divisors->p1--) { 341 divisors->m = compute_pll_m(divisors); 342 divisors->p = compute_pll_p(divisors); 343 344 if (!valid_pll_divisors(divisors, &limits)) 345 continue; 346 347 float error = fabs(requestedPixelClock 348 - ((referenceClock * divisors->m) / divisors->n) 349 / divisors->p); 350 if (error < best) { 351 best = error; 352 bestDivisors = *divisors; 353 354 if (error == 0) 355 break; 356 } 357 } 358 } 359 } 360 } 361 *divisors = bestDivisors; 362 TRACE("%s: best MHz: %g (error: %g)\n", __func__, 363 ((referenceClock * divisors->m) / divisors->n) / divisors->p, 364 best); 365 } 366 367 368 static void 369 compute_dpll_9xx(display_mode* current, pll_divisors* divisors, bool isLVDS) 370 { 371 float requestedPixelClock = current->timing.pixel_clock / 1000.0f; 372 float referenceClock 373 = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; 374 375 TRACE("%s: required MHz: %g\n", __func__, requestedPixelClock); 376 377 pll_limits limits; 378 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN)) { 379 if (isLVDS) 380 memcpy(&limits, &kLimitsPinLvds, sizeof(pll_limits)); 381 else 382 memcpy(&limits, &kLimitsPinSdvo, sizeof(pll_limits)); 383 } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_85x)) { 384 memcpy(&limits, &kLimits85x, sizeof(pll_limits)); 385 } else { 386 if (isLVDS) 387 memcpy(&limits, &kLimits9xxLvds, sizeof(pll_limits)); 388 else 389 memcpy(&limits, &kLimits9xxSdvo, sizeof(pll_limits)); 390 } 391 392 compute_pll_p2(current, divisors, &limits, isLVDS); 393 394 TRACE("PLL limits, min: p %" B_PRId32 " (p1 %" B_PRId32 ", " 395 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 396 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.min.p, 397 limits.min.p1, limits.min.p2, limits.min.n, limits.min.m, 398 limits.min.m1, limits.min.m2); 399 TRACE("PLL limits, max: p %" B_PRId32 " (p1 %" B_PRId32 ", " 400 "p2 %" B_PRId32 "), n %" B_PRId32 ", m %" B_PRId32 " " 401 "(m1 %" B_PRId32 ", m2 %" B_PRId32 ")\n", limits.max.p, 402 limits.max.p1, limits.max.p2, limits.max.n, limits.max.m, 403 limits.max.m1, limits.max.m2); 404 405 bool is_pine = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_PIN); 406 407 float best = requestedPixelClock; 408 pll_divisors bestDivisors; 409 memset(&bestDivisors, 0, sizeof(bestDivisors)); 410 411 for (divisors->m1 = limits.min.m1; divisors->m1 <= limits.max.m1; 412 divisors->m1++) { 413 for (divisors->m2 = limits.min.m2; divisors->m2 <= limits.max.m2 414 && ((divisors->m2 < divisors->m1) || is_pine); divisors->m2++) { 415 for (divisors->n = limits.min.n; divisors->n <= limits.max.n; 416 divisors->n++) { 417 for (divisors->p1 = limits.min.p1; 418 divisors->p1 <= limits.max.p1; divisors->p1++) { 419 divisors->m = compute_pll_m(divisors); 420 divisors->p = compute_pll_p(divisors); 421 422 if (!valid_pll_divisors(divisors, &limits)) 423 continue; 424 425 float error = fabs(requestedPixelClock 426 - ((referenceClock * divisors->m) / divisors->n) 427 / divisors->p); 428 if (error < best) { 429 best = error; 430 bestDivisors = *divisors; 431 432 if (error == 0) 433 break; 434 } 435 } 436 } 437 } 438 } 439 440 *divisors = bestDivisors; 441 442 if (best == requestedPixelClock) 443 debugger("No valid PLL configuration found"); 444 else { 445 TRACE("%s: best MHz: %g (error: %g)\n", __func__, 446 ((referenceClock * divisors->m) / divisors->n) / divisors->p, 447 best); 448 } 449 } 450 451 452 void 453 compute_pll_divisors(display_mode* current, pll_divisors* divisors, bool isLVDS) 454 { 455 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x) 456 || (gInfo->shared_info->pch_info != INTEL_PCH_NONE)) { 457 compute_dpll_g4x(current, divisors, isLVDS); 458 } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) { 459 ERROR("%s: TODO: CherryView\n", __func__); 460 } else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) { 461 ERROR("%s: TODO: VallyView\n", __func__); 462 } else 463 compute_dpll_9xx(current, divisors, isLVDS); 464 465 TRACE("%s: found: p = %" B_PRId32 " (p1 = %" B_PRId32 ", " 466 "p2 = %" B_PRId32 "), n = %" B_PRId32 ", m = %" B_PRId32 " " 467 "(m1 = %" B_PRId32 ", m2 = %" B_PRId32 ")\n", __func__, 468 divisors->p, divisors->p1, divisors->p2, divisors->n, 469 divisors->m, divisors->m1, divisors->m2); 470 } 471 472 473 void 474 refclk_activate_ilk(bool hasPanel) 475 { 476 CALLED(); 477 478 // aka, our engineers hate you 479 480 bool wantsSSC; 481 bool hasCK505; 482 if (gInfo->shared_info->pch_info == INTEL_PCH_IBX) { 483 //XXX: This should be == vbt display_clock_mode 484 hasCK505 = false; 485 wantsSSC = hasCK505; 486 } else { 487 hasCK505 = false; 488 wantsSSC = true; 489 } 490 491 uint32 clkRef = read32(PCH_DREF_CONTROL); 492 uint32 newRef = clkRef; 493 494 newRef &= ~DREF_NONSPREAD_SOURCE_MASK; 495 496 if (hasCK505) 497 newRef |= DREF_NONSPREAD_CK505_ENABLE; 498 else 499 newRef |= DREF_NONSPREAD_SOURCE_ENABLE; 500 501 newRef &= ~DREF_SSC_SOURCE_MASK; 502 newRef &= ~DREF_CPU_SOURCE_OUTPUT_MASK; 503 newRef &= ~DREF_SSC1_ENABLE; 504 505 if (newRef == clkRef) { 506 TRACE("%s: No changes to reference clock.\n", __func__); 507 return; 508 } 509 510 if (hasPanel) { 511 newRef &= ~DREF_SSC_SOURCE_MASK; 512 newRef |= DREF_SSC_SOURCE_ENABLE; 513 514 if (wantsSSC) 515 newRef |= DREF_SSC1_ENABLE; 516 else 517 newRef &= ~DREF_SSC1_ENABLE; 518 519 // Power up SSC before enabling outputs 520 write32(PCH_DREF_CONTROL, newRef); 521 read32(PCH_DREF_CONTROL); 522 spin(200); 523 524 newRef &= ~DREF_CPU_SOURCE_OUTPUT_MASK; 525 526 bool hasEDP = true; 527 if (hasEDP) { 528 if (wantsSSC) 529 newRef |= DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD; 530 else 531 newRef |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD; 532 } else 533 newRef |= DREF_CPU_SOURCE_OUTPUT_DISABLE; 534 535 write32(PCH_DREF_CONTROL, newRef); 536 read32(PCH_DREF_CONTROL); 537 spin(200); 538 } else { 539 newRef &= ~DREF_CPU_SOURCE_OUTPUT_MASK; 540 newRef |= DREF_CPU_SOURCE_OUTPUT_DISABLE; 541 542 write32(PCH_DREF_CONTROL, newRef); 543 read32(PCH_DREF_CONTROL); 544 spin(200); 545 546 if (!wantsSSC) { 547 newRef &= ~DREF_SSC_SOURCE_MASK; 548 newRef |= DREF_SSC_SOURCE_DISABLE; 549 newRef &= ~DREF_SSC1_ENABLE; 550 551 write32(PCH_DREF_CONTROL, newRef); 552 read32(PCH_DREF_CONTROL); 553 spin(200); 554 } 555 } 556 } 557 558