diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 12 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 81 | ||||
| -rw-r--r-- | include/drm/i915_powerwell.h | 36 |
5 files changed, 132 insertions, 7 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 22534c3b4fe5..fd8898c8f8e3 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -1656,6 +1656,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1656 | /* Start out suspended */ | 1656 | /* Start out suspended */ |
| 1657 | dev_priv->mm.suspended = 1; | 1657 | dev_priv->mm.suspended = 1; |
| 1658 | 1658 | ||
| 1659 | if (HAS_POWER_WELL(dev)) | ||
| 1660 | i915_init_power_well(dev); | ||
| 1661 | |||
| 1659 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 1662 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 1660 | ret = i915_load_modeset_init(dev); | 1663 | ret = i915_load_modeset_init(dev); |
| 1661 | if (ret < 0) { | 1664 | if (ret < 0) { |
| @@ -1712,6 +1715,9 @@ int i915_driver_unload(struct drm_device *dev) | |||
| 1712 | 1715 | ||
| 1713 | intel_gpu_ips_teardown(); | 1716 | intel_gpu_ips_teardown(); |
| 1714 | 1717 | ||
| 1718 | if (HAS_POWER_WELL(dev)) | ||
| 1719 | i915_remove_power_well(dev); | ||
| 1720 | |||
| 1715 | i915_teardown_sysfs(dev); | 1721 | i915_teardown_sysfs(dev); |
| 1716 | 1722 | ||
| 1717 | if (dev_priv->mm.inactive_shrinker.shrink) | 1723 | if (dev_priv->mm.inactive_shrinker.shrink) |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 215aa63e3f47..87f7f88b1030 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -740,6 +740,15 @@ struct intel_ilk_power_mgmt { | |||
| 740 | struct drm_i915_gem_object *renderctx; | 740 | struct drm_i915_gem_object *renderctx; |
| 741 | }; | 741 | }; |
| 742 | 742 | ||
| 743 | /* Power well structure for haswell */ | ||
| 744 | struct i915_power_well { | ||
| 745 | struct drm_device *device; | ||
| 746 | spinlock_t lock; | ||
| 747 | /* power well enable/disable usage count */ | ||
| 748 | int count; | ||
| 749 | int i915_request; | ||
| 750 | }; | ||
| 751 | |||
| 743 | struct i915_dri1_state { | 752 | struct i915_dri1_state { |
| 744 | unsigned allow_batchbuffer : 1; | 753 | unsigned allow_batchbuffer : 1; |
| 745 | u32 __iomem *gfx_hws_cpu_addr; | 754 | u32 __iomem *gfx_hws_cpu_addr; |
| @@ -1099,6 +1108,9 @@ typedef struct drm_i915_private { | |||
| 1099 | * mchdev_lock in intel_pm.c */ | 1108 | * mchdev_lock in intel_pm.c */ |
| 1100 | struct intel_ilk_power_mgmt ips; | 1109 | struct intel_ilk_power_mgmt ips; |
| 1101 | 1110 | ||
| 1111 | /* Haswell power well */ | ||
| 1112 | struct i915_power_well power_well; | ||
| 1113 | |||
| 1102 | enum no_fbc_reason no_fbc_reason; | 1114 | enum no_fbc_reason no_fbc_reason; |
| 1103 | 1115 | ||
| 1104 | struct drm_mm_node *compressed_fb; | 1116 | struct drm_mm_node *compressed_fb; |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 6bbebf824078..1735cdc86770 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -768,6 +768,10 @@ extern void intel_update_fbc(struct drm_device *dev); | |||
| 768 | extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); | 768 | extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); |
| 769 | extern void intel_gpu_ips_teardown(void); | 769 | extern void intel_gpu_ips_teardown(void); |
| 770 | 770 | ||
| 771 | /* Power well */ | ||
| 772 | extern int i915_init_power_well(struct drm_device *dev); | ||
| 773 | extern void i915_remove_power_well(struct drm_device *dev); | ||
| 774 | |||
| 771 | extern bool intel_display_power_enabled(struct drm_device *dev, | 775 | extern bool intel_display_power_enabled(struct drm_device *dev, |
| 772 | enum intel_display_power_domain domain); | 776 | enum intel_display_power_domain domain); |
| 773 | extern void intel_init_power_well(struct drm_device *dev); | 777 | extern void intel_init_power_well(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1e1b48ec6c46..a417d7b196c2 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -5024,18 +5024,12 @@ bool intel_display_power_enabled(struct drm_device *dev, | |||
| 5024 | } | 5024 | } |
| 5025 | } | 5025 | } |
| 5026 | 5026 | ||
| 5027 | void intel_set_power_well(struct drm_device *dev, bool enable) | 5027 | static void __intel_set_power_well(struct drm_device *dev, bool enable) |
| 5028 | { | 5028 | { |
| 5029 | struct drm_i915_private *dev_priv = dev->dev_private; | 5029 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 5030 | bool is_enabled, enable_requested; | 5030 | bool is_enabled, enable_requested; |
| 5031 | uint32_t tmp; | 5031 | uint32_t tmp; |
| 5032 | 5032 | ||
| 5033 | if (!HAS_POWER_WELL(dev)) | ||
| 5034 | return; | ||
| 5035 | |||
| 5036 | if (!i915_disable_power_well && !enable) | ||
| 5037 | return; | ||
| 5038 | |||
| 5039 | tmp = I915_READ(HSW_PWR_WELL_DRIVER); | 5033 | tmp = I915_READ(HSW_PWR_WELL_DRIVER); |
| 5040 | is_enabled = tmp & HSW_PWR_WELL_STATE; | 5034 | is_enabled = tmp & HSW_PWR_WELL_STATE; |
| 5041 | enable_requested = tmp & HSW_PWR_WELL_ENABLE; | 5035 | enable_requested = tmp & HSW_PWR_WELL_ENABLE; |
| @@ -5058,6 +5052,79 @@ void intel_set_power_well(struct drm_device *dev, bool enable) | |||
| 5058 | } | 5052 | } |
| 5059 | } | 5053 | } |
| 5060 | 5054 | ||
| 5055 | static struct i915_power_well *hsw_pwr; | ||
| 5056 | |||
| 5057 | /* Display audio driver power well request */ | ||
| 5058 | void i915_request_power_well(void) | ||
| 5059 | { | ||
| 5060 | if (WARN_ON(!hsw_pwr)) | ||
| 5061 | return; | ||
| 5062 | |||
| 5063 | spin_lock_irq(&hsw_pwr->lock); | ||
| 5064 | if (!hsw_pwr->count++ && | ||
| 5065 | !hsw_pwr->i915_request) | ||
| 5066 | __intel_set_power_well(hsw_pwr->device, true); | ||
| 5067 | spin_unlock_irq(&hsw_pwr->lock); | ||
| 5068 | } | ||
| 5069 | EXPORT_SYMBOL_GPL(i915_request_power_well); | ||
| 5070 | |||
| 5071 | /* Display audio driver power well release */ | ||
| 5072 | void i915_release_power_well(void) | ||
| 5073 | { | ||
| 5074 | if (WARN_ON(!hsw_pwr)) | ||
| 5075 | return; | ||
| 5076 | |||
| 5077 | spin_lock_irq(&hsw_pwr->lock); | ||
| 5078 | WARN_ON(!hsw_pwr->count); | ||
| 5079 | if (!--hsw_pwr->count && | ||
| 5080 | !hsw_pwr->i915_request) | ||
| 5081 | __intel_set_power_well(hsw_pwr->device, false); | ||
| 5082 | spin_unlock_irq(&hsw_pwr->lock); | ||
| 5083 | } | ||
| 5084 | EXPORT_SYMBOL_GPL(i915_release_power_well); | ||
| 5085 | |||
| 5086 | int i915_init_power_well(struct drm_device *dev) | ||
| 5087 | { | ||
| 5088 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 5089 | |||
| 5090 | hsw_pwr = &dev_priv->power_well; | ||
| 5091 | |||
| 5092 | hsw_pwr->device = dev; | ||
| 5093 | spin_lock_init(&hsw_pwr->lock); | ||
| 5094 | hsw_pwr->count = 0; | ||
| 5095 | |||
| 5096 | return 0; | ||
| 5097 | } | ||
| 5098 | |||
| 5099 | void i915_remove_power_well(struct drm_device *dev) | ||
| 5100 | { | ||
| 5101 | hsw_pwr = NULL; | ||
| 5102 | } | ||
| 5103 | |||
| 5104 | void intel_set_power_well(struct drm_device *dev, bool enable) | ||
| 5105 | { | ||
| 5106 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 5107 | struct i915_power_well *power_well = &dev_priv->power_well; | ||
| 5108 | |||
| 5109 | if (!HAS_POWER_WELL(dev)) | ||
| 5110 | return; | ||
| 5111 | |||
| 5112 | if (!i915_disable_power_well && !enable) | ||
| 5113 | return; | ||
| 5114 | |||
| 5115 | spin_lock_irq(&power_well->lock); | ||
| 5116 | power_well->i915_request = enable; | ||
| 5117 | |||
| 5118 | /* only reject "disable" power well request */ | ||
| 5119 | if (power_well->count && !enable) { | ||
| 5120 | spin_unlock_irq(&power_well->lock); | ||
| 5121 | return; | ||
| 5122 | } | ||
| 5123 | |||
| 5124 | __intel_set_power_well(dev, enable); | ||
| 5125 | spin_unlock_irq(&power_well->lock); | ||
| 5126 | } | ||
| 5127 | |||
| 5061 | /* | 5128 | /* |
| 5062 | * Starting with Haswell, we have a "Power Down Well" that can be turned off | 5129 | * Starting with Haswell, we have a "Power Down Well" that can be turned off |
| 5063 | * when not needed anymore. We have 4 registers that can request the power well | 5130 | * when not needed anymore. We have 4 registers that can request the power well |
diff --git a/include/drm/i915_powerwell.h b/include/drm/i915_powerwell.h new file mode 100644 index 000000000000..cfdc884405b7 --- /dev/null +++ b/include/drm/i915_powerwell.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2013 Intel Inc. | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | * | ||
| 27 | **************************************************************************/ | ||
| 28 | |||
| 29 | #ifndef _I915_POWERWELL_H_ | ||
| 30 | #define _I915_POWERWELL_H_ | ||
| 31 | |||
| 32 | /* For use by hda_i915 driver */ | ||
| 33 | extern void i915_request_power_well(void); | ||
| 34 | extern void i915_release_power_well(void); | ||
| 35 | |||
| 36 | #endif /* _I915_POWERWELL_H_ */ | ||
