diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 89 |
1 files changed, 54 insertions, 35 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d1e53abec1b5..ee72807069e4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -511,8 +511,7 @@ void intel_update_fbc(struct drm_device *dev) | |||
511 | obj = intel_fb->obj; | 511 | obj = intel_fb->obj; |
512 | adjusted_mode = &intel_crtc->config.adjusted_mode; | 512 | adjusted_mode = &intel_crtc->config.adjusted_mode; |
513 | 513 | ||
514 | if (i915.enable_fbc < 0 && | 514 | if (i915.enable_fbc < 0) { |
515 | INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) { | ||
516 | if (set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT)) | 515 | if (set_no_fbc_reason(dev_priv, FBC_CHIP_DEFAULT)) |
517 | DRM_DEBUG_KMS("disabled per chip default\n"); | 516 | DRM_DEBUG_KMS("disabled per chip default\n"); |
518 | goto out_disable; | 517 | goto out_disable; |
@@ -3210,6 +3209,14 @@ void gen6_set_rps(struct drm_device *dev, u8 val) | |||
3210 | */ | 3209 | */ |
3211 | static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) | 3210 | static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) |
3212 | { | 3211 | { |
3212 | struct drm_device *dev = dev_priv->dev; | ||
3213 | |||
3214 | /* Latest VLV doesn't need to force the gfx clock */ | ||
3215 | if (dev->pdev->revision >= 0xd) { | ||
3216 | valleyview_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit); | ||
3217 | return; | ||
3218 | } | ||
3219 | |||
3213 | /* | 3220 | /* |
3214 | * When we are idle. Drop to min voltage state. | 3221 | * When we are idle. Drop to min voltage state. |
3215 | */ | 3222 | */ |
@@ -3506,15 +3513,11 @@ static void gen8_enable_rps(struct drm_device *dev) | |||
3506 | 3513 | ||
3507 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | 3514 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); |
3508 | 3515 | ||
3509 | /* WaDisablePwrmtrEvent:chv (pre-production hw) */ | ||
3510 | I915_WRITE(0xA80C, I915_READ(0xA80C) & 0x00ffffff); | ||
3511 | I915_WRITE(0xA810, I915_READ(0xA810) & 0xffffff00); | ||
3512 | |||
3513 | /* 5: Enable RPS */ | 3516 | /* 5: Enable RPS */ |
3514 | I915_WRITE(GEN6_RP_CONTROL, | 3517 | I915_WRITE(GEN6_RP_CONTROL, |
3515 | GEN6_RP_MEDIA_TURBO | | 3518 | GEN6_RP_MEDIA_TURBO | |
3516 | GEN6_RP_MEDIA_HW_NORMAL_MODE | | 3519 | GEN6_RP_MEDIA_HW_NORMAL_MODE | |
3517 | GEN6_RP_MEDIA_IS_GFX | /* WaSetMaskForGfxBusyness:chv (pre-production hw ?) */ | 3520 | GEN6_RP_MEDIA_IS_GFX | |
3518 | GEN6_RP_ENABLE | | 3521 | GEN6_RP_ENABLE | |
3519 | GEN6_RP_UP_BUSY_AVG | | 3522 | GEN6_RP_UP_BUSY_AVG | |
3520 | GEN6_RP_DOWN_IDLE_AVG); | 3523 | GEN6_RP_DOWN_IDLE_AVG); |
@@ -5608,8 +5611,8 @@ static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, | |||
5608 | (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); | 5611 | (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); |
5609 | } | 5612 | } |
5610 | 5613 | ||
5611 | bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv, | 5614 | bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv, |
5612 | enum intel_display_power_domain domain) | 5615 | enum intel_display_power_domain domain) |
5613 | { | 5616 | { |
5614 | struct i915_power_domains *power_domains; | 5617 | struct i915_power_domains *power_domains; |
5615 | struct i915_power_well *power_well; | 5618 | struct i915_power_well *power_well; |
@@ -5620,16 +5623,19 @@ bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv, | |||
5620 | return false; | 5623 | return false; |
5621 | 5624 | ||
5622 | power_domains = &dev_priv->power_domains; | 5625 | power_domains = &dev_priv->power_domains; |
5626 | |||
5623 | is_enabled = true; | 5627 | is_enabled = true; |
5628 | |||
5624 | for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { | 5629 | for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { |
5625 | if (power_well->always_on) | 5630 | if (power_well->always_on) |
5626 | continue; | 5631 | continue; |
5627 | 5632 | ||
5628 | if (!power_well->count) { | 5633 | if (!power_well->hw_enabled) { |
5629 | is_enabled = false; | 5634 | is_enabled = false; |
5630 | break; | 5635 | break; |
5631 | } | 5636 | } |
5632 | } | 5637 | } |
5638 | |||
5633 | return is_enabled; | 5639 | return is_enabled; |
5634 | } | 5640 | } |
5635 | 5641 | ||
@@ -5637,30 +5643,15 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv, | |||
5637 | enum intel_display_power_domain domain) | 5643 | enum intel_display_power_domain domain) |
5638 | { | 5644 | { |
5639 | struct i915_power_domains *power_domains; | 5645 | struct i915_power_domains *power_domains; |
5640 | struct i915_power_well *power_well; | 5646 | bool ret; |
5641 | bool is_enabled; | ||
5642 | int i; | ||
5643 | |||
5644 | if (dev_priv->pm.suspended) | ||
5645 | return false; | ||
5646 | 5647 | ||
5647 | power_domains = &dev_priv->power_domains; | 5648 | power_domains = &dev_priv->power_domains; |
5648 | 5649 | ||
5649 | is_enabled = true; | ||
5650 | |||
5651 | mutex_lock(&power_domains->lock); | 5650 | mutex_lock(&power_domains->lock); |
5652 | for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { | 5651 | ret = intel_display_power_enabled_unlocked(dev_priv, domain); |
5653 | if (power_well->always_on) | ||
5654 | continue; | ||
5655 | |||
5656 | if (!power_well->ops->is_enabled(dev_priv, power_well)) { | ||
5657 | is_enabled = false; | ||
5658 | break; | ||
5659 | } | ||
5660 | } | ||
5661 | mutex_unlock(&power_domains->lock); | 5652 | mutex_unlock(&power_domains->lock); |
5662 | 5653 | ||
5663 | return is_enabled; | 5654 | return ret; |
5664 | } | 5655 | } |
5665 | 5656 | ||
5666 | /* | 5657 | /* |
@@ -5981,6 +5972,7 @@ void intel_display_power_get(struct drm_i915_private *dev_priv, | |||
5981 | if (!power_well->count++) { | 5972 | if (!power_well->count++) { |
5982 | DRM_DEBUG_KMS("enabling %s\n", power_well->name); | 5973 | DRM_DEBUG_KMS("enabling %s\n", power_well->name); |
5983 | power_well->ops->enable(dev_priv, power_well); | 5974 | power_well->ops->enable(dev_priv, power_well); |
5975 | power_well->hw_enabled = true; | ||
5984 | } | 5976 | } |
5985 | 5977 | ||
5986 | check_power_well_state(dev_priv, power_well); | 5978 | check_power_well_state(dev_priv, power_well); |
@@ -6010,6 +6002,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, | |||
6010 | 6002 | ||
6011 | if (!--power_well->count && i915.disable_power_well) { | 6003 | if (!--power_well->count && i915.disable_power_well) { |
6012 | DRM_DEBUG_KMS("disabling %s\n", power_well->name); | 6004 | DRM_DEBUG_KMS("disabling %s\n", power_well->name); |
6005 | power_well->hw_enabled = false; | ||
6013 | power_well->ops->disable(dev_priv, power_well); | 6006 | power_well->ops->disable(dev_priv, power_well); |
6014 | } | 6007 | } |
6015 | 6008 | ||
@@ -6024,33 +6017,56 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, | |||
6024 | static struct i915_power_domains *hsw_pwr; | 6017 | static struct i915_power_domains *hsw_pwr; |
6025 | 6018 | ||
6026 | /* Display audio driver power well request */ | 6019 | /* Display audio driver power well request */ |
6027 | void i915_request_power_well(void) | 6020 | int i915_request_power_well(void) |
6028 | { | 6021 | { |
6029 | struct drm_i915_private *dev_priv; | 6022 | struct drm_i915_private *dev_priv; |
6030 | 6023 | ||
6031 | if (WARN_ON(!hsw_pwr)) | 6024 | if (!hsw_pwr) |
6032 | return; | 6025 | return -ENODEV; |
6033 | 6026 | ||
6034 | dev_priv = container_of(hsw_pwr, struct drm_i915_private, | 6027 | dev_priv = container_of(hsw_pwr, struct drm_i915_private, |
6035 | power_domains); | 6028 | power_domains); |
6036 | intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); | 6029 | intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO); |
6030 | return 0; | ||
6037 | } | 6031 | } |
6038 | EXPORT_SYMBOL_GPL(i915_request_power_well); | 6032 | EXPORT_SYMBOL_GPL(i915_request_power_well); |
6039 | 6033 | ||
6040 | /* Display audio driver power well release */ | 6034 | /* Display audio driver power well release */ |
6041 | void i915_release_power_well(void) | 6035 | int i915_release_power_well(void) |
6042 | { | 6036 | { |
6043 | struct drm_i915_private *dev_priv; | 6037 | struct drm_i915_private *dev_priv; |
6044 | 6038 | ||
6045 | if (WARN_ON(!hsw_pwr)) | 6039 | if (!hsw_pwr) |
6046 | return; | 6040 | return -ENODEV; |
6047 | 6041 | ||
6048 | dev_priv = container_of(hsw_pwr, struct drm_i915_private, | 6042 | dev_priv = container_of(hsw_pwr, struct drm_i915_private, |
6049 | power_domains); | 6043 | power_domains); |
6050 | intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); | 6044 | intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO); |
6045 | return 0; | ||
6051 | } | 6046 | } |
6052 | EXPORT_SYMBOL_GPL(i915_release_power_well); | 6047 | EXPORT_SYMBOL_GPL(i915_release_power_well); |
6053 | 6048 | ||
6049 | /* | ||
6050 | * Private interface for the audio driver to get CDCLK in kHz. | ||
6051 | * | ||
6052 | * Caller must request power well using i915_request_power_well() prior to | ||
6053 | * making the call. | ||
6054 | */ | ||
6055 | int i915_get_cdclk_freq(void) | ||
6056 | { | ||
6057 | struct drm_i915_private *dev_priv; | ||
6058 | |||
6059 | if (!hsw_pwr) | ||
6060 | return -ENODEV; | ||
6061 | |||
6062 | dev_priv = container_of(hsw_pwr, struct drm_i915_private, | ||
6063 | power_domains); | ||
6064 | |||
6065 | return intel_ddi_get_cdclk_freq(dev_priv); | ||
6066 | } | ||
6067 | EXPORT_SYMBOL_GPL(i915_get_cdclk_freq); | ||
6068 | |||
6069 | |||
6054 | #define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1) | 6070 | #define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1) |
6055 | 6071 | ||
6056 | #define HSW_ALWAYS_ON_POWER_DOMAINS ( \ | 6072 | #define HSW_ALWAYS_ON_POWER_DOMAINS ( \ |
@@ -6270,8 +6286,11 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv) | |||
6270 | int i; | 6286 | int i; |
6271 | 6287 | ||
6272 | mutex_lock(&power_domains->lock); | 6288 | mutex_lock(&power_domains->lock); |
6273 | for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) | 6289 | for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) { |
6274 | power_well->ops->sync_hw(dev_priv, power_well); | 6290 | power_well->ops->sync_hw(dev_priv, power_well); |
6291 | power_well->hw_enabled = power_well->ops->is_enabled(dev_priv, | ||
6292 | power_well); | ||
6293 | } | ||
6275 | mutex_unlock(&power_domains->lock); | 6294 | mutex_unlock(&power_domains->lock); |
6276 | } | 6295 | } |
6277 | 6296 | ||