aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_pm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c85
1 files changed, 63 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 13a0666a53b4..e34ad9642519 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2558,8 +2558,8 @@ static void gen6_enable_rps(struct drm_device *dev)
2558 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); 2558 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
2559 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); 2559 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
2560 2560
2561 /* In units of 100MHz */ 2561 /* In units of 50MHz */
2562 dev_priv->rps.max_delay = rp_state_cap & 0xff; 2562 dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff;
2563 dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16; 2563 dev_priv->rps.min_delay = (rp_state_cap & 0xff0000) >> 16;
2564 dev_priv->rps.cur_delay = 0; 2564 dev_priv->rps.cur_delay = 0;
2565 2565
@@ -2643,10 +2643,10 @@ static void gen6_enable_rps(struct drm_device *dev)
2643 pcu_mbox = 0; 2643 pcu_mbox = 0;
2644 ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox); 2644 ret = sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, &pcu_mbox);
2645 if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */ 2645 if (!ret && (pcu_mbox & (1<<31))) { /* OC supported */
2646 DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max from %dMHz to %dMHz\n", 2646 DRM_DEBUG_DRIVER("Overclocking supported. Max: %dMHz, Overclock max: %dMHz\n",
2647 (dev_priv->rps.max_delay & 0xff) * 50, 2647 (dev_priv->rps.max_delay & 0xff) * 50,
2648 (pcu_mbox & 0xff) * 50); 2648 (pcu_mbox & 0xff) * 50);
2649 dev_priv->rps.max_delay = pcu_mbox & 0xff; 2649 dev_priv->rps.hw_max = pcu_mbox & 0xff;
2650 } 2650 }
2651 } else { 2651 } else {
2652 DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); 2652 DRM_DEBUG_DRIVER("Failed to set the min frequency\n");
@@ -2684,8 +2684,8 @@ static void gen6_update_ring_freq(struct drm_device *dev)
2684{ 2684{
2685 struct drm_i915_private *dev_priv = dev->dev_private; 2685 struct drm_i915_private *dev_priv = dev->dev_private;
2686 int min_freq = 15; 2686 int min_freq = 15;
2687 int gpu_freq; 2687 unsigned int gpu_freq;
2688 unsigned int ia_freq, max_ia_freq; 2688 unsigned int max_ia_freq, min_ring_freq;
2689 int scaling_factor = 180; 2689 int scaling_factor = 180;
2690 2690
2691 WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); 2691 WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
@@ -2701,6 +2701,10 @@ static void gen6_update_ring_freq(struct drm_device *dev)
2701 /* Convert from kHz to MHz */ 2701 /* Convert from kHz to MHz */
2702 max_ia_freq /= 1000; 2702 max_ia_freq /= 1000;
2703 2703
2704 min_ring_freq = I915_READ(MCHBAR_MIRROR_BASE_SNB + DCLK);
2705 /* convert DDR frequency from units of 133.3MHz to bandwidth */
2706 min_ring_freq = (2 * 4 * min_ring_freq + 2) / 3;
2707
2704 /* 2708 /*
2705 * For each potential GPU frequency, load a ring frequency we'd like 2709 * For each potential GPU frequency, load a ring frequency we'd like
2706 * to use for memory access. We do this by specifying the IA frequency 2710 * to use for memory access. We do this by specifying the IA frequency
@@ -2709,21 +2713,32 @@ static void gen6_update_ring_freq(struct drm_device *dev)
2709 for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay; 2713 for (gpu_freq = dev_priv->rps.max_delay; gpu_freq >= dev_priv->rps.min_delay;
2710 gpu_freq--) { 2714 gpu_freq--) {
2711 int diff = dev_priv->rps.max_delay - gpu_freq; 2715 int diff = dev_priv->rps.max_delay - gpu_freq;
2712 2716 unsigned int ia_freq = 0, ring_freq = 0;
2713 /* 2717
2714 * For GPU frequencies less than 750MHz, just use the lowest 2718 if (IS_HASWELL(dev)) {
2715 * ring freq. 2719 ring_freq = (gpu_freq * 5 + 3) / 4;
2716 */ 2720 ring_freq = max(min_ring_freq, ring_freq);
2717 if (gpu_freq < min_freq) 2721 /* leave ia_freq as the default, chosen by cpufreq */
2718 ia_freq = 800; 2722 } else {
2719 else 2723 /* On older processors, there is no separate ring
2720 ia_freq = max_ia_freq - ((diff * scaling_factor) / 2); 2724 * clock domain, so in order to boost the bandwidth
2721 ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100); 2725 * of the ring, we need to upclock the CPU (ia_freq).
2722 ia_freq <<= GEN6_PCODE_FREQ_IA_RATIO_SHIFT; 2726 *
2727 * For GPU frequencies less than 750MHz,
2728 * just use the lowest ring freq.
2729 */
2730 if (gpu_freq < min_freq)
2731 ia_freq = 800;
2732 else
2733 ia_freq = max_ia_freq - ((diff * scaling_factor) / 2);
2734 ia_freq = DIV_ROUND_CLOSEST(ia_freq, 100);
2735 }
2723 2736
2724 sandybridge_pcode_write(dev_priv, 2737 sandybridge_pcode_write(dev_priv,
2725 GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 2738 GEN6_PCODE_WRITE_MIN_FREQ_TABLE,
2726 ia_freq | gpu_freq); 2739 ia_freq << GEN6_PCODE_FREQ_IA_RATIO_SHIFT |
2740 ring_freq << GEN6_PCODE_FREQ_RING_RATIO_SHIFT |
2741 gpu_freq);
2727 } 2742 }
2728} 2743}
2729 2744
@@ -3575,6 +3590,7 @@ static void cpt_init_clock_gating(struct drm_device *dev)
3575{ 3590{
3576 struct drm_i915_private *dev_priv = dev->dev_private; 3591 struct drm_i915_private *dev_priv = dev->dev_private;
3577 int pipe; 3592 int pipe;
3593 uint32_t val;
3578 3594
3579 /* 3595 /*
3580 * On Ibex Peak and Cougar Point, we need to disable clock 3596 * On Ibex Peak and Cougar Point, we need to disable clock
@@ -3587,8 +3603,17 @@ static void cpt_init_clock_gating(struct drm_device *dev)
3587 /* The below fixes the weird display corruption, a few pixels shifted 3603 /* The below fixes the weird display corruption, a few pixels shifted
3588 * downward, on (only) LVDS of some HP laptops with IVY. 3604 * downward, on (only) LVDS of some HP laptops with IVY.
3589 */ 3605 */
3590 for_each_pipe(pipe) 3606 for_each_pipe(pipe) {
3591 I915_WRITE(TRANS_CHICKEN2(pipe), TRANS_CHICKEN2_TIMING_OVERRIDE); 3607 val = I915_READ(TRANS_CHICKEN2(pipe));
3608 val |= TRANS_CHICKEN2_TIMING_OVERRIDE;
3609 val &= ~TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
3610 if (dev_priv->fdi_rx_polarity_inverted)
3611 val |= TRANS_CHICKEN2_FDI_POLARITY_REVERSED;
3612 val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK;
3613 val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_COUNTER;
3614 val &= ~TRANS_CHICKEN2_DISABLE_DEEP_COLOR_MODESWITCH;
3615 I915_WRITE(TRANS_CHICKEN2(pipe), val);
3616 }
3592 /* WADP0ClockGatingDisable */ 3617 /* WADP0ClockGatingDisable */
3593 for_each_pipe(pipe) { 3618 for_each_pipe(pipe) {
3594 I915_WRITE(TRANS_CHICKEN1(pipe), 3619 I915_WRITE(TRANS_CHICKEN1(pipe),
@@ -3890,7 +3915,8 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
3890 snpcr |= GEN6_MBC_SNPCR_MED; 3915 snpcr |= GEN6_MBC_SNPCR_MED;
3891 I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); 3916 I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr);
3892 3917
3893 cpt_init_clock_gating(dev); 3918 if (!HAS_PCH_NOP(dev))
3919 cpt_init_clock_gating(dev);
3894 3920
3895 gen6_check_mch_setup(dev); 3921 gen6_check_mch_setup(dev);
3896} 3922}
@@ -4084,6 +4110,22 @@ void intel_init_clock_gating(struct drm_device *dev)
4084 dev_priv->display.init_clock_gating(dev); 4110 dev_priv->display.init_clock_gating(dev);
4085} 4111}
4086 4112
4113/**
4114 * We should only use the power well if we explicitly asked the hardware to
4115 * enable it, so check if it's enabled and also check if we've requested it to
4116 * be enabled.
4117 */
4118bool intel_using_power_well(struct drm_device *dev)
4119{
4120 struct drm_i915_private *dev_priv = dev->dev_private;
4121
4122 if (IS_HASWELL(dev))
4123 return I915_READ(HSW_PWR_WELL_DRIVER) ==
4124 (HSW_PWR_WELL_ENABLE | HSW_PWR_WELL_STATE);
4125 else
4126 return true;
4127}
4128
4087void intel_set_power_well(struct drm_device *dev, bool enable) 4129void intel_set_power_well(struct drm_device *dev, bool enable)
4088{ 4130{
4089 struct drm_i915_private *dev_priv = dev->dev_private; 4131 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -4190,7 +4232,6 @@ void intel_init_pm(struct drm_device *dev)
4190 } 4232 }
4191 dev_priv->display.init_clock_gating = gen6_init_clock_gating; 4233 dev_priv->display.init_clock_gating = gen6_init_clock_gating;
4192 } else if (IS_IVYBRIDGE(dev)) { 4234 } else if (IS_IVYBRIDGE(dev)) {
4193 /* FIXME: detect B0+ stepping and use auto training */
4194 if (SNB_READ_WM0_LATENCY()) { 4235 if (SNB_READ_WM0_LATENCY()) {
4195 dev_priv->display.update_wm = ivybridge_update_wm; 4236 dev_priv->display.update_wm = ivybridge_update_wm;
4196 dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm; 4237 dev_priv->display.update_sprite_wm = sandybridge_update_sprite_wm;