Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i915/drm: Add private api for power well usage

Haswell Display audio depends on power well in graphic side, it should
request power well before use it and release power well after use.
I915 will not shutdown power well if it detects audio is using.
This patch protects display audio crash for Intel Haswell C3 stepping board.

Signed-off-by: Wang Xingchao <xingchao.wang@linux.intel.com>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

authored by

Wang Xingchao and committed by
Daniel Vetter
a38911a3 99a2008d

+132 -7
+6
drivers/gpu/drm/i915/i915_dma.c
··· 1656 1656 /* Start out suspended */ 1657 1657 dev_priv->mm.suspended = 1; 1658 1658 1659 + if (HAS_POWER_WELL(dev)) 1660 + i915_init_power_well(dev); 1661 + 1659 1662 if (drm_core_check_feature(dev, DRIVER_MODESET)) { 1660 1663 ret = i915_load_modeset_init(dev); 1661 1664 if (ret < 0) { ··· 1714 1711 int ret; 1715 1712 1716 1713 intel_gpu_ips_teardown(); 1714 + 1715 + if (HAS_POWER_WELL(dev)) 1716 + i915_remove_power_well(dev); 1717 1717 1718 1718 i915_teardown_sysfs(dev); 1719 1719
+12
drivers/gpu/drm/i915/i915_drv.h
··· 740 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 752 struct i915_dri1_state { 744 753 unsigned allow_batchbuffer : 1; 745 754 u32 __iomem *gfx_hws_cpu_addr; ··· 1107 1098 /* ilk-only ips/rps state. Everything in here is protected by the global 1108 1099 * mchdev_lock in intel_pm.c */ 1109 1100 struct intel_ilk_power_mgmt ips; 1101 + 1102 + /* Haswell power well */ 1103 + struct i915_power_well power_well; 1110 1104 1111 1105 enum no_fbc_reason no_fbc_reason; 1112 1106
+4
drivers/gpu/drm/i915/intel_drv.h
··· 768 768 extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); 769 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 775 extern bool intel_display_power_enabled(struct drm_device *dev, 772 776 enum intel_display_power_domain domain); 773 777 extern void intel_init_power_well(struct drm_device *dev);
+74 -7
drivers/gpu/drm/i915/intel_pm.c
··· 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 5029 struct drm_i915_private *dev_priv = dev->dev_private; 5030 5030 bool is_enabled, enable_requested; 5031 5031 uint32_t tmp; 5032 - 5033 - if (!HAS_POWER_WELL(dev)) 5034 - return; 5035 - 5036 - if (!i915_disable_power_well && !enable) 5037 - return; 5038 5032 5039 5033 tmp = I915_READ(HSW_PWR_WELL_DRIVER); 5040 5034 is_enabled = tmp & HSW_PWR_WELL_STATE; ··· 5050 5056 DRM_DEBUG_KMS("Requesting to disable the power well\n"); 5051 5057 } 5052 5058 } 5059 + } 5060 + 5061 + static struct i915_power_well *hsw_pwr; 5062 + 5063 + /* Display audio driver power well request */ 5064 + void i915_request_power_well(void) 5065 + { 5066 + if (WARN_ON(!hsw_pwr)) 5067 + return; 5068 + 5069 + spin_lock_irq(&hsw_pwr->lock); 5070 + if (!hsw_pwr->count++ && 5071 + !hsw_pwr->i915_request) 5072 + __intel_set_power_well(hsw_pwr->device, true); 5073 + spin_unlock_irq(&hsw_pwr->lock); 5074 + } 5075 + EXPORT_SYMBOL_GPL(i915_request_power_well); 5076 + 5077 + /* Display audio driver power well release */ 5078 + void i915_release_power_well(void) 5079 + { 5080 + if (WARN_ON(!hsw_pwr)) 5081 + return; 5082 + 5083 + spin_lock_irq(&hsw_pwr->lock); 5084 + WARN_ON(!hsw_pwr->count); 5085 + if (!--hsw_pwr->count && 5086 + !hsw_pwr->i915_request) 5087 + __intel_set_power_well(hsw_pwr->device, false); 5088 + spin_unlock_irq(&hsw_pwr->lock); 5089 + } 5090 + EXPORT_SYMBOL_GPL(i915_release_power_well); 5091 + 5092 + int i915_init_power_well(struct drm_device *dev) 5093 + { 5094 + struct drm_i915_private *dev_priv = dev->dev_private; 5095 + 5096 + hsw_pwr = &dev_priv->power_well; 5097 + 5098 + hsw_pwr->device = dev; 5099 + spin_lock_init(&hsw_pwr->lock); 5100 + hsw_pwr->count = 0; 5101 + 5102 + return 0; 5103 + } 5104 + 5105 + void i915_remove_power_well(struct drm_device *dev) 5106 + { 5107 + hsw_pwr = NULL; 5108 + } 5109 + 5110 + void intel_set_power_well(struct drm_device *dev, bool enable) 5111 + { 5112 + struct drm_i915_private *dev_priv = dev->dev_private; 5113 + struct i915_power_well *power_well = &dev_priv->power_well; 5114 + 5115 + if (!HAS_POWER_WELL(dev)) 5116 + return; 5117 + 5118 + if (!i915_disable_power_well && !enable) 5119 + return; 5120 + 5121 + spin_lock_irq(&power_well->lock); 5122 + power_well->i915_request = enable; 5123 + 5124 + /* only reject "disable" power well request */ 5125 + if (power_well->count && !enable) { 5126 + spin_unlock_irq(&power_well->lock); 5127 + return; 5128 + } 5129 + 5130 + __intel_set_power_well(dev, enable); 5131 + spin_unlock_irq(&power_well->lock); 5053 5132 } 5054 5133 5055 5134 /*
+36
include/drm/i915_powerwell.h
··· 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_ */