aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2009-12-31 03:06:04 -0500
committerEric Anholt <eric@anholt.net>2010-01-06 12:40:13 -0500
commit4547668a050e7de3cd73a4c6736dfc2adebff67d (patch)
treeda6d1fe67ed8295f89caaf2e9882718c61781557 /drivers/gpu/drm/i915/intel_display.c
parente5a95eb778690bc864eb330202d2c1b974caaeb4 (diff)
drm/i915: Add DP dpll limit on ironlake and use existing DPLL search function
For some clocks, the old Ironlake DPLL calculator wold give m/n/p combinations that didn't match the spreadsheet of what HW validation tests. Instead, use the G4X DPLL calculator, which does a better job at it. So we use the intel_g4x_find_best_pll to calculate the DPLL for CRT/HDMI/LVDS on ironlake. At the same time to consider the dpll setting for display port, we add the display port DPLL limit on ironlake, which will directly use the function of intel_find_pll_ironlake_dp to get the corresponding dpll setting. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c116
1 files changed, 48 insertions, 68 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 5e2159b59920..002612fae717 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -262,6 +262,14 @@ struct intel_limit {
262#define IRONLAKE_P2_LVDS_FAST 7 /* double channel */ 262#define IRONLAKE_P2_LVDS_FAST 7 /* double channel */
263#define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */ 263#define IRONLAKE_P2_DOT_LIMIT 225000 /* 225Mhz */
264 264
265#define IRONLAKE_P_DISPLAY_PORT_MIN 10
266#define IRONLAKE_P_DISPLAY_PORT_MAX 20
267#define IRONLAKE_P2_DISPLAY_PORT_FAST 10
268#define IRONLAKE_P2_DISPLAY_PORT_SLOW 10
269#define IRONLAKE_P2_DISPLAY_PORT_LIMIT 0
270#define IRONLAKE_P1_DISPLAY_PORT_MIN 1
271#define IRONLAKE_P1_DISPLAY_PORT_MAX 2
272
265static bool 273static bool
266intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, 274intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
267 int target, int refclk, intel_clock_t *best_clock); 275 int target, int refclk, intel_clock_t *best_clock);
@@ -271,9 +279,6 @@ intel_find_best_reduced_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
271static bool 279static bool
272intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, 280intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
273 int target, int refclk, intel_clock_t *best_clock); 281 int target, int refclk, intel_clock_t *best_clock);
274static bool
275intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
276 int target, int refclk, intel_clock_t *best_clock);
277 282
278static bool 283static bool
279intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, 284intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc,
@@ -496,7 +501,7 @@ static const intel_limit_t intel_limits_ironlake_sdvo = {
496 .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, 501 .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
497 .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW, 502 .p2_slow = IRONLAKE_P2_SDVO_DAC_SLOW,
498 .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST }, 503 .p2_fast = IRONLAKE_P2_SDVO_DAC_FAST },
499 .find_pll = intel_ironlake_find_best_PLL, 504 .find_pll = intel_g4x_find_best_PLL,
500}; 505};
501 506
502static const intel_limit_t intel_limits_ironlake_lvds = { 507static const intel_limit_t intel_limits_ironlake_lvds = {
@@ -511,7 +516,30 @@ static const intel_limit_t intel_limits_ironlake_lvds = {
511 .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT, 516 .p2 = { .dot_limit = IRONLAKE_P2_DOT_LIMIT,
512 .p2_slow = IRONLAKE_P2_LVDS_SLOW, 517 .p2_slow = IRONLAKE_P2_LVDS_SLOW,
513 .p2_fast = IRONLAKE_P2_LVDS_FAST }, 518 .p2_fast = IRONLAKE_P2_LVDS_FAST },
514 .find_pll = intel_ironlake_find_best_PLL, 519 .find_pll = intel_g4x_find_best_PLL,
520};
521
522static const intel_limit_t intel_limits_ironlake_display_port = {
523 .dot = { .min = IRONLAKE_DOT_MIN,
524 .max = IRONLAKE_DOT_MAX },
525 .vco = { .min = IRONLAKE_VCO_MIN,
526 .max = IRONLAKE_VCO_MAX},
527 .n = { .min = IRONLAKE_N_MIN,
528 .max = IRONLAKE_N_MAX },
529 .m = { .min = IRONLAKE_M_MIN,
530 .max = IRONLAKE_M_MAX },
531 .m1 = { .min = IRONLAKE_M1_MIN,
532 .max = IRONLAKE_M1_MAX },
533 .m2 = { .min = IRONLAKE_M2_MIN,
534 .max = IRONLAKE_M2_MAX },
535 .p = { .min = IRONLAKE_P_DISPLAY_PORT_MIN,
536 .max = IRONLAKE_P_DISPLAY_PORT_MAX },
537 .p1 = { .min = IRONLAKE_P1_DISPLAY_PORT_MIN,
538 .max = IRONLAKE_P1_DISPLAY_PORT_MAX},
539 .p2 = { .dot_limit = IRONLAKE_P2_DISPLAY_PORT_LIMIT,
540 .p2_slow = IRONLAKE_P2_DISPLAY_PORT_SLOW,
541 .p2_fast = IRONLAKE_P2_DISPLAY_PORT_FAST },
542 .find_pll = intel_find_pll_ironlake_dp,
515}; 543};
516 544
517static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) 545static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)
@@ -519,6 +547,9 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc)
519 const intel_limit_t *limit; 547 const intel_limit_t *limit;
520 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) 548 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
521 limit = &intel_limits_ironlake_lvds; 549 limit = &intel_limits_ironlake_lvds;
550 else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
551 HAS_eDP)
552 limit = &intel_limits_ironlake_display_port;
522 else 553 else
523 limit = &intel_limits_ironlake_sdvo; 554 limit = &intel_limits_ironlake_sdvo;
524 555
@@ -791,7 +822,13 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
791 found = false; 822 found = false;
792 823
793 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { 824 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
794 if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == 825 int lvds_reg;
826
827 if (IS_IRONLAKE(dev))
828 lvds_reg = PCH_LVDS;
829 else
830 lvds_reg = LVDS;
831 if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) ==
795 LVDS_CLKB_POWER_UP) 832 LVDS_CLKB_POWER_UP)
796 clock.p2 = limit->p2.p2_fast; 833 clock.p2 = limit->p2.p2_fast;
797 else 834 else
@@ -839,6 +876,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
839{ 876{
840 struct drm_device *dev = crtc->dev; 877 struct drm_device *dev = crtc->dev;
841 intel_clock_t clock; 878 intel_clock_t clock;
879
880 /* return directly when it is eDP */
881 if (HAS_eDP)
882 return true;
883
842 if (target < 200000) { 884 if (target < 200000) {
843 clock.n = 1; 885 clock.n = 1;
844 clock.p1 = 2; 886 clock.p1 = 2;
@@ -857,68 +899,6 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
857 return true; 899 return true;
858} 900}
859 901
860static bool
861intel_ironlake_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,
862 int target, int refclk, intel_clock_t *best_clock)
863{
864 struct drm_device *dev = crtc->dev;
865 struct drm_i915_private *dev_priv = dev->dev_private;
866 intel_clock_t clock;
867 int err_most = 47;
868 int err_min = 10000;
869
870 /* eDP has only 2 clock choice, no n/m/p setting */
871 if (HAS_eDP)
872 return true;
873
874 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
875 return intel_find_pll_ironlake_dp(limit, crtc, target,
876 refclk, best_clock);
877
878 if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
879 if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) ==
880 LVDS_CLKB_POWER_UP)
881 clock.p2 = limit->p2.p2_fast;
882 else
883 clock.p2 = limit->p2.p2_slow;
884 } else {
885 if (target < limit->p2.dot_limit)
886 clock.p2 = limit->p2.p2_slow;
887 else
888 clock.p2 = limit->p2.p2_fast;
889 }
890
891 memset(best_clock, 0, sizeof(*best_clock));
892 for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) {
893 /* based on hardware requriment prefer smaller n to precision */
894 for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
895 /* based on hardware requirment prefere larger m1,m2 */
896 for (clock.m1 = limit->m1.max;
897 clock.m1 >= limit->m1.min; clock.m1--) {
898 for (clock.m2 = limit->m2.max;
899 clock.m2 >= limit->m2.min; clock.m2--) {
900 int this_err;
901
902 intel_clock(dev, refclk, &clock);
903 if (!intel_PLL_is_valid(crtc, &clock))
904 continue;
905 this_err = abs((10000 - (target*10000/clock.dot)));
906 if (this_err < err_most) {
907 *best_clock = clock;
908 /* found on first matching */
909 goto out;
910 } else if (this_err < err_min) {
911 *best_clock = clock;
912 err_min = this_err;
913 }
914 }
915 }
916 }
917 }
918out:
919 return true;
920}
921
922/* DisplayPort has only two frequencies, 162MHz and 270MHz */ 902/* DisplayPort has only two frequencies, 162MHz and 270MHz */
923static bool 903static bool
924intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, 904intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,