aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2014-06-05 13:31:47 -0400
committerJani Nikula <jani.nikula@intel.com>2014-06-23 03:02:03 -0400
commitbfafe93a1cd466ef318b7e5f6c65f59aee147791 (patch)
tree35ba06381f0cb31c9ed37c0216c98b7e8d739677
parenta497c3ba1d97fc69c1e78e7b96435ba8c2cb42ee (diff)
drm/i915: cache hw power well enabled state
Jesse noticed that the punit communication needed to query the VLV power well status can cause substantial delays. Since we can query the state frequently, for example during I2C transfers, maintain a cached version of the HW state to get rid of this delay. This fixes at least one reported regression where boot time increased by ~4 seconds due to frequent power well state queries on VLV during eDP EDID read. This regression has been introduced in commit bb4932c4f17b68f34645ffbcf845e4c29d17290b Author: Imre Deak <imre.deak@intel.com> Date: Mon Apr 14 20:24:33 2014 +0300 drm/i915: vlv: check port power domain instead of only D0 for eDP VDD on Reported-by: Jesse Barnes <jesse.barnes@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_display.c6
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c37
4 files changed, 22 insertions, 27 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 49414d30e8d4..a47fbf60b781 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -977,6 +977,8 @@ struct i915_power_well {
977 bool always_on; 977 bool always_on;
978 /* power well enable/disable usage count */ 978 /* power well enable/disable usage count */
979 int count; 979 int count;
980 /* cached hw enabled state */
981 bool hw_enabled;
980 unsigned long domains; 982 unsigned long domains;
981 unsigned long data; 983 unsigned long data;
982 const struct i915_power_well_ops *ops; 984 const struct i915_power_well_ops *ops;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index efd3cf50cb0f..9188fede99ef 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12411,8 +12411,8 @@ intel_display_capture_error_state(struct drm_device *dev)
12411 12411
12412 for_each_pipe(i) { 12412 for_each_pipe(i) {
12413 error->pipe[i].power_domain_on = 12413 error->pipe[i].power_domain_on =
12414 intel_display_power_enabled_sw(dev_priv, 12414 intel_display_power_enabled_unlocked(dev_priv,
12415 POWER_DOMAIN_PIPE(i)); 12415 POWER_DOMAIN_PIPE(i));
12416 if (!error->pipe[i].power_domain_on) 12416 if (!error->pipe[i].power_domain_on)
12417 continue; 12417 continue;
12418 12418
@@ -12447,7 +12447,7 @@ intel_display_capture_error_state(struct drm_device *dev)
12447 enum transcoder cpu_transcoder = transcoders[i]; 12447 enum transcoder cpu_transcoder = transcoders[i];
12448 12448
12449 error->transcoder[i].power_domain_on = 12449 error->transcoder[i].power_domain_on =
12450 intel_display_power_enabled_sw(dev_priv, 12450 intel_display_power_enabled_unlocked(dev_priv,
12451 POWER_DOMAIN_TRANSCODER(cpu_transcoder)); 12451 POWER_DOMAIN_TRANSCODER(cpu_transcoder));
12452 if (!error->transcoder[i].power_domain_on) 12452 if (!error->transcoder[i].power_domain_on)
12453 continue; 12453 continue;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index bda0ae3d80cc..eaa27ee9e367 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -950,8 +950,8 @@ int intel_power_domains_init(struct drm_i915_private *);
950void intel_power_domains_remove(struct drm_i915_private *); 950void intel_power_domains_remove(struct drm_i915_private *);
951bool intel_display_power_enabled(struct drm_i915_private *dev_priv, 951bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
952 enum intel_display_power_domain domain); 952 enum intel_display_power_domain domain);
953bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv, 953bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv,
954 enum intel_display_power_domain domain); 954 enum intel_display_power_domain domain);
955void intel_display_power_get(struct drm_i915_private *dev_priv, 955void intel_display_power_get(struct drm_i915_private *dev_priv,
956 enum intel_display_power_domain domain); 956 enum intel_display_power_domain domain);
957void intel_display_power_put(struct drm_i915_private *dev_priv, 957void intel_display_power_put(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 54242e4f6f4c..9ad0c6afc487 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5603,8 +5603,8 @@ static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
5603 (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); 5603 (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
5604} 5604}
5605 5605
5606bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv, 5606bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv,
5607 enum intel_display_power_domain domain) 5607 enum intel_display_power_domain domain)
5608{ 5608{
5609 struct i915_power_domains *power_domains; 5609 struct i915_power_domains *power_domains;
5610 struct i915_power_well *power_well; 5610 struct i915_power_well *power_well;
@@ -5615,16 +5615,19 @@ bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
5615 return false; 5615 return false;
5616 5616
5617 power_domains = &dev_priv->power_domains; 5617 power_domains = &dev_priv->power_domains;
5618
5618 is_enabled = true; 5619 is_enabled = true;
5620
5619 for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { 5621 for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
5620 if (power_well->always_on) 5622 if (power_well->always_on)
5621 continue; 5623 continue;
5622 5624
5623 if (!power_well->count) { 5625 if (!power_well->hw_enabled) {
5624 is_enabled = false; 5626 is_enabled = false;
5625 break; 5627 break;
5626 } 5628 }
5627 } 5629 }
5630
5628 return is_enabled; 5631 return is_enabled;
5629} 5632}
5630 5633
@@ -5632,30 +5635,15 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
5632 enum intel_display_power_domain domain) 5635 enum intel_display_power_domain domain)
5633{ 5636{
5634 struct i915_power_domains *power_domains; 5637 struct i915_power_domains *power_domains;
5635 struct i915_power_well *power_well; 5638 bool ret;
5636 bool is_enabled;
5637 int i;
5638
5639 if (dev_priv->pm.suspended)
5640 return false;
5641 5639
5642 power_domains = &dev_priv->power_domains; 5640 power_domains = &dev_priv->power_domains;
5643 5641
5644 is_enabled = true;
5645
5646 mutex_lock(&power_domains->lock); 5642 mutex_lock(&power_domains->lock);
5647 for_each_power_well_rev(i, power_well, BIT(domain), power_domains) { 5643 ret = intel_display_power_enabled_unlocked(dev_priv, domain);
5648 if (power_well->always_on)
5649 continue;
5650
5651 if (!power_well->ops->is_enabled(dev_priv, power_well)) {
5652 is_enabled = false;
5653 break;
5654 }
5655 }
5656 mutex_unlock(&power_domains->lock); 5644 mutex_unlock(&power_domains->lock);
5657 5645
5658 return is_enabled; 5646 return ret;
5659} 5647}
5660 5648
5661/* 5649/*
@@ -5976,6 +5964,7 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
5976 if (!power_well->count++) { 5964 if (!power_well->count++) {
5977 DRM_DEBUG_KMS("enabling %s\n", power_well->name); 5965 DRM_DEBUG_KMS("enabling %s\n", power_well->name);
5978 power_well->ops->enable(dev_priv, power_well); 5966 power_well->ops->enable(dev_priv, power_well);
5967 power_well->hw_enabled = true;
5979 } 5968 }
5980 5969
5981 check_power_well_state(dev_priv, power_well); 5970 check_power_well_state(dev_priv, power_well);
@@ -6005,6 +5994,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
6005 5994
6006 if (!--power_well->count && i915.disable_power_well) { 5995 if (!--power_well->count && i915.disable_power_well) {
6007 DRM_DEBUG_KMS("disabling %s\n", power_well->name); 5996 DRM_DEBUG_KMS("disabling %s\n", power_well->name);
5997 power_well->hw_enabled = false;
6008 power_well->ops->disable(dev_priv, power_well); 5998 power_well->ops->disable(dev_priv, power_well);
6009 } 5999 }
6010 6000
@@ -6267,8 +6257,11 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
6267 int i; 6257 int i;
6268 6258
6269 mutex_lock(&power_domains->lock); 6259 mutex_lock(&power_domains->lock);
6270 for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) 6260 for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
6271 power_well->ops->sync_hw(dev_priv, power_well); 6261 power_well->ops->sync_hw(dev_priv, power_well);
6262 power_well->hw_enabled = power_well->ops->is_enabled(dev_priv,
6263 power_well);
6264 }
6272 mutex_unlock(&power_domains->lock); 6265 mutex_unlock(&power_domains->lock);
6273} 6266}
6274 6267