diff options
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 116 |
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 | |||
| 265 | static bool | 273 | static bool |
| 266 | intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 274 | intel_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, | |||
| 271 | static bool | 279 | static bool |
| 272 | intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 280 | intel_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); |
| 274 | static bool | ||
| 275 | intel_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 | ||
| 278 | static bool | 283 | static bool |
| 279 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, | 284 | intel_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 | ||
| 502 | static const intel_limit_t intel_limits_ironlake_lvds = { | 507 | static 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 | |||
| 522 | static 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 | ||
| 517 | static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) | 545 | static 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 | ||
| 860 | static bool | ||
| 861 | intel_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 | } | ||
| 918 | out: | ||
| 919 | return true; | ||
| 920 | } | ||
| 921 | |||
| 922 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ | 902 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ |
| 923 | static bool | 903 | static bool |
| 924 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | 904 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, |
