summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-04-24 23:55:42 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-06-11 16:57:41 +0200
commit0e572fe7383a376992364914694c39aa7fe44c1d (patch)
tree1582ec9c10a2ed45dab298e8707b9c5625764131 /drivers/gpu/drm
parent7365fb78965725c8ddd5e4d5c061d6d8fbb617e7 (diff)
drm/i915: runtime PM support for DPMS
Keeping track of the power domains is a bit messy since crtc->active is currently updated by the platform hooks, but we need to be aware of which state transition exactly is going on. Maybe we simply need to shovel all the power domain handling down into platform code to simplify this. But doing that requires some more auditing since currently the ->mode_set callbacks still read some random registers (to e.g. figure out the reference clocks). Also note that intel_crtc_update_dpms is always call first/last even for encoders which have their own dpms functions. Hence we really only need to update this place here. Being a quick "does it blow up?" run not really tested yet. v2: Don't do runtime PM in the DPMS hooks for HAS_DDI platforms since that is stalled. Also add a comment to explain what's going on. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e6a2a75c4f5..b5cbb283042 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4876,16 +4876,43 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *intel_encoder;
+ enum intel_display_power_domain domain;
+ unsigned long domains;
bool enable = false;
for_each_encoder_on_crtc(dev, crtc, intel_encoder)
enable |= intel_encoder->connectors_active;
- if (enable)
- dev_priv->display.crtc_enable(crtc);
- else
- dev_priv->display.crtc_disable(crtc);
+ if (enable) {
+ if (!intel_crtc->active) {
+ /*
+ * FIXME: DDI plls and relevant code isn't converted
+ * yet, so do runtime PM for DPMS only for all other
+ * platforms for now.
+ */
+ if (!HAS_DDI(dev)) {
+ domains = get_crtc_power_domains(crtc);
+ for_each_power_domain(domain, domains)
+ intel_display_power_get(dev_priv, domain);
+ intel_crtc->enabled_power_domains = domains;
+ }
+
+ dev_priv->display.crtc_enable(crtc);
+ }
+ } else {
+ if (intel_crtc->active) {
+ dev_priv->display.crtc_disable(crtc);
+
+ if (!HAS_DDI(dev)) {
+ domains = intel_crtc->enabled_power_domains;
+ for_each_power_domain(domain, domains)
+ intel_display_power_put(dev_priv, domain);
+ intel_crtc->enabled_power_domains = 0;
+ }
+ }
+ }
intel_crtc_update_sarea(crtc, enable);
}