aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2012-06-15 14:55:13 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-06-20 08:21:23 -0400
commita0c4da24eafb32a3ce44f37b7c3412c6ffb6e37c (patch)
treeb512d984cd6e3745822640edde9fa96af8cceafd /drivers/gpu
parentcc889e0f6ce6a63c62db17d702ecfed86d58083f (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.h1
-rw-r--r--drivers/gpu/drm/i915/intel_display.c240
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
101static bool
102intel_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
101static inline u32 /* units of 100MHz */ 106static inline u32 /* units of 100MHz */
102intel_fdi_link_freq(struct drm_device *dev) 107intel_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
367static 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
381static 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
395static 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
362u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) 409u32 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
434static 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
452out_unlock:
453 spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);
454}
455
387static void vlv_init_dpio(struct drm_device *dev) 456static 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}
862static bool
863intel_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
787static void ironlake_wait_for_vblank(struct drm_device *dev, int pipe) 930static 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
3818static 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
3675static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) 3840static 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
3963static 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
3796static void i9xx_update_pll(struct drm_crtc *crtc, 4029static 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,