summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c6
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h12
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c81
-rw-r--r--include/drm/i915_powerwell.h36
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 22534c3b4fe..fd8898c8f8e 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)
/* Start out suspended */
dev_priv->mm.suspended = 1;
+ if (HAS_POWER_WELL(dev))
+ i915_init_power_well(dev);
+
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = i915_load_modeset_init(dev);
if (ret < 0) {
@@ -1712,6 +1715,9 @@ int i915_driver_unload(struct drm_device *dev)
intel_gpu_ips_teardown();
+ if (HAS_POWER_WELL(dev))
+ i915_remove_power_well(dev);
+
i915_teardown_sysfs(dev);
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 215aa63e3f4..87f7f88b103 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 {
struct drm_i915_gem_object *renderctx;
};
+/* Power well structure for haswell */
+struct i915_power_well {
+ struct drm_device *device;
+ spinlock_t lock;
+ /* power well enable/disable usage count */
+ int count;
+ int i915_request;
+};
+
struct i915_dri1_state {
unsigned allow_batchbuffer : 1;
u32 __iomem *gfx_hws_cpu_addr;
@@ -1099,6 +1108,9 @@ typedef struct drm_i915_private {
* mchdev_lock in intel_pm.c */
struct intel_ilk_power_mgmt ips;
+ /* Haswell power well */
+ struct i915_power_well power_well;
+
enum no_fbc_reason no_fbc_reason;
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 6bbebf82407..1735cdc8677 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);
extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
extern void intel_gpu_ips_teardown(void);
+/* Power well */
+extern int i915_init_power_well(struct drm_device *dev);
+extern void i915_remove_power_well(struct drm_device *dev);
+
extern bool intel_display_power_enabled(struct drm_device *dev,
enum intel_display_power_domain domain);
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 1e1b48ec6c4..a417d7b196c 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,
}
}
-void intel_set_power_well(struct drm_device *dev, bool enable)
+static void __intel_set_power_well(struct drm_device *dev, bool enable)
{
struct drm_i915_private *dev_priv = dev->dev_private;
bool is_enabled, enable_requested;
uint32_t tmp;
- if (!HAS_POWER_WELL(dev))
- return;
-
- if (!i915_disable_power_well && !enable)
- return;
-
tmp = I915_READ(HSW_PWR_WELL_DRIVER);
is_enabled = tmp & HSW_PWR_WELL_STATE;
enable_requested = tmp & HSW_PWR_WELL_ENABLE;
@@ -5058,6 +5052,79 @@ void intel_set_power_well(struct drm_device *dev, bool enable)
}
}
+static struct i915_power_well *hsw_pwr;
+
+/* Display audio driver power well request */
+void i915_request_power_well(void)
+{
+ if (WARN_ON(!hsw_pwr))
+ return;
+
+ spin_lock_irq(&hsw_pwr->lock);
+ if (!hsw_pwr->count++ &&
+ !hsw_pwr->i915_request)
+ __intel_set_power_well(hsw_pwr->device, true);
+ spin_unlock_irq(&hsw_pwr->lock);
+}
+EXPORT_SYMBOL_GPL(i915_request_power_well);
+
+/* Display audio driver power well release */
+void i915_release_power_well(void)
+{
+ if (WARN_ON(!hsw_pwr))
+ return;
+
+ spin_lock_irq(&hsw_pwr->lock);
+ WARN_ON(!hsw_pwr->count);
+ if (!--hsw_pwr->count &&
+ !hsw_pwr->i915_request)
+ __intel_set_power_well(hsw_pwr->device, false);
+ spin_unlock_irq(&hsw_pwr->lock);
+}
+EXPORT_SYMBOL_GPL(i915_release_power_well);
+
+int i915_init_power_well(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+
+ hsw_pwr = &dev_priv->power_well;
+
+ hsw_pwr->device = dev;
+ spin_lock_init(&hsw_pwr->lock);
+ hsw_pwr->count = 0;
+
+ return 0;
+}
+
+void i915_remove_power_well(struct drm_device *dev)
+{
+ hsw_pwr = NULL;
+}
+
+void intel_set_power_well(struct drm_device *dev, bool enable)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct i915_power_well *power_well = &dev_priv->power_well;
+
+ if (!HAS_POWER_WELL(dev))
+ return;
+
+ if (!i915_disable_power_well && !enable)
+ return;
+
+ spin_lock_irq(&power_well->lock);
+ power_well->i915_request = enable;
+
+ /* only reject "disable" power well request */
+ if (power_well->count && !enable) {
+ spin_unlock_irq(&power_well->lock);
+ return;
+ }
+
+ __intel_set_power_well(dev, enable);
+ spin_unlock_irq(&power_well->lock);
+}
+
/*
* Starting with Haswell, we have a "Power Down Well" that can be turned off
* 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 00000000000..cfdc884405b
--- /dev/null
+++ b/include/drm/i915_powerwell.h
@@ -0,0 +1,36 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Intel Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ *
+ **************************************************************************/
+
+#ifndef _I915_POWERWELL_H_
+#define _I915_POWERWELL_H_
+
+/* For use by hda_i915 driver */
+extern void i915_request_power_well(void);
+extern void i915_release_power_well(void);
+
+#endif /* _I915_POWERWELL_H_ */