aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2013-10-16 10:25:52 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-21 14:59:55 -0400
commit6efdf354ddb186c6604d1692075421e8d2c740e9 (patch)
tree040ba159ca0405d8549a51c9f93fd27357c0e23e
parent4f0741291eaad552ebfffc20770d494375507412 (diff)
drm/i915: enable only the needed power domains during modeset
So far the modeset code enabled all power domains if it needed any. It wasn't a problem since HW generations so far only had one always-on power well and one dynamic power well that can be enabled/disabled. For domains powered by always-on power wells (panel fitter on pipe A and the eDP transcoder) we didn't do anything, for all other domains we just enabled the single dynamic power well. Future HW generations will change this, as they add multiple dynamic power wells. Support for these will be added later, this patch prepares for those by making sure we only enable the required domains. Note that after this change on HSW we'll enable all power domains even if it was the domain for the panel fitter on pipe A or the eDP transcoder. This isn't a problem since the power domain framework already checks if the domain is on an always-on power well and doesn't do anything in this case. Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c46
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
2 files changed, 42 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 320c696374ac..cfe9e7093b2a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6557,21 +6557,57 @@ static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv)
6557 } 6557 }
6558} 6558}
6559 6559
6560#define for_each_power_domain(domain, mask) \
6561 for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
6562 if ((1 << (domain)) & (mask))
6563
6564static unsigned long get_pipe_power_domains(struct drm_device *dev,
6565 enum pipe pipe, bool pfit_enabled)
6566{
6567 unsigned long mask;
6568 enum transcoder transcoder;
6569
6570 transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
6571
6572 mask = BIT(POWER_DOMAIN_PIPE(pipe));
6573 mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
6574 if (pfit_enabled)
6575 mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
6576
6577 return mask;
6578}
6579
6560static void modeset_update_power_wells(struct drm_device *dev) 6580static void modeset_update_power_wells(struct drm_device *dev)
6561{ 6581{
6562 bool enable = false; 6582 unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
6563 struct intel_crtc *crtc; 6583 struct intel_crtc *crtc;
6564 6584
6585 /*
6586 * First get all needed power domains, then put all unneeded, to avoid
6587 * any unnecessary toggling of the power wells.
6588 */
6565 list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { 6589 list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
6590 enum intel_display_power_domain domain;
6591
6566 if (!crtc->base.enabled) 6592 if (!crtc->base.enabled)
6567 continue; 6593 continue;
6568 6594
6569 if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.enabled || 6595 pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
6570 crtc->config.cpu_transcoder != TRANSCODER_EDP) 6596 crtc->pipe,
6571 enable = true; 6597 crtc->config.pch_pfit.enabled);
6598
6599 for_each_power_domain(domain, pipe_domains[crtc->pipe])
6600 intel_display_power_get(dev, domain);
6572 } 6601 }
6573 6602
6574 intel_set_power_well(dev, enable); 6603 list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
6604 enum intel_display_power_domain domain;
6605
6606 for_each_power_domain(domain, crtc->enabled_power_domains)
6607 intel_display_power_put(dev, domain);
6608
6609 crtc->enabled_power_domains = pipe_domains[crtc->pipe];
6610 }
6575} 6611}
6576 6612
6577static void haswell_modeset_global_resources(struct drm_device *dev) 6613static void haswell_modeset_global_resources(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e33f387d4185..af1553ca0f4e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -326,6 +326,7 @@ struct intel_crtc {
326 * some outputs connected to this crtc. 326 * some outputs connected to this crtc.
327 */ 327 */
328 bool active; 328 bool active;
329 unsigned long enabled_power_domains;
329 bool eld_vld; 330 bool eld_vld;
330 bool primary_enabled; /* is the primary plane (partially) visible? */ 331 bool primary_enabled; /* is the primary plane (partially) visible? */
331 bool lowfreq_avail; 332 bool lowfreq_avail;