diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 85 |
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 | */ | ||
4118 | bool 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 | |||
4087 | void intel_set_power_well(struct drm_device *dev, bool enable) | 4129 | void 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; |