[PATCH 4/5] drm/i915: take power well refs when needed

Jesse Barnes
2013-10-14T23:07:55Z

When accessing the display regs for hw state readout or cross check, we
need to make sure the power well is enabled so we can read valid
register state.

Likewise, in an actual mode set, we need to take a ref on the
appropriate power well so that the mode set succeeds. From then on, the
power well ref will be tracked by the CRTC enable/disable code.

Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
---
drivers/gpu/drm/i915/i915_dma.c | 2 ++
drivers/gpu/drm/i915/intel_display.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 313a8c9..91c3e6c 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1367,6 +1367,8 @@ static int i915_load_modeset_init(struct drm_device *dev)
i915_disable_vga_mem(dev);
intel_display_power_put(dev, POWER_DOMAIN_VGA);

+ intel_display_power_put(dev, POWER_DOMAIN_PIPE(0));
+
/* Only enable hotplug handling once the fbdev is fully set up. */
dev_priv->enable_hotplug_processing = true;

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6e4729b..62ee110 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3841,6 +3841,8 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
if (intel_crtc->active)
return;

+ intel_display_power_get(dev, POWER_DOMAIN_PIPE(pipe));
+
intel_crtc->active = true;

for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -3975,6 +3977,9 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
intel_update_watermarks(crtc);

intel_update_fbc(dev);
+
+ if (IS_VALLEYVIEW(dev))
+ intel_display_power_put(dev, POWER_DOMAIN_PIPE(pipe));
}

static void i9xx_crtc_off(struct drm_crtc *crtc)
@@ -4134,6 +4139,11 @@ static void intel_connector_check_state(struct intel_connector *connector)
* consider. */
void intel_connector_dpms(struct drm_connector *connector, int mode)
{
+ struct intel_crtc *intel_crtc = to_intel_crtc(connector->encoder->crtc);
+ enum intel_display_power_domain domain;
+
+ domain = POWER_DOMAIN_PIPE(intel_crtc->pipe);
+
/* All the simple cases only support two dpms states. */
if (mode != DRM_MODE_DPMS_ON)
mode = DRM_MODE_DPMS_OFF;
@@ -4141,6 +4151,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
if (mode == connector->dpms)
return;

+ intel_display_power_get(connector->dev, domain);
connector->dpms = mode;

/* Only need to change hw state when actually enabled */
@@ -4148,6 +4159,7 @@ void intel_connector_dpms(struct drm_connector *connector, int mode)
intel_encoder_dpms(to_intel_encoder(connector->encoder), mode);

intel_modeset_check_state(connector->dev);
+ intel_display_power_put(connector->dev, domain);
}

/* Simple connector->get_hw_state implementation for encoders that support only
@@ -9192,6 +9204,15 @@ static int __intel_set_mode(struct drm_crtc *crtc,
for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)
intel_crtc_disable(&intel_crtc->base);

+ /*
+ * We take a ref here so the mode set will hit live hw. Once
+ * we call the CRTC enable, we can drop our ref since it'll get
+ * tracked there from then on.
+ */
+ for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
+ intel_display_power_get(dev,
+ POWER_DOMAIN_PIPE(intel_crtc->pipe));
+
for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc) {
if (intel_crtc->base.enabled)
dev_priv->display.crtc_disable(&intel_crtc->base);
@@ -9247,6 +9268,10 @@ done:
}

out:
+ for_each_intel_crtc_masked(dev, prepare_pipes, intel_crtc)
+ intel_display_power_put(dev,
+ POWER_DOMAIN_PIPE(intel_crtc->pipe));
+
kfree(pipe_config);
kfree(saved_mode);
return ret;
@@ -10692,6 +10717,11 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)

crtc->base.enabled = crtc->active;

+ if (crtc->active)
+ intel_display_power_get(dev,
+ POWER_DOMAIN_PIPE(crtc->pipe));
+
+
DRM_DEBUG_KMS("[CRTC:%d] hw state readout: %s\n",
crtc->base.base.id,
crtc->active ? "enabled" : "disabled");
--
1.8.3.1