drm/i915: Rework DPLL calculation parameters for Ironlake

Got Ironlake DPLL parameter table, which reflects the hardware
optimized values. So this one trys to list DPLL parameters for
different output types, should potential fix clock issue seen
on new Arrandale CPUs.

This fixes DPLL setting failure on one 1920x1080 dual channel
LVDS for Ironlake. Test has also been made on LVDS panels with
smaller size and CRT/HDMI/DP ports for different monitors on
their all supported modes.

Update:
- Change name of double LVDS to dual LVDS.
- Fix SSC 120M reference clock to use the right range.

Cc: CSJ <changsijay@gmail.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>

authored by Zhenyu Wang and committed by Eric Anholt b91ad0ec e28cab42

+167 -50
+167 -50
drivers/gpu/drm/i915/intel_display.c
··· 240 240 #define IRONLAKE_DOT_MAX 350000 241 241 #define IRONLAKE_VCO_MIN 1760000 242 242 #define IRONLAKE_VCO_MAX 3510000 243 - #define IRONLAKE_N_MIN 1 244 - #define IRONLAKE_N_MAX 6 245 - #define IRONLAKE_M_MIN 79 246 - #define IRONLAKE_M_MAX 127 247 243 #define IRONLAKE_M1_MIN 12 248 244 #define IRONLAKE_M1_MAX 22 249 245 #define IRONLAKE_M2_MIN 5 250 246 #define IRONLAKE_M2_MAX 9 251 - #define IRONLAKE_P_SDVO_DAC_MIN 5 252 - #define IRONLAKE_P_SDVO_DAC_MAX 80 253 - #define IRONLAKE_P_LVDS_MIN 28 254 - #define IRONLAKE_P_LVDS_MAX 112 255 - #define IRONLAKE_P1_MIN 1 256 - #define IRONLAKE_P1_MAX 8 257 - #define IRONLAKE_P2_SDVO_DAC_SLOW 10 258 - #define IRONLAKE_P2_SDVO_DAC_FAST 5 259 - #define IRONLAKE_P2_LVDS_SLOW 14 /* single channel */ 260 - #define IRONLAKE_P2_LVDS_FAST 7 /* double channel */ 261 247 #define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */ 262 248 263 - #define IRONLAKE_P_DISPLAY_PORT_MIN 10 264 - #define IRONLAKE_P_DISPLAY_PORT_MAX 20 265 - #define IRONLAKE_P2_DISPLAY_PORT_FAST 10 266 - #define IRONLAKE_P2_DISPLAY_PORT_SLOW 10 267 - #define IRONLAKE_P2_DISPLAY_PORT_LIMIT 0 268 - #define IRONLAKE_P1_DISPLAY_PORT_MIN 1 269 - #define IRONLAKE_P1_DISPLAY_PORT_MAX 2 249 + /* We have parameter ranges for different type of outputs. */ 250 + 251 + /* DAC & HDMI Refclk 120Mhz */ 252 + #define IRONLAKE_DAC_N_MIN 1 253 + #define IRONLAKE_DAC_N_MAX 5 254 + #define IRONLAKE_DAC_M_MIN 79 255 + #define IRONLAKE_DAC_M_MAX 127 256 + #define IRONLAKE_DAC_P_MIN 5 257 + #define IRONLAKE_DAC_P_MAX 80 258 + #define IRONLAKE_DAC_P1_MIN 1 259 + #define IRONLAKE_DAC_P1_MAX 8 260 + #define IRONLAKE_DAC_P2_SLOW 10 261 + #define IRONLAKE_DAC_P2_FAST 5 262 + 263 + /* LVDS single-channel 120Mhz refclk */ 264 + #define IRONLAKE_LVDS_S_N_MIN 1 265 + #define IRONLAKE_LVDS_S_N_MAX 3 266 + #define IRONLAKE_LVDS_S_M_MIN 79 267 + #define IRONLAKE_LVDS_S_M_MAX 118 268 + #define IRONLAKE_LVDS_S_P_MIN 28 269 + #define IRONLAKE_LVDS_S_P_MAX 112 270 + #define IRONLAKE_LVDS_S_P1_MIN 2 271 + #define IRONLAKE_LVDS_S_P1_MAX 8 272 + #define IRONLAKE_LVDS_S_P2_SLOW 14 273 + #define IRONLAKE_LVDS_S_P2_FAST 14 274 + 275 + /* LVDS dual-channel 120Mhz refclk */ 276 + #define IRONLAKE_LVDS_D_N_MIN 1 277 + #define IRONLAKE_LVDS_D_N_MAX 3 278 + #define IRONLAKE_LVDS_D_M_MIN 79 279 + #define IRONLAKE_LVDS_D_M_MAX 127 280 + #define IRONLAKE_LVDS_D_P_MIN 14 281 + #define IRONLAKE_LVDS_D_P_MAX 56 282 + #define IRONLAKE_LVDS_D_P1_MIN 2 283 + #define IRONLAKE_LVDS_D_P1_MAX 8 284 + #define IRONLAKE_LVDS_D_P2_SLOW 7 285 + #define IRONLAKE_LVDS_D_P2_FAST 7 286 + 287 + /* LVDS single-channel 100Mhz refclk */ 288 + #define IRONLAKE_LVDS_S_SSC_N_MIN 1 289 + #define IRONLAKE_LVDS_S_SSC_N_MAX 2 290 + #define IRONLAKE_LVDS_S_SSC_M_MIN 79 291 + #define IRONLAKE_LVDS_S_SSC_M_MAX 126 292 + #define IRONLAKE_LVDS_S_SSC_P_MIN 28 293 + #define IRONLAKE_LVDS_S_SSC_P_MAX 112 294 + #define IRONLAKE_LVDS_S_SSC_P1_MIN 2 295 + #define IRONLAKE_LVDS_S_SSC_P1_MAX 8 296 + #define IRONLAKE_LVDS_S_SSC_P2_SLOW 14 297 + #define IRONLAKE_LVDS_S_SSC_P2_FAST 14 298 + 299 + /* LVDS dual-channel 100Mhz refclk */ 300 + #define IRONLAKE_LVDS_D_SSC_N_MIN 1 301 + #define IRONLAKE_LVDS_D_SSC_N_MAX 3 302 + #define IRONLAKE_LVDS_D_SSC_M_MIN 79 303 + #define IRONLAKE_LVDS_D_SSC_M_MAX 126 304 + #define IRONLAKE_LVDS_D_SSC_P_MIN 14 305 + #define IRONLAKE_LVDS_D_SSC_P_MAX 42 306 + #define IRONLAKE_LVDS_D_SSC_P1_MIN 2 307 + #define IRONLAKE_LVDS_D_SSC_P1_MAX 6 308 + #define IRONLAKE_LVDS_D_SSC_P2_SLOW 7 309 + #define IRONLAKE_LVDS_D_SSC_P2_FAST 7 310 + 311 + /* DisplayPort */ 312 + #define IRONLAKE_DP_N_MIN 1 313 + #define IRONLAKE_DP_N_MAX 2 314 + #define IRONLAKE_DP_M_MIN 81 315 + #define IRONLAKE_DP_M_MAX 90 316 + #define IRONLAKE_DP_P_MIN 10 317 + #define IRONLAKE_DP_P_MAX 20 318 + #define IRONLAKE_DP_P2_FAST 10 319 + #define IRONLAKE_DP_P2_SLOW 10 320 + #define IRONLAKE_DP_P2_LIMIT 0 321 + #define IRONLAKE_DP_P1_MIN 1 322 + #define IRONLAKE_DP_P1_MAX 2 270 323 271 324 static bool 272 325 intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, ··· 527 474 .find_pll = intel_find_best_PLL, 528 475 }; 529 476 530 - static const intel_limit_t intel_limits_ironlake_sdvo = { 477 + static const intel_limit_t intel_limits_ironlake_dac = { 531 478 .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, 532 479 .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, 533 - .n = { .min = IRONLAKE_N_MIN, .max = IRONLAKE_N_MAX }, 534 - .m = { .min = IRONLAKE_M_MIN, .max = IRONLAKE_M_MAX }, 480 + .n = { .min = IRONLAKE_DAC_N_MIN, .max = IRONLAKE_DAC_N_MAX }, 481 + .m = { .min = IRONLAKE_DAC_M_MIN, .max = IRONLAKE_DAC_M_MAX }, 535 482 .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, 536 483 .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, 537 - .p = { .min = IRONLAKE_P_SDVO_DAC_MIN, .max = IRONLAKE_P_SDVO_DAC_MAX }, 538 - .p1 = { .min = IRONLAKE_P1_MIN, .max = IRONLAKE_P1_MAX }, 484 + .p = { .min = IRONLAKE_DAC_P_MIN, .max = IRONLAKE_DAC_P_MAX }, 485 + .p1 = { .min = IRONLAKE_DAC_P1_MIN, .max = IRONLAKE_DAC_P1_MAX }, 539 486 .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, 540 - .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW, 541 - .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST }, 487 + .p2_slow = IRONLAKE_DAC_P2_SLOW, 488 + .p2_fast = IRONLAKE_DAC_P2_FAST }, 542 489 .find_pll = intel_g4x_find_best_PLL, 543 490 }; 544 491 545 - static const intel_limit_t intel_limits_ironlake_lvds = { 492 + static const intel_limit_t intel_limits_ironlake_single_lvds = { 546 493 .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, 547 494 .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, 548 - .n = { .min = IRONLAKE_N_MIN, .max = IRONLAKE_N_MAX }, 549 - .m = { .min = IRONLAKE_M_MIN, .max = IRONLAKE_M_MAX }, 495 + .n = { .min = IRONLAKE_LVDS_S_N_MIN, .max = IRONLAKE_LVDS_S_N_MAX }, 496 + .m = { .min = IRONLAKE_LVDS_S_M_MIN, .max = IRONLAKE_LVDS_S_M_MAX }, 550 497 .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, 551 498 .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, 552 - .p = { .min = IRONLAKE_P_LVDS_MIN, .max = IRONLAKE_P_LVDS_MAX }, 553 - .p1 = { .min = IRONLAKE_P1_MIN, .max = IRONLAKE_P1_MAX }, 499 + .p = { .min = IRONLAKE_LVDS_S_P_MIN, .max = IRONLAKE_LVDS_S_P_MAX }, 500 + .p1 = { .min = IRONLAKE_LVDS_S_P1_MIN, .max = IRONLAKE_LVDS_S_P1_MAX }, 554 501 .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, 555 - .p2_slow = IRONLAKE_P2_LVDS_SLOW, 556 - .p2_fast = IRONLAKE_P2_LVDS_FAST }, 502 + .p2_slow = IRONLAKE_LVDS_S_P2_SLOW, 503 + .p2_fast = IRONLAKE_LVDS_S_P2_FAST }, 504 + .find_pll = intel_g4x_find_best_PLL, 505 + }; 506 + 507 + static const intel_limit_t intel_limits_ironlake_dual_lvds = { 508 + .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, 509 + .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, 510 + .n = { .min = IRONLAKE_LVDS_D_N_MIN, .max = IRONLAKE_LVDS_D_N_MAX }, 511 + .m = { .min = IRONLAKE_LVDS_D_M_MIN, .max = IRONLAKE_LVDS_D_M_MAX }, 512 + .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, 513 + .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, 514 + .p = { .min = IRONLAKE_LVDS_D_P_MIN, .max = IRONLAKE_LVDS_D_P_MAX }, 515 + .p1 = { .min = IRONLAKE_LVDS_D_P1_MIN, .max = IRONLAKE_LVDS_D_P1_MAX }, 516 + .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, 517 + .p2_slow = IRONLAKE_LVDS_D_P2_SLOW, 518 + .p2_fast = IRONLAKE_LVDS_D_P2_FAST }, 519 + .find_pll = intel_g4x_find_best_PLL, 520 + }; 521 + 522 + static const intel_limit_t intel_limits_ironlake_single_lvds_100m = { 523 + .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, 524 + .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, 525 + .n = { .min = IRONLAKE_LVDS_S_SSC_N_MIN, .max = IRONLAKE_LVDS_S_SSC_N_MAX }, 526 + .m = { .min = IRONLAKE_LVDS_S_SSC_M_MIN, .max = IRONLAKE_LVDS_S_SSC_M_MAX }, 527 + .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, 528 + .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, 529 + .p = { .min = IRONLAKE_LVDS_S_SSC_P_MIN, .max = IRONLAKE_LVDS_S_SSC_P_MAX }, 530 + .p1 = { .min = IRONLAKE_LVDS_S_SSC_P1_MIN,.max = IRONLAKE_LVDS_S_SSC_P1_MAX }, 531 + .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, 532 + .p2_slow = IRONLAKE_LVDS_S_SSC_P2_SLOW, 533 + .p2_fast = IRONLAKE_LVDS_S_SSC_P2_FAST }, 534 + .find_pll = intel_g4x_find_best_PLL, 535 + }; 536 + 537 + static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = { 538 + .dot = { .min = IRONLAKE_DOT_MIN, .max = IRONLAKE_DOT_MAX }, 539 + .vco = { .min = IRONLAKE_VCO_MIN, .max = IRONLAKE_VCO_MAX }, 540 + .n = { .min = IRONLAKE_LVDS_D_SSC_N_MIN, .max = IRONLAKE_LVDS_D_SSC_N_MAX }, 541 + .m = { .min = IRONLAKE_LVDS_D_SSC_M_MIN, .max = IRONLAKE_LVDS_D_SSC_M_MAX }, 542 + .m1 = { .min = IRONLAKE_M1_MIN, .max = IRONLAKE_M1_MAX }, 543 + .m2 = { .min = IRONLAKE_M2_MIN, .max = IRONLAKE_M2_MAX }, 544 + .p = { .min = IRONLAKE_LVDS_D_SSC_P_MIN, .max = IRONLAKE_LVDS_D_SSC_P_MAX }, 545 + .p1 = { .min = IRONLAKE_LVDS_D_SSC_P1_MIN,.max = IRONLAKE_LVDS_D_SSC_P1_MAX }, 546 + .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, 547 + .p2_slow = IRONLAKE_LVDS_D_SSC_P2_SLOW, 548 + .p2_fast = IRONLAKE_LVDS_D_SSC_P2_FAST }, 557 549 .find_pll = intel_g4x_find_best_PLL, 558 550 }; 559 551 ··· 607 509 .max = IRONLAKE_DOT_MAX }, 608 510 .vco = { .min = IRONLAKE_VCO_MIN, 609 511 .max = IRONLAKE_VCO_MAX}, 610 - .n = { .min = IRONLAKE_N_MIN, 611 - .max = IRONLAKE_N_MAX }, 612 - .m = { .min = IRONLAKE_M_MIN, 613 - .max = IRONLAKE_M_MAX }, 512 + .n = { .min = IRONLAKE_DP_N_MIN, 513 + .max = IRONLAKE_DP_N_MAX }, 514 + .m = { .min = IRONLAKE_DP_M_MIN, 515 + .max = IRONLAKE_DP_M_MAX }, 614 516 .m1 = { .min = IRONLAKE_M1_MIN, 615 517 .max = IRONLAKE_M1_MAX }, 616 518 .m2 = { .min = IRONLAKE_M2_MIN, 617 519 .max = IRONLAKE_M2_MAX }, 618 - .p = { .min = IRONLAKE_P_DISPLAY_PORT_MIN, 619 - .max = IRONLAKE_P_DISPLAY_PORT_MAX }, 620 - .p1 = { .min = IRONLAKE_P1_DISPLAY_PORT_MIN, 621 - .max = IRONLAKE_P1_DISPLAY_PORT_MAX}, 622 - .p2 = { .dot_limit = IRONLAKE_P2_DISPLAY_PORT_LIMIT, 623 - .p2_slow = IRONLAKE_P2_DISPLAY_PORT_SLOW, 624 - .p2_fast = IRONLAKE_P2_DISPLAY_PORT_FAST }, 520 + .p = { .min = IRONLAKE_DP_P_MIN, 521 + .max = IRONLAKE_DP_P_MAX }, 522 + .p1 = { .min = IRONLAKE_DP_P1_MIN, 523 + .max = IRONLAKE_DP_P1_MAX}, 524 + .p2 = { .dot_limit = IRONLAKE_DP_P2_LIMIT, 525 + .p2_slow = IRONLAKE_DP_P2_SLOW, 526 + .p2_fast = IRONLAKE_DP_P2_FAST }, 625 527 .find_pll = intel_find_pll_ironlake_dp, 626 528 }; 627 529 628 530 static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) 629 531 { 532 + struct drm_device *dev = crtc->dev; 533 + struct drm_i915_private *dev_priv = dev->dev_private; 630 534 const intel_limit_t *limit; 631 - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) 632 - limit = &intel_limits_ironlake_lvds; 633 - else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || 535 + int refclk = 120; 536 + 537 + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { 538 + if (dev_priv->lvds_use_ssc && dev_priv->lvds_ssc_freq == 100) 539 + refclk = 100; 540 + 541 + if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == 542 + LVDS_CLKB_POWER_UP) { 543 + /* LVDS dual channel */ 544 + if (refclk == 100) 545 + limit = &intel_limits_ironlake_dual_lvds_100m; 546 + else 547 + limit = &intel_limits_ironlake_dual_lvds; 548 + } else { 549 + if (refclk == 100) 550 + limit = &intel_limits_ironlake_single_lvds_100m; 551 + else 552 + limit = &intel_limits_ironlake_single_lvds; 553 + } 554 + } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || 634 555 HAS_eDP) 635 556 limit = &intel_limits_ironlake_display_port; 636 557 else 637 - limit = &intel_limits_ironlake_sdvo; 558 + limit = &intel_limits_ironlake_dac; 638 559 639 560 return limit; 640 561 }