aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2013-01-25 13:59:11 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-01-26 11:54:28 -0500
commitfa42e23c1055a4549c433ac56ff869e441c973c8 (patch)
treeb73dbd06e700e73a288d975618bf6f674e5b4874
parent80a75f7c44c8fd8cf6b271dc20801846bd630349 (diff)
drm/i915: fix intel_init_power_wells
The current code was wrong in many different ways, so this is a full rewrite. We don't have "different power wells for different parts of the GPU", we have a single power well, but we have multiple registers that can be used to request enabling/disabling the power well. So let's be a good citizen and only use the register we're suppose to use, except when we're loading the driver, where we clear the request made by the BIOS. If any of the registers is requesting the power well to be enabled, it will be enabled. If none of the registers is requesting the power well to be enabled, it will be disabled. For now we're just forcing the power well to be enabled, but in the next commits we'll change this. V2: - Remove debug messages that could be misleading due to possible race conditions with KVMr, Debug and BIOS. - Don't wait on disabling: after a conversaion with a hardware engineer we discovered that the "restriction" on bit 31 is just for the "enable" case, and we don't even need to wait on the "disable" case. Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h8
-rw-r--r--drivers/gpu/drm/i915/intel_display.c5
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c57
4 files changed, 46 insertions, 26 deletions
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 215443c378cc..a18218ccac1e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4422,10 +4422,10 @@
4422#define AUDIO_CP_READY_C (1<<9) 4422#define AUDIO_CP_READY_C (1<<9)
4423 4423
4424/* HSW Power Wells */ 4424/* HSW Power Wells */
4425#define HSW_PWR_WELL_CTL1 0x45400 /* BIOS */ 4425#define HSW_PWR_WELL_BIOS 0x45400 /* CTL1 */
4426#define HSW_PWR_WELL_CTL2 0x45404 /* Driver */ 4426#define HSW_PWR_WELL_DRIVER 0x45404 /* CTL2 */
4427#define HSW_PWR_WELL_CTL3 0x45408 /* KVMR */ 4427#define HSW_PWR_WELL_KVMR 0x45408 /* CTL3 */
4428#define HSW_PWR_WELL_CTL4 0x4540C /* Debug */ 4428#define HSW_PWR_WELL_DEBUG 0x4540C /* CTL4 */
4429#define HSW_PWR_WELL_ENABLE (1<<31) 4429#define HSW_PWR_WELL_ENABLE (1<<31)
4430#define HSW_PWR_WELL_STATE (1<<30) 4430#define HSW_PWR_WELL_STATE (1<<30)
4431#define HSW_PWR_WELL_CTL5 0x45410 4431#define HSW_PWR_WELL_CTL5 0x45410
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index c5997d260172..19ab75f307e5 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8659,10 +8659,7 @@ static void i915_disable_vga(struct drm_device *dev)
8659 8659
8660void intel_modeset_init_hw(struct drm_device *dev) 8660void intel_modeset_init_hw(struct drm_device *dev)
8661{ 8661{
8662 /* We attempt to init the necessary power wells early in the initialization 8662 intel_init_power_well(dev);
8663 * time, so the subsystems that expect power to be enabled can work.
8664 */
8665 intel_init_power_wells(dev);
8666 8663
8667 intel_prepare_ddi(dev); 8664 intel_prepare_ddi(dev);
8668 8665
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 66619d80348f..32c30423eaca 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -667,7 +667,7 @@ extern void intel_update_fbc(struct drm_device *dev);
667extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv); 667extern void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
668extern void intel_gpu_ips_teardown(void); 668extern void intel_gpu_ips_teardown(void);
669 669
670extern void intel_init_power_wells(struct drm_device *dev); 670extern void intel_init_power_well(struct drm_device *dev);
671extern void intel_enable_gt_powersave(struct drm_device *dev); 671extern void intel_enable_gt_powersave(struct drm_device *dev);
672extern void intel_disable_gt_powersave(struct drm_device *dev); 672extern void intel_disable_gt_powersave(struct drm_device *dev);
673extern void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv); 673extern void gen6_gt_check_fifodbg(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 5a8a72c5a89d..b8cf16c06b1b 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4043,33 +4043,56 @@ void intel_init_clock_gating(struct drm_device *dev)
4043 dev_priv->display.init_clock_gating(dev); 4043 dev_priv->display.init_clock_gating(dev);
4044} 4044}
4045 4045
4046/* Starting with Haswell, we have different power wells for 4046static void intel_set_power_well(struct drm_device *dev, bool enable)
4047 * different parts of the GPU. This attempts to enable them all. 4047{
4048 struct drm_i915_private *dev_priv = dev->dev_private;
4049 bool is_enabled, enable_requested;
4050 uint32_t tmp;
4051
4052 tmp = I915_READ(HSW_PWR_WELL_DRIVER);
4053 is_enabled = tmp & HSW_PWR_WELL_STATE;
4054 enable_requested = tmp & HSW_PWR_WELL_ENABLE;
4055
4056 if (enable) {
4057 if (!enable_requested)
4058 I915_WRITE(HSW_PWR_WELL_DRIVER, HSW_PWR_WELL_ENABLE);
4059
4060 if (!is_enabled) {
4061 DRM_DEBUG_KMS("Enabling power well\n");
4062 if (wait_for((I915_READ(HSW_PWR_WELL_DRIVER) &
4063 HSW_PWR_WELL_STATE), 20))
4064 DRM_ERROR("Timeout enabling power well\n");
4065 }
4066 } else {
4067 if (enable_requested) {
4068 I915_WRITE(HSW_PWR_WELL_DRIVER, 0);
4069 DRM_DEBUG_KMS("Requesting to disable the power well\n");
4070 }
4071 }
4072}
4073
4074/*
4075 * Starting with Haswell, we have a "Power Down Well" that can be turned off
4076 * when not needed anymore. We have 4 registers that can request the power well
4077 * to be enabled, and it will only be disabled if none of the registers is
4078 * requesting it to be enabled.
4048 */ 4079 */
4049void intel_init_power_wells(struct drm_device *dev) 4080void intel_init_power_well(struct drm_device *dev)
4050{ 4081{
4051 struct drm_i915_private *dev_priv = dev->dev_private; 4082 struct drm_i915_private *dev_priv = dev->dev_private;
4052 unsigned long power_wells[] = {
4053 HSW_PWR_WELL_CTL1,
4054 HSW_PWR_WELL_CTL2,
4055 HSW_PWR_WELL_CTL4
4056 };
4057 int i;
4058 4083
4059 if (!IS_HASWELL(dev)) 4084 if (!IS_HASWELL(dev))
4060 return; 4085 return;
4061 4086
4062 mutex_lock(&dev->struct_mutex); 4087 mutex_lock(&dev->struct_mutex);
4063 4088
4064 for (i = 0; i < ARRAY_SIZE(power_wells); i++) { 4089 /* For now, we need the power well to be always enabled. */
4065 int well = I915_READ(power_wells[i]); 4090 intel_set_power_well(dev, true);
4066 4091
4067 if ((well & HSW_PWR_WELL_STATE) == 0) { 4092 /* We're taking over the BIOS, so clear any requests made by it since
4068 I915_WRITE(power_wells[i], well & HSW_PWR_WELL_ENABLE); 4093 * the driver is in charge now. */
4069 if (wait_for((I915_READ(power_wells[i]) & HSW_PWR_WELL_STATE), 20)) 4094 if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE)
4070 DRM_ERROR("Error enabling power well %lx\n", power_wells[i]); 4095 I915_WRITE(HSW_PWR_WELL_BIOS, 0);
4071 }
4072 }
4073 4096
4074 mutex_unlock(&dev->struct_mutex); 4097 mutex_unlock(&dev->struct_mutex);
4075} 4098}