diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2012-06-15 14:55:13 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-06-20 08:21:23 -0400 |
commit | a0c4da24eafb32a3ce44f37b7c3412c6ffb6e37c (patch) | |
tree | b512d984cd6e3745822640edde9fa96af8cceafd /drivers/gpu | |
parent | cc889e0f6ce6a63c62db17d702ecfed86d58083f (diff) |
drm/i915: ValleyView mode setting limits and PLL functions
Add some VLV limit structures and update the PLL code.
v2: resolve conflicts, Vijay to re-post with PLL valid checks and fixed limits
v3: re-add dpio write function
v4: squash in Vijay's fixes for the PLL limits and clean up the m/n finder
Signed-off-by: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Vijay Purushothaman <vijay.a.purushothaman@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 240 |
2 files changed, 239 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 782e5d1dc218..b6f5f1040d77 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -904,6 +904,7 @@ | |||
904 | #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ | 904 | #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ |
905 | #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ | 905 | #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ |
906 | #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ | 906 | #define DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW 0x00ff8000 /* Pineview */ |
907 | #define DPLL_LOCK_VLV (1<<15) | ||
907 | #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) | 908 | #define DPLL_INTEGRATED_CLOCK_VLV (1<<13) |
908 | 909 | ||
909 | #define SRX_INDEX 0x3c4 | 910 | #define SRX_INDEX 0x3c4 |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 97301621f48a..7794c1a630c0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -98,6 +98,11 @@ intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, | |||
98 | int target, int refclk, intel_clock_t *match_clock, | 98 | int target, int refclk, intel_clock_t *match_clock, |
99 | intel_clock_t *best_clock); | 99 | intel_clock_t *best_clock); |
100 | 100 | ||
101 | static bool | ||
102 | intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
103 | int target, int refclk, intel_clock_t *match_clock, | ||
104 | intel_clock_t *best_clock); | ||
105 | |||
101 | static inline u32 /* units of 100MHz */ | 106 | static inline u32 /* units of 100MHz */ |
102 | intel_fdi_link_freq(struct drm_device *dev) | 107 | intel_fdi_link_freq(struct drm_device *dev) |
103 | { | 108 | { |
@@ -359,6 +364,48 @@ static const intel_limit_t intel_limits_ironlake_display_port = { | |||
359 | .find_pll = intel_find_pll_ironlake_dp, | 364 | .find_pll = intel_find_pll_ironlake_dp, |
360 | }; | 365 | }; |
361 | 366 | ||
367 | static const intel_limit_t intel_limits_vlv_dac = { | ||
368 | .dot = { .min = 25000, .max = 270000 }, | ||
369 | .vco = { .min = 4000000, .max = 6000000 }, | ||
370 | .n = { .min = 1, .max = 7 }, | ||
371 | .m = { .min = 22, .max = 450 }, /* guess */ | ||
372 | .m1 = { .min = 2, .max = 3 }, | ||
373 | .m2 = { .min = 11, .max = 156 }, | ||
374 | .p = { .min = 10, .max = 30 }, | ||
375 | .p1 = { .min = 2, .max = 3 }, | ||
376 | .p2 = { .dot_limit = 270000, | ||
377 | .p2_slow = 2, .p2_fast = 20 }, | ||
378 | .find_pll = intel_vlv_find_best_pll, | ||
379 | }; | ||
380 | |||
381 | static const intel_limit_t intel_limits_vlv_hdmi = { | ||
382 | .dot = { .min = 20000, .max = 165000 }, | ||
383 | .vco = { .min = 5994000, .max = 4000000 }, | ||
384 | .n = { .min = 1, .max = 7 }, | ||
385 | .m = { .min = 60, .max = 300 }, /* guess */ | ||
386 | .m1 = { .min = 2, .max = 3 }, | ||
387 | .m2 = { .min = 11, .max = 156 }, | ||
388 | .p = { .min = 10, .max = 30 }, | ||
389 | .p1 = { .min = 2, .max = 3 }, | ||
390 | .p2 = { .dot_limit = 270000, | ||
391 | .p2_slow = 2, .p2_fast = 20 }, | ||
392 | .find_pll = intel_vlv_find_best_pll, | ||
393 | }; | ||
394 | |||
395 | static const intel_limit_t intel_limits_vlv_dp = { | ||
396 | .dot = { .min = 162000, .max = 270000 }, | ||
397 | .vco = { .min = 5994000, .max = 4000000 }, | ||
398 | .n = { .min = 1, .max = 7 }, | ||
399 | .m = { .min = 60, .max = 300 }, /* guess */ | ||
400 | .m1 = { .min = 2, .max = 3 }, | ||
401 | .m2 = { .min = 11, .max = 156 }, | ||
402 | .p = { .min = 10, .max = 30 }, | ||
403 | .p1 = { .min = 2, .max = 3 }, | ||
404 | .p2 = { .dot_limit = 270000, | ||
405 | .p2_slow = 2, .p2_fast = 20 }, | ||
406 | .find_pll = intel_vlv_find_best_pll, | ||
407 | }; | ||
408 | |||
362 | u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) | 409 | u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) |
363 | { | 410 | { |
364 | unsigned long flags; | 411 | unsigned long flags; |
@@ -384,6 +431,28 @@ out_unlock: | |||
384 | return val; | 431 | return val; |
385 | } | 432 | } |
386 | 433 | ||
434 | static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, | ||
435 | u32 val) | ||
436 | { | ||
437 | unsigned long flags; | ||
438 | |||
439 | spin_lock_irqsave(&dev_priv->dpio_lock, flags); | ||
440 | if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) { | ||
441 | DRM_ERROR("DPIO idle wait timed out\n"); | ||
442 | goto out_unlock; | ||
443 | } | ||
444 | |||
445 | I915_WRITE(DPIO_DATA, val); | ||
446 | I915_WRITE(DPIO_REG, reg); | ||
447 | I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID | | ||
448 | DPIO_BYTE); | ||
449 | if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) | ||
450 | DRM_ERROR("DPIO write wait timed out\n"); | ||
451 | |||
452 | out_unlock: | ||
453 | spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); | ||
454 | } | ||
455 | |||
387 | static void vlv_init_dpio(struct drm_device *dev) | 456 | static void vlv_init_dpio(struct drm_device *dev) |
388 | { | 457 | { |
389 | struct drm_i915_private *dev_priv = dev->dev_private; | 458 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -510,6 +579,13 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) | |||
510 | limit = &intel_limits_pineview_lvds; | 579 | limit = &intel_limits_pineview_lvds; |
511 | else | 580 | else |
512 | limit = &intel_limits_pineview_sdvo; | 581 | limit = &intel_limits_pineview_sdvo; |
582 | } else if (IS_VALLEYVIEW(dev)) { | ||
583 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) | ||
584 | limit = &intel_limits_vlv_dac; | ||
585 | else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) | ||
586 | limit = &intel_limits_vlv_hdmi; | ||
587 | else | ||
588 | limit = &intel_limits_vlv_dp; | ||
513 | } else if (!IS_GEN2(dev)) { | 589 | } else if (!IS_GEN2(dev)) { |
514 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 590 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
515 | limit = &intel_limits_i9xx_lvds; | 591 | limit = &intel_limits_i9xx_lvds; |
@@ -783,6 +859,73 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | |||
783 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | 859 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); |
784 | return true; | 860 | return true; |
785 | } | 861 | } |
862 | static bool | ||
863 | intel_vlv_find_best_pll(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
864 | int target, int refclk, intel_clock_t *match_clock, | ||
865 | intel_clock_t *best_clock) | ||
866 | { | ||
867 | u32 p1, p2, m1, m2, vco, bestn, bestm1, bestm2, bestp1, bestp2; | ||
868 | u32 m, n, fastclk; | ||
869 | u32 updrate, minupdate, fracbits, p; | ||
870 | unsigned long bestppm, ppm, absppm; | ||
871 | int dotclk, flag; | ||
872 | |||
873 | dotclk = target * 1000; | ||
874 | bestppm = 1000000; | ||
875 | ppm = absppm = 0; | ||
876 | fastclk = dotclk / (2*100); | ||
877 | updrate = 0; | ||
878 | minupdate = 19200; | ||
879 | fracbits = 1; | ||
880 | n = p = p1 = p2 = m = m1 = m2 = vco = bestn = 0; | ||
881 | bestm1 = bestm2 = bestp1 = bestp2 = 0; | ||
882 | |||
883 | /* based on hardware requirement, prefer smaller n to precision */ | ||
884 | for (n = limit->n.min; n <= ((refclk) / minupdate); n++) { | ||
885 | updrate = refclk / n; | ||
886 | for (p1 = limit->p1.max; p1 > limit->p1.min; p1--) { | ||
887 | for (p2 = limit->p2.p2_fast+1; p2 > 0; p2--) { | ||
888 | if (p2 > 10) | ||
889 | p2 = p2 - 1; | ||
890 | p = p1 * p2; | ||
891 | /* based on hardware requirement, prefer bigger m1,m2 values */ | ||
892 | for (m1 = limit->m1.min; m1 <= limit->m1.max; m1++) { | ||
893 | m2 = (((2*(fastclk * p * n / m1 )) + | ||
894 | refclk) / (2*refclk)); | ||
895 | m = m1 * m2; | ||
896 | vco = updrate * m; | ||
897 | if (vco >= limit->vco.min && vco < limit->vco.max) { | ||
898 | ppm = 1000000 * ((vco / p) - fastclk) / fastclk; | ||
899 | absppm = (ppm > 0) ? ppm : (-ppm); | ||
900 | if (absppm < 100 && ((p1 * p2) > (bestp1 * bestp2))) { | ||
901 | bestppm = 0; | ||
902 | flag = 1; | ||
903 | } | ||
904 | if (absppm < bestppm - 10) { | ||
905 | bestppm = absppm; | ||
906 | flag = 1; | ||
907 | } | ||
908 | if (flag) { | ||
909 | bestn = n; | ||
910 | bestm1 = m1; | ||
911 | bestm2 = m2; | ||
912 | bestp1 = p1; | ||
913 | bestp2 = p2; | ||
914 | flag = 0; | ||
915 | } | ||
916 | } | ||
917 | } | ||
918 | } | ||
919 | } | ||
920 | } | ||
921 | best_clock->n = bestn; | ||
922 | best_clock->m1 = bestm1; | ||
923 | best_clock->m2 = bestm2; | ||
924 | best_clock->p1 = bestp1; | ||
925 | best_clock->p2 = bestp2; | ||
926 | |||
927 | return true; | ||
928 | } | ||
786 | 929 | ||
787 | static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) | 930 | static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) |
788 | { | 931 | { |
@@ -1293,7 +1436,7 @@ static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) | |||
1293 | u32 val; | 1436 | u32 val; |
1294 | 1437 | ||
1295 | /* No really, not for ILK+ */ | 1438 | /* No really, not for ILK+ */ |
1296 | BUG_ON(dev_priv->info->gen >= 5); | 1439 | BUG_ON(!IS_VALLEYVIEW(dev_priv->dev) && dev_priv->info->gen >= 5); |
1297 | 1440 | ||
1298 | /* PLL is protected by panel, make sure we can write it */ | 1441 | /* PLL is protected by panel, make sure we can write it */ |
1299 | if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) | 1442 | if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev)) |
@@ -3672,13 +3815,37 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, | |||
3672 | return display_bpc != bpc; | 3815 | return display_bpc != bpc; |
3673 | } | 3816 | } |
3674 | 3817 | ||
3818 | static int vlv_get_refclk(struct drm_crtc *crtc) | ||
3819 | { | ||
3820 | struct drm_device *dev = crtc->dev; | ||
3821 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3822 | int refclk = 27000; /* for DP & HDMI */ | ||
3823 | |||
3824 | return 100000; /* only one validated so far */ | ||
3825 | |||
3826 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { | ||
3827 | refclk = 96000; | ||
3828 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { | ||
3829 | if (intel_panel_use_ssc(dev_priv)) | ||
3830 | refclk = 100000; | ||
3831 | else | ||
3832 | refclk = 96000; | ||
3833 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { | ||
3834 | refclk = 100000; | ||
3835 | } | ||
3836 | |||
3837 | return refclk; | ||
3838 | } | ||
3839 | |||
3675 | static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) | 3840 | static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) |
3676 | { | 3841 | { |
3677 | struct drm_device *dev = crtc->dev; | 3842 | struct drm_device *dev = crtc->dev; |
3678 | struct drm_i915_private *dev_priv = dev->dev_private; | 3843 | struct drm_i915_private *dev_priv = dev->dev_private; |
3679 | int refclk; | 3844 | int refclk; |
3680 | 3845 | ||
3681 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | 3846 | if (IS_VALLEYVIEW(dev)) { |
3847 | refclk = vlv_get_refclk(crtc); | ||
3848 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | ||
3682 | intel_panel_use_ssc(dev_priv) && num_connectors < 2) { | 3849 | intel_panel_use_ssc(dev_priv) && num_connectors < 2) { |
3683 | refclk = dev_priv->lvds_ssc_freq * 1000; | 3850 | refclk = dev_priv->lvds_ssc_freq * 1000; |
3684 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", | 3851 | DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", |
@@ -3793,6 +3960,72 @@ static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock, | |||
3793 | I915_WRITE(LVDS, temp); | 3960 | I915_WRITE(LVDS, temp); |
3794 | } | 3961 | } |
3795 | 3962 | ||
3963 | static void vlv_update_pll(struct drm_crtc *crtc, | ||
3964 | struct drm_display_mode *mode, | ||
3965 | struct drm_display_mode *adjusted_mode, | ||
3966 | intel_clock_t *clock, intel_clock_t *reduced_clock, | ||
3967 | int refclk, int num_connectors) | ||
3968 | { | ||
3969 | struct drm_device *dev = crtc->dev; | ||
3970 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3971 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
3972 | int pipe = intel_crtc->pipe; | ||
3973 | u32 dpll, mdiv, pdiv; | ||
3974 | u32 bestn, bestm1, bestm2, bestp1, bestp2; | ||
3975 | bool is_hdmi; | ||
3976 | |||
3977 | is_hdmi = intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI); | ||
3978 | |||
3979 | bestn = clock->n; | ||
3980 | bestm1 = clock->m1; | ||
3981 | bestm2 = clock->m2; | ||
3982 | bestp1 = clock->p1; | ||
3983 | bestp2 = clock->p2; | ||
3984 | |||
3985 | /* Enable DPIO clock input */ | ||
3986 | dpll = DPLL_EXT_BUFFER_ENABLE_VLV | DPLL_REFA_CLK_ENABLE_VLV | | ||
3987 | DPLL_VGA_MODE_DIS | DPLL_INTEGRATED_CLOCK_VLV; | ||
3988 | I915_WRITE(DPLL(pipe), dpll); | ||
3989 | POSTING_READ(DPLL(pipe)); | ||
3990 | |||
3991 | mdiv = ((bestm1 << DPIO_M1DIV_SHIFT) | (bestm2 & DPIO_M2DIV_MASK)); | ||
3992 | mdiv |= ((bestp1 << DPIO_P1_SHIFT) | (bestp2 << DPIO_P2_SHIFT)); | ||
3993 | mdiv |= ((bestn << DPIO_N_SHIFT)); | ||
3994 | mdiv |= (1 << DPIO_POST_DIV_SHIFT); | ||
3995 | mdiv |= (1 << DPIO_K_SHIFT); | ||
3996 | mdiv |= DPIO_ENABLE_CALIBRATION; | ||
3997 | intel_dpio_write(dev_priv, DPIO_DIV(pipe), mdiv); | ||
3998 | |||
3999 | intel_dpio_write(dev_priv, DPIO_CORE_CLK(pipe), 0x01000000); | ||
4000 | |||
4001 | pdiv = DPIO_REFSEL_OVERRIDE | (5 << DPIO_PLL_MODESEL_SHIFT) | | ||
4002 | (3 << DPIO_BIAS_CURRENT_CTL_SHIFT) | (1<<20) | | ||
4003 | (8 << DPIO_DRIVER_CTL_SHIFT) | (5 << DPIO_CLK_BIAS_CTL_SHIFT); | ||
4004 | intel_dpio_write(dev_priv, DPIO_REFSFR(pipe), pdiv); | ||
4005 | |||
4006 | intel_dpio_write(dev_priv, DPIO_LFP_COEFF(pipe), 0x009f0051); | ||
4007 | |||
4008 | dpll |= DPLL_VCO_ENABLE; | ||
4009 | I915_WRITE(DPLL(pipe), dpll); | ||
4010 | POSTING_READ(DPLL(pipe)); | ||
4011 | if (wait_for(((I915_READ(DPLL(pipe)) & DPLL_LOCK_VLV) == DPLL_LOCK_VLV), 1)) | ||
4012 | DRM_ERROR("DPLL %d failed to lock\n", pipe); | ||
4013 | |||
4014 | if (is_hdmi) { | ||
4015 | u32 temp = intel_mode_get_pixel_multiplier(adjusted_mode); | ||
4016 | |||
4017 | if (temp > 1) | ||
4018 | temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; | ||
4019 | else | ||
4020 | temp = 0; | ||
4021 | |||
4022 | I915_WRITE(DPLL_MD(pipe), temp); | ||
4023 | POSTING_READ(DPLL_MD(pipe)); | ||
4024 | } | ||
4025 | |||
4026 | intel_dpio_write(dev_priv, DPIO_FASTCLK_DISABLE, 0x641); /* ??? */ | ||
4027 | } | ||
4028 | |||
3796 | static void i9xx_update_pll(struct drm_crtc *crtc, | 4029 | static void i9xx_update_pll(struct drm_crtc *crtc, |
3797 | struct drm_display_mode *mode, | 4030 | struct drm_display_mode *mode, |
3798 | struct drm_display_mode *adjusted_mode, | 4031 | struct drm_display_mode *adjusted_mode, |
@@ -4050,6 +4283,9 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, | |||
4050 | 4283 | ||
4051 | if (IS_GEN2(dev)) | 4284 | if (IS_GEN2(dev)) |
4052 | i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors); | 4285 | i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors); |
4286 | else if (IS_VALLEYVIEW(dev)) | ||
4287 | vlv_update_pll(crtc, mode,adjusted_mode, &clock, NULL, | ||
4288 | refclk, num_connectors); | ||
4053 | else | 4289 | else |
4054 | i9xx_update_pll(crtc, mode, adjusted_mode, &clock, | 4290 | i9xx_update_pll(crtc, mode, adjusted_mode, &clock, |
4055 | has_reduced_clock ? &reduced_clock : NULL, | 4291 | has_reduced_clock ? &reduced_clock : NULL, |