All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/19] drm/i915: vlv power domains support
@ 2014-02-17 22:02 Imre Deak
  2014-02-17 22:02 ` [PATCH 01/19] drm/i915: use drm_i915_private everywhere in the power domain api Imre Deak
                   ` (18 more replies)
  0 siblings, 19 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

This patchset adds support for enabling/disabling dynamic power-wells on
VLV on-demand.

Before enabling on-demand power well toggling the patchset adds the
checks for required power domains for places that poke at the HW. These
are the pipe, encoder and connector HW state readout functions. It also
does a get/put of required power domains in the connector detect and
get_mode handlers.

Also a set of new port specific power domains are added so the above
encoder and connector specific check/get/put parts can refer to them.

One TODO item left is hot-plug detection on BYT. With the display power
well off HPD stops working and this patchset doesn't add any workaround
for that, as that wasn't deemed to be important. A solution to make it
work again would be to use connector polling for VGA and GPIO re-muxing
for DP,HDMI.

Another TODO is more power optimizations for DP 2 lane configurations
and configurations where only a single DP port is enabled. Since atm,
the PHY setup code assumes a two port/4 lanes config, we enable all
power domains that this requires. Atm, the only win is when all ports
are off, or in case of a single VGA connection, where we can power off
the DPIO TX lane power wells.

Tested on BYT DP/HDMI/VGA with xset dpms force off/on and suspend /
resume. Also did some basic testing on HSW,IVB with DP. I ransome of
the igt gem tests on BYT with all display power wells off, they
seemed to run ok.

Imre Deak (19):
  drm/i915: use drm_i915_private everywhere in the power domain api
  drm/i915: fold in __intel_power_well_get/put functions
  drm/i915: move modeset_update_power_wells earlier
  drm/i915: move power domain macros to intel_pm.c
  drm/i915: power domains: add power well ops
  drm/i915: remove power_well->always_on flag
  drm/i915: add port power domains
  drm/i915: get port power domain in connector detect
  drm/i915: check port power domain when reading the encoder hw state
  drm/i915: check pipe power domain when reading its hw state
  drm/i915: vlv: keep first level vblank IRQs masked
  drm/i915: sanitize PUNIT register macro definitions
  drm/i915: factor out reset_vblank_counter
  drm/i915: switch order of power domain init wrt. irq install
  drm/i915: use power domain api to check vga power state
  drm/i915: sanity check power well sw state against hw state
  drm/i915: vlv: factor out valleyview_display_irq_install
  drm/i915: move hsw power domain comment to its right place
  drm/i915: power domains: add vlv power wells

 drivers/gpu/drm/i915/i915_debugfs.c  |  22 ++
 drivers/gpu/drm/i915/i915_dma.c      |  16 +-
 drivers/gpu/drm/i915/i915_drv.c      |   4 +-
 drivers/gpu/drm/i915/i915_drv.h      |  65 ++++--
 drivers/gpu/drm/i915/i915_irq.c      | 126 +++++++---
 drivers/gpu/drm/i915/i915_reg.h      |  29 ++-
 drivers/gpu/drm/i915/intel_crt.c     |  42 +++-
 drivers/gpu/drm/i915/intel_ddi.c     |   2 +-
 drivers/gpu/drm/i915/intel_display.c | 255 +++++++++++++--------
 drivers/gpu/drm/i915/intel_dp.c      |  16 +-
 drivers/gpu/drm/i915/intel_drv.h     |  20 +-
 drivers/gpu/drm/i915/intel_dsi.c     |  13 +-
 drivers/gpu/drm/i915/intel_pm.c      | 433 +++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_uncore.c  |   4 +-
 14 files changed, 797 insertions(+), 250 deletions(-)

-- 
1.8.4

^ permalink raw reply	[flat|nested] 68+ messages in thread

* [PATCH 01/19] drm/i915: use drm_i915_private everywhere in the power domain api
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:16   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions Imre Deak
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

The power domains framework is internal to the i915 driver, so pass
drm_i915_private instead of drm_device to its functions.

Also remove a dangling intel_set_power_well() declaration.

No functional change.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c      | 14 ++++----
 drivers/gpu/drm/i915/i915_drv.c      |  4 +--
 drivers/gpu/drm/i915/i915_drv.h      |  4 +--
 drivers/gpu/drm/i915/intel_display.c | 27 +++++++--------
 drivers/gpu/drm/i915/intel_drv.h     | 17 +++++-----
 drivers/gpu/drm/i915/intel_pm.c      | 65 ++++++++++++++----------------------
 6 files changed, 58 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 7688abc..8177c17 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1325,7 +1325,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	if (ret)
 		goto cleanup_gem_stolen;
 
-	intel_power_domains_init_hw(dev);
+	intel_power_domains_init_hw(dev_priv);
 
 	/* Important: The output setup functions called by modeset_init need
 	 * working irqs for e.g. gmbus and dp aux transfers. */
@@ -1343,7 +1343,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	/* FIXME: do pre/post-mode set stuff in core KMS code */
 	dev->vblank_disable_allowed = true;
 	if (INTEL_INFO(dev)->num_pipes == 0) {
-		intel_display_power_put(dev, POWER_DOMAIN_VGA);
+		intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
 		return 0;
 	}
 
@@ -1381,7 +1381,7 @@ cleanup_gem:
 	WARN_ON(dev_priv->mm.aliasing_ppgtt);
 	drm_mm_takedown(&dev_priv->gtt.base.mm);
 cleanup_power:
-	intel_display_power_put(dev, POWER_DOMAIN_VGA);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
 	drm_irq_uninstall(dev);
 cleanup_gem_stolen:
 	i915_gem_cleanup_stolen(dev);
@@ -1702,7 +1702,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 			goto out_gem_unload;
 	}
 
-	intel_power_domains_init(dev);
+	intel_power_domains_init(dev_priv);
 
 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 		ret = i915_load_modeset_init(dev);
@@ -1731,7 +1731,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	return 0;
 
 out_power_well:
-	intel_power_domains_remove(dev);
+	intel_power_domains_remove(dev_priv);
 	drm_vblank_cleanup(dev);
 out_gem_unload:
 	if (dev_priv->mm.inactive_shrinker.scan_objects)
@@ -1781,8 +1781,8 @@ int i915_driver_unload(struct drm_device *dev)
 	/* The i915.ko module is still not prepared to be loaded when
 	 * the power well is not enabled, so just enable it in case
 	 * we're going to unload/reload. */
-	intel_display_set_init_power(dev, true);
-	intel_power_domains_remove(dev);
+	intel_display_set_init_power(dev_priv, true);
+	intel_power_domains_remove(dev_priv);
 
 	i915_teardown_sysfs(dev);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 08052f3d..ce898af 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -429,7 +429,7 @@ static int i915_drm_freeze(struct drm_device *dev)
 	/* We do a lot of poking in a lot of registers, make sure they work
 	 * properly. */
 	hsw_disable_package_c8(dev_priv);
-	intel_display_set_init_power(dev, true);
+	intel_display_set_init_power(dev_priv, true);
 
 	drm_kms_helper_poll_disable(dev);
 
@@ -551,7 +551,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
 		mutex_unlock(&dev->struct_mutex);
 	}
 
-	intel_power_domains_init_hw(dev);
+	intel_power_domains_init_hw(dev_priv);
 
 	i915_restore_state(dev);
 	intel_opregion_setup(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8c64831..796f971 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1024,9 +1024,9 @@ struct i915_power_well {
 	int count;
 	unsigned long domains;
 	void *data;
-	void (*set)(struct drm_device *dev, struct i915_power_well *power_well,
+	void (*set)(struct drm_i915_private *dev_priv, struct i915_power_well *power_well,
 		    bool enable);
-	bool (*is_enabled)(struct drm_device *dev,
+	bool (*is_enabled)(struct drm_i915_private *dev_priv,
 			   struct i915_power_well *power_well);
 };
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f19e6ea..17c2033 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1122,7 +1122,7 @@ void assert_pipe(struct drm_i915_private *dev_priv,
 	if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
 		state = true;
 
-	if (!intel_display_power_enabled(dev_priv->dev,
+	if (!intel_display_power_enabled(dev_priv,
 				POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
 		cur_state = false;
 	} else {
@@ -6858,23 +6858,23 @@ static unsigned long get_pipe_power_domains(struct drm_device *dev,
 	return mask;
 }
 
-void intel_display_set_init_power(struct drm_device *dev, bool enable)
+void intel_display_set_init_power(struct drm_i915_private *dev_priv,
+				  bool enable)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	if (dev_priv->power_domains.init_power_on == enable)
 		return;
 
 	if (enable)
-		intel_display_power_get(dev, POWER_DOMAIN_INIT);
+		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 	else
-		intel_display_power_put(dev, POWER_DOMAIN_INIT);
+		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
 	dev_priv->power_domains.init_power_on = enable;
 }
 
 static void modeset_update_power_wells(struct drm_device *dev)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
 	struct intel_crtc *crtc;
 
@@ -6893,19 +6893,19 @@ static void modeset_update_power_wells(struct drm_device *dev)
 						crtc->config.pch_pfit.enabled);
 
 		for_each_power_domain(domain, pipe_domains[crtc->pipe])
-			intel_display_power_get(dev, domain);
+			intel_display_power_get(dev_priv, domain);
 	}
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
 		enum intel_display_power_domain domain;
 
 		for_each_power_domain(domain, crtc->enabled_power_domains)
-			intel_display_power_put(dev, domain);
+			intel_display_power_put(dev_priv, domain);
 
 		crtc->enabled_power_domains = pipe_domains[crtc->pipe];
 	}
 
-	intel_display_set_init_power(dev, false);
+	intel_display_set_init_power(dev_priv, false);
 }
 
 static void haswell_modeset_global_resources(struct drm_device *dev)
@@ -6986,7 +6986,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 			pipe_config->cpu_transcoder = TRANSCODER_EDP;
 	}
 
-	if (!intel_display_power_enabled(dev,
+	if (!intel_display_power_enabled(dev_priv,
 			POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
 		return false;
 
@@ -7014,7 +7014,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
 	intel_get_pipe_timings(crtc, pipe_config);
 
 	pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
-	if (intel_display_power_enabled(dev, pfit_domain))
+	if (intel_display_power_enabled(dev_priv, pfit_domain))
 		ironlake_get_pfit_config(crtc, pipe_config);
 
 	if (IS_HASWELL(dev))
@@ -11602,7 +11602,8 @@ intel_display_capture_error_state(struct drm_device *dev)
 
 	for_each_pipe(i) {
 		error->pipe[i].power_domain_on =
-			intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
+			intel_display_power_enabled_sw(dev_priv,
+						       POWER_DOMAIN_PIPE(i));
 		if (!error->pipe[i].power_domain_on)
 			continue;
 
@@ -11640,7 +11641,7 @@ intel_display_capture_error_state(struct drm_device *dev)
 		enum transcoder cpu_transcoder = transcoders[i];
 
 		error->transcoder[i].power_domain_on =
-			intel_display_power_enabled_sw(dev,
+			intel_display_power_enabled_sw(dev_priv,
 				POWER_DOMAIN_TRANSCODER(cpu_transcoder));
 		if (!error->transcoder[i].power_domain_on)
 			continue;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index a4ffc02..6042797 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -732,7 +732,7 @@ ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
 bool intel_crtc_active(struct drm_crtc *crtc);
 void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
-void intel_display_set_init_power(struct drm_device *dev, bool enable);
+void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
 int valleyview_get_vco(struct drm_i915_private *dev_priv);
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_config *pipe_config);
@@ -871,18 +871,17 @@ bool intel_fbc_enabled(struct drm_device *dev);
 void intel_update_fbc(struct drm_device *dev);
 void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
 void intel_gpu_ips_teardown(void);
-int intel_power_domains_init(struct drm_device *dev);
-void intel_power_domains_remove(struct drm_device *dev);
-bool intel_display_power_enabled(struct drm_device *dev,
+int intel_power_domains_init(struct drm_i915_private *);
+void intel_power_domains_remove(struct drm_i915_private *);
+bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
 				 enum intel_display_power_domain domain);
-bool intel_display_power_enabled_sw(struct drm_device *dev,
+bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
 				    enum intel_display_power_domain domain);
-void intel_display_power_get(struct drm_device *dev,
+void intel_display_power_get(struct drm_i915_private *dev_priv,
 			     enum intel_display_power_domain domain);
-void intel_display_power_put(struct drm_device *dev,
+void intel_display_power_put(struct drm_i915_private *dev_priv,
 			     enum intel_display_power_domain domain);
-void intel_power_domains_init_hw(struct drm_device *dev);
-void intel_set_power_well(struct drm_device *dev, bool enable);
+void intel_power_domains_init_hw(struct drm_i915_private *dev_priv);
 void intel_enable_gt_powersave(struct drm_device *dev);
 void intel_disable_gt_powersave(struct drm_device *dev);
 void ironlake_teardown_rc6(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index c8347ae..aa9c2df 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5169,19 +5169,16 @@ void intel_suspend_hw(struct drm_device *dev)
  * enable it, so check if it's enabled and also check if we've requested it to
  * be enabled.
  */
-static bool hsw_power_well_enabled(struct drm_device *dev,
+static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
 				   struct i915_power_well *power_well)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	return I915_READ(HSW_PWR_WELL_DRIVER) ==
 		     (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
 }
 
-bool intel_display_power_enabled_sw(struct drm_device *dev,
+bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
 				    enum intel_display_power_domain domain)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_power_domains *power_domains;
 
 	power_domains = &dev_priv->power_domains;
@@ -5189,10 +5186,9 @@ bool intel_display_power_enabled_sw(struct drm_device *dev,
 	return power_domains->domain_use_count[domain];
 }
 
-bool intel_display_power_enabled(struct drm_device *dev,
+bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
 				 enum intel_display_power_domain domain)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_power_domains *power_domains;
 	struct i915_power_well *power_well;
 	bool is_enabled;
@@ -5207,7 +5203,7 @@ bool intel_display_power_enabled(struct drm_device *dev,
 		if (power_well->always_on)
 			continue;
 
-		if (!power_well->is_enabled(dev, power_well)) {
+		if (!power_well->is_enabled(dev_priv, power_well)) {
 			is_enabled = false;
 			break;
 		}
@@ -5273,10 +5269,9 @@ static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 
-static void hsw_set_power_well(struct drm_device *dev,
+static void hsw_set_power_well(struct drm_i915_private *dev_priv,
 			       struct i915_power_well *power_well, bool enable)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	bool is_enabled, enable_requested;
 	uint32_t tmp;
 
@@ -5310,35 +5305,30 @@ static void hsw_set_power_well(struct drm_device *dev,
 	}
 }
 
-static void __intel_power_well_get(struct drm_device *dev,
+static void __intel_power_well_get(struct drm_i915_private *dev_priv,
 				   struct i915_power_well *power_well)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	if (!power_well->count++ && power_well->set) {
 		hsw_disable_package_c8(dev_priv);
-		power_well->set(dev, power_well, true);
+		power_well->set(dev_priv, power_well, true);
 	}
 }
 
-static void __intel_power_well_put(struct drm_device *dev,
+static void __intel_power_well_put(struct drm_i915_private *dev_priv,
 				   struct i915_power_well *power_well)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	WARN_ON(!power_well->count);
 
 	if (!--power_well->count && power_well->set &&
 	    i915.disable_power_well) {
-		power_well->set(dev, power_well, false);
+		power_well->set(dev_priv, power_well, false);
 		hsw_enable_package_c8(dev_priv);
 	}
 }
 
-void intel_display_power_get(struct drm_device *dev,
+void intel_display_power_get(struct drm_i915_private *dev_priv,
 			     enum intel_display_power_domain domain)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_power_domains *power_domains;
 	struct i915_power_well *power_well;
 	int i;
@@ -5348,17 +5338,16 @@ void intel_display_power_get(struct drm_device *dev,
 	mutex_lock(&power_domains->lock);
 
 	for_each_power_well(i, power_well, BIT(domain), power_domains)
-		__intel_power_well_get(dev, power_well);
+		__intel_power_well_get(dev_priv, power_well);
 
 	power_domains->domain_use_count[domain]++;
 
 	mutex_unlock(&power_domains->lock);
 }
 
-void intel_display_power_put(struct drm_device *dev,
+void intel_display_power_put(struct drm_i915_private *dev_priv,
 			     enum intel_display_power_domain domain)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_power_domains *power_domains;
 	struct i915_power_well *power_well;
 	int i;
@@ -5371,7 +5360,7 @@ void intel_display_power_put(struct drm_device *dev,
 	power_domains->domain_use_count[domain]--;
 
 	for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
-		__intel_power_well_put(dev, power_well);
+		__intel_power_well_put(dev_priv, power_well);
 
 	mutex_unlock(&power_domains->lock);
 }
@@ -5388,7 +5377,7 @@ void i915_request_power_well(void)
 
 	dev_priv = container_of(hsw_pwr, struct drm_i915_private,
 				power_domains);
-	intel_display_power_get(dev_priv->dev, POWER_DOMAIN_AUDIO);
+	intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
 }
 EXPORT_SYMBOL_GPL(i915_request_power_well);
 
@@ -5402,7 +5391,7 @@ void i915_release_power_well(void)
 
 	dev_priv = container_of(hsw_pwr, struct drm_i915_private,
 				power_domains);
-	intel_display_power_put(dev_priv->dev, POWER_DOMAIN_AUDIO);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
 }
 EXPORT_SYMBOL_GPL(i915_release_power_well);
 
@@ -5447,9 +5436,8 @@ static struct i915_power_well bdw_power_wells[] = {
 	(power_domains)->power_well_count = ARRAY_SIZE(__power_wells);	\
 })
 
-int intel_power_domains_init(struct drm_device *dev)
+int intel_power_domains_init(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
 
 	mutex_init(&power_domains->lock);
@@ -5458,10 +5446,10 @@ int intel_power_domains_init(struct drm_device *dev)
 	 * The enabling order will be from lower to higher indexed wells,
 	 * the disabling order is reversed.
 	 */
-	if (IS_HASWELL(dev)) {
+	if (IS_HASWELL(dev_priv->dev)) {
 		set_power_wells(power_domains, hsw_power_wells);
 		hsw_pwr = power_domains;
-	} else if (IS_BROADWELL(dev)) {
+	} else if (IS_BROADWELL(dev_priv->dev)) {
 		set_power_wells(power_domains, bdw_power_wells);
 		hsw_pwr = power_domains;
 	} else {
@@ -5471,14 +5459,13 @@ int intel_power_domains_init(struct drm_device *dev)
 	return 0;
 }
 
-void intel_power_domains_remove(struct drm_device *dev)
+void intel_power_domains_remove(struct drm_i915_private *dev_priv)
 {
 	hsw_pwr = NULL;
 }
 
-static void intel_power_domains_resume(struct drm_device *dev)
+static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_power_domains *power_domains = &dev_priv->power_domains;
 	struct i915_power_well *power_well;
 	int i;
@@ -5486,7 +5473,7 @@ static void intel_power_domains_resume(struct drm_device *dev)
 	mutex_lock(&power_domains->lock);
 	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
 		if (power_well->set)
-			power_well->set(dev, power_well, power_well->count > 0);
+			power_well->set(dev_priv, power_well, power_well->count > 0);
 	}
 	mutex_unlock(&power_domains->lock);
 }
@@ -5497,15 +5484,13 @@ static void intel_power_domains_resume(struct drm_device *dev)
  * to be enabled, and it will only be disabled if none of the registers is
  * requesting it to be enabled.
  */
-void intel_power_domains_init_hw(struct drm_device *dev)
+void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
 	/* For now, we need the power well to be always enabled. */
-	intel_display_set_init_power(dev, true);
-	intel_power_domains_resume(dev);
+	intel_display_set_init_power(dev_priv, true);
+	intel_power_domains_resume(dev_priv);
 
-	if (!(IS_HASWELL(dev) || IS_BROADWELL(dev)))
+	if (!(IS_HASWELL(dev_priv->dev) || IS_BROADWELL(dev_priv->dev)))
 		return;
 
 	/* We're taking over the BIOS, so clear any requests made by it since
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
  2014-02-17 22:02 ` [PATCH 01/19] drm/i915: use drm_i915_private everywhere in the power domain api Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:17   ` Jesse Barnes
  2014-02-24 13:23   ` Paulo Zanoni
  2014-02-17 22:02 ` [PATCH 03/19] drm/i915: move modeset_update_power_wells earlier Imre Deak
                   ` (16 subsequent siblings)
  18 siblings, 2 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

These functions are used only by a single call site and are simple
enough to just fold them in.

No functional change.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 37 +++++++++++++------------------------
 1 file changed, 13 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index aa9c2df..db48d55 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5305,27 +5305,6 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
 	}
 }
 
-static void __intel_power_well_get(struct drm_i915_private *dev_priv,
-				   struct i915_power_well *power_well)
-{
-	if (!power_well->count++ && power_well->set) {
-		hsw_disable_package_c8(dev_priv);
-		power_well->set(dev_priv, power_well, true);
-	}
-}
-
-static void __intel_power_well_put(struct drm_i915_private *dev_priv,
-				   struct i915_power_well *power_well)
-{
-	WARN_ON(!power_well->count);
-
-	if (!--power_well->count && power_well->set &&
-	    i915.disable_power_well) {
-		power_well->set(dev_priv, power_well, false);
-		hsw_enable_package_c8(dev_priv);
-	}
-}
-
 void intel_display_power_get(struct drm_i915_private *dev_priv,
 			     enum intel_display_power_domain domain)
 {
@@ -5338,7 +5317,10 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
 	mutex_lock(&power_domains->lock);
 
 	for_each_power_well(i, power_well, BIT(domain), power_domains)
-		__intel_power_well_get(dev_priv, power_well);
+		if (!power_well->count++ && power_well->set) {
+			hsw_disable_package_c8(dev_priv);
+			power_well->set(dev_priv, power_well, true);
+		}
 
 	power_domains->domain_use_count[domain]++;
 
@@ -5359,8 +5341,15 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
 	WARN_ON(!power_domains->domain_use_count[domain]);
 	power_domains->domain_use_count[domain]--;
 
-	for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
-		__intel_power_well_put(dev_priv, power_well);
+	for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
+		WARN_ON(!power_well->count);
+
+		if (!--power_well->count && power_well->set &&
+				i915.disable_power_well) {
+			power_well->set(dev_priv, power_well, false);
+			hsw_enable_package_c8(dev_priv);
+		}
+	}
 
 	mutex_unlock(&power_domains->lock);
 }
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 03/19] drm/i915: move modeset_update_power_wells earlier
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
  2014-02-17 22:02 ` [PATCH 01/19] drm/i915: use drm_i915_private everywhere in the power domain api Imre Deak
  2014-02-17 22:02 ` [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:18   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 04/19] drm/i915: move power domain macros to intel_pm.c Imre Deak
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

These functions will be needed by the valleyview specific power well
update functionality added in an upcoming patch, so move them earlier.

No functional change.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 140 +++++++++++++++++------------------
 1 file changed, 70 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 17c2033..fa50f6e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3953,6 +3953,76 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
 	I915_WRITE(BCLRPAT(crtc->pipe), 0);
 }
 
+#define for_each_power_domain(domain, mask)				\
+	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
+		if ((1 << (domain)) & (mask))
+
+static unsigned long get_pipe_power_domains(struct drm_device *dev,
+					    enum pipe pipe, bool pfit_enabled)
+{
+	unsigned long mask;
+	enum transcoder transcoder;
+
+	transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
+
+	mask = BIT(POWER_DOMAIN_PIPE(pipe));
+	mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
+	if (pfit_enabled)
+		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
+
+	return mask;
+}
+
+void intel_display_set_init_power(struct drm_i915_private *dev_priv,
+				  bool enable)
+{
+	if (dev_priv->power_domains.init_power_on == enable)
+		return;
+
+	if (enable)
+		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
+	else
+		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
+
+	dev_priv->power_domains.init_power_on = enable;
+}
+
+static void modeset_update_power_wells(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
+	struct intel_crtc *crtc;
+
+	/*
+	 * First get all needed power domains, then put all unneeded, to avoid
+	 * any unnecessary toggling of the power wells.
+	 */
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
+		enum intel_display_power_domain domain;
+
+		if (!crtc->base.enabled)
+			continue;
+
+		pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
+						crtc->pipe,
+						crtc->config.pch_pfit.enabled);
+
+		for_each_power_domain(domain, pipe_domains[crtc->pipe])
+			intel_display_power_get(dev_priv, domain);
+	}
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
+		enum intel_display_power_domain domain;
+
+		for_each_power_domain(domain, crtc->enabled_power_domains)
+			intel_display_power_put(dev_priv, domain);
+
+		crtc->enabled_power_domains = pipe_domains[crtc->pipe];
+	}
+
+	intel_display_set_init_power(dev_priv, false);
+}
+
 int valleyview_get_vco(struct drm_i915_private *dev_priv)
 {
 	int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
@@ -6838,76 +6908,6 @@ static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv)
 	mutex_unlock(&dev_priv->pc8.lock);
 }
 
-#define for_each_power_domain(domain, mask)				\
-	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
-		if ((1 << (domain)) & (mask))
-
-static unsigned long get_pipe_power_domains(struct drm_device *dev,
-					    enum pipe pipe, bool pfit_enabled)
-{
-	unsigned long mask;
-	enum transcoder transcoder;
-
-	transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
-
-	mask = BIT(POWER_DOMAIN_PIPE(pipe));
-	mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
-	if (pfit_enabled)
-		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
-
-	return mask;
-}
-
-void intel_display_set_init_power(struct drm_i915_private *dev_priv,
-				  bool enable)
-{
-	if (dev_priv->power_domains.init_power_on == enable)
-		return;
-
-	if (enable)
-		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
-	else
-		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
-
-	dev_priv->power_domains.init_power_on = enable;
-}
-
-static void modeset_update_power_wells(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
-	struct intel_crtc *crtc;
-
-	/*
-	 * First get all needed power domains, then put all unneeded, to avoid
-	 * any unnecessary toggling of the power wells.
-	 */
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
-		enum intel_display_power_domain domain;
-
-		if (!crtc->base.enabled)
-			continue;
-
-		pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
-						crtc->pipe,
-						crtc->config.pch_pfit.enabled);
-
-		for_each_power_domain(domain, pipe_domains[crtc->pipe])
-			intel_display_power_get(dev_priv, domain);
-	}
-
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
-		enum intel_display_power_domain domain;
-
-		for_each_power_domain(domain, crtc->enabled_power_domains)
-			intel_display_power_put(dev_priv, domain);
-
-		crtc->enabled_power_domains = pipe_domains[crtc->pipe];
-	}
-
-	intel_display_set_init_power(dev_priv, false);
-}
-
 static void haswell_modeset_global_resources(struct drm_device *dev)
 {
 	modeset_update_power_wells(dev);
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 04/19] drm/i915: move power domain macros to intel_pm.c
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (2 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 03/19] drm/i915: move modeset_update_power_wells earlier Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:21   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 05/19] drm/i915: power domains: add power well ops Imre Deak
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

These macros are used only locally, so move them to the .c file.

Also since logically the init power domain should be part of all power
wells add it to the always-on power wells too for consistency. Since
always-on power wells have noop handlers, this doesn't change the
functionality.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h | 10 ----------
 drivers/gpu/drm/i915/intel_pm.c | 21 +++++++++++++++++++--
 2 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 796f971..de0c0e0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -121,8 +121,6 @@ enum intel_display_power_domain {
 	POWER_DOMAIN_NUM,
 };
 
-#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
-
 #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
 #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
 		((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
@@ -130,14 +128,6 @@ enum intel_display_power_domain {
 	((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
 	 (tran) + POWER_DOMAIN_TRANSCODER_A)
 
-#define HSW_ALWAYS_ON_POWER_DOMAINS (		\
-	BIT(POWER_DOMAIN_PIPE_A) |		\
-	BIT(POWER_DOMAIN_TRANSCODER_EDP))
-#define BDW_ALWAYS_ON_POWER_DOMAINS (		\
-	BIT(POWER_DOMAIN_PIPE_A) |		\
-	BIT(POWER_DOMAIN_TRANSCODER_EDP) |	\
-	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
-
 enum hpd_pin {
 	HPD_NONE = 0,
 	HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index db48d55..9a608f1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5384,6 +5384,23 @@ void i915_release_power_well(void)
 }
 EXPORT_SYMBOL_GPL(i915_release_power_well);
 
+#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
+
+#define HSW_ALWAYS_ON_POWER_DOMAINS (			\
+	BIT(POWER_DOMAIN_PIPE_A) |			\
+	BIT(POWER_DOMAIN_TRANSCODER_EDP) |		\
+	BIT(POWER_DOMAIN_INIT))
+#define HSW_DISPLAY_POWER_DOMAINS (				\
+	(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |	\
+	BIT(POWER_DOMAIN_INIT))
+
+#define BDW_ALWAYS_ON_POWER_DOMAINS (			\
+	HSW_ALWAYS_ON_POWER_DOMAINS |			\
+	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
+#define BDW_DISPLAY_POWER_DOMAINS (				\
+	(POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |	\
+	BIT(POWER_DOMAIN_INIT))
+
 static struct i915_power_well i9xx_always_on_power_well[] = {
 	{
 		.name = "always-on",
@@ -5400,7 +5417,7 @@ static struct i915_power_well hsw_power_wells[] = {
 	},
 	{
 		.name = "display",
-		.domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS,
+		.domains = HSW_DISPLAY_POWER_DOMAINS,
 		.is_enabled = hsw_power_well_enabled,
 		.set = hsw_set_power_well,
 	},
@@ -5414,7 +5431,7 @@ static struct i915_power_well bdw_power_wells[] = {
 	},
 	{
 		.name = "display",
-		.domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS,
+		.domains = BDW_DISPLAY_POWER_DOMAINS,
 		.is_enabled = hsw_power_well_enabled,
 		.set = hsw_set_power_well,
 	},
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 05/19] drm/i915: power domains: add power well ops
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (3 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 04/19] drm/i915: move power domain macros to intel_pm.c Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:26   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 06/19] drm/i915: remove power_well->always_on flag Imre Deak
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

Split the 'set' power well handler into an 'enable', 'disable' and
'sync_hw' handler. This maps more conveniently to higher level
operations, for example it allows us to push the hsw package c8 handling
into the corresponding hsw/bdw enable/disable handlers and the hsw BIOS
hand-over setting into the hsw/bdw sync_hw handler.

No functional change.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h | 35 +++++++++++++++++---
 drivers/gpu/drm/i915/intel_pm.c | 73 +++++++++++++++++++++++++++--------------
 2 files changed, 80 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index de0c0e0..8c8635e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1006,6 +1006,36 @@ struct intel_ilk_power_mgmt {
 	struct drm_i915_gem_object *renderctx;
 };
 
+struct drm_i915_private;
+struct i915_power_well;
+
+struct i915_power_well_ops {
+	/*
+	 * Synchronize the well's hw state to match the current sw state, for
+	 * example enable/disable it based on the current refcount. Called
+	 * during driver init and resume time, possibly after first calling
+	 * the enable/disable handlers.
+	 */
+	void (*sync_hw)(struct drm_i915_private *dev_priv,
+		        struct i915_power_well *power_well);
+	/*
+	 * Enable the well and resources that depend on it (for example
+	 * interrupts located on the well). Called after the 0->1 refcount
+	 * transition.
+	 */
+	void (*enable)(struct drm_i915_private *dev_priv,
+		       struct i915_power_well *power_well);
+	/*
+	 * Disable the well and resources that depend on it. Called after
+	 * the 1->0 refcount transition.
+	 */
+	void (*disable)(struct drm_i915_private *dev_priv,
+		        struct i915_power_well *power_well);
+	/* Returns the hw enabled state. */
+	bool (*is_enabled)(struct drm_i915_private *dev_priv,
+			   struct i915_power_well *power_well);
+};
+
 /* Power well structure for haswell */
 struct i915_power_well {
 	const char *name;
@@ -1014,10 +1044,7 @@ struct i915_power_well {
 	int count;
 	unsigned long domains;
 	void *data;
-	void (*set)(struct drm_i915_private *dev_priv, struct i915_power_well *power_well,
-		    bool enable);
-	bool (*is_enabled)(struct drm_i915_private *dev_priv,
-			   struct i915_power_well *power_well);
+	const struct i915_power_well_ops *ops;
 };
 
 struct i915_power_domains {
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 9a608f1..7866426 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5203,7 +5203,7 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
 		if (power_well->always_on)
 			continue;
 
-		if (!power_well->is_enabled(dev_priv, power_well)) {
+		if (!power_well->ops->is_enabled(dev_priv, power_well)) {
 			is_enabled = false;
 			break;
 		}
@@ -5305,6 +5305,33 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
 	}
 }
 
+static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
+			           struct i915_power_well *power_well)
+{
+	hsw_set_power_well(dev_priv, power_well, power_well->count > 0);
+
+	/*
+	 * We're taking over the BIOS, so clear any requests made by it since
+	 * the driver is in charge now.
+	 */
+	if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
+		I915_WRITE(HSW_PWR_WELL_BIOS, 0);
+}
+
+static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
+				  struct i915_power_well *power_well)
+{
+	hsw_disable_package_c8(dev_priv);
+	hsw_set_power_well(dev_priv, power_well, true);
+}
+
+static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
+				   struct i915_power_well *power_well)
+{
+	hsw_set_power_well(dev_priv, power_well, false);
+	hsw_enable_package_c8(dev_priv);
+}
+
 void intel_display_power_get(struct drm_i915_private *dev_priv,
 			     enum intel_display_power_domain domain)
 {
@@ -5317,10 +5344,8 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
 	mutex_lock(&power_domains->lock);
 
 	for_each_power_well(i, power_well, BIT(domain), power_domains)
-		if (!power_well->count++ && power_well->set) {
-			hsw_disable_package_c8(dev_priv);
-			power_well->set(dev_priv, power_well, true);
-		}
+		if (!power_well->count++ && power_well->ops->enable)
+			power_well->ops->enable(dev_priv, power_well);
 
 	power_domains->domain_use_count[domain]++;
 
@@ -5344,11 +5369,9 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
 	for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
 		WARN_ON(!power_well->count);
 
-		if (!--power_well->count && power_well->set &&
-				i915.disable_power_well) {
-			power_well->set(dev_priv, power_well, false);
-			hsw_enable_package_c8(dev_priv);
-		}
+		if (!--power_well->count && power_well->ops->disable &&
+		    i915.disable_power_well)
+			power_well->ops->disable(dev_priv, power_well);
 	}
 
 	mutex_unlock(&power_domains->lock);
@@ -5401,25 +5424,35 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
 	(POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |	\
 	BIT(POWER_DOMAIN_INIT))
 
+static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { };
+
 static struct i915_power_well i9xx_always_on_power_well[] = {
 	{
 		.name = "always-on",
 		.always_on = 1,
 		.domains = POWER_DOMAIN_MASK,
+		.ops = &i9xx_always_on_power_well_ops,
 	},
 };
 
+static const struct i915_power_well_ops hsw_power_well_ops = {
+	.sync_hw = hsw_power_well_sync_hw,
+	.enable = hsw_power_well_enable,
+	.disable = hsw_power_well_disable,
+	.is_enabled = hsw_power_well_enabled,
+};
+
 static struct i915_power_well hsw_power_wells[] = {
 	{
 		.name = "always-on",
 		.always_on = 1,
 		.domains = HSW_ALWAYS_ON_POWER_DOMAINS,
+		.ops = &i9xx_always_on_power_well_ops,
 	},
 	{
 		.name = "display",
 		.domains = HSW_DISPLAY_POWER_DOMAINS,
-		.is_enabled = hsw_power_well_enabled,
-		.set = hsw_set_power_well,
+		.ops = &hsw_power_well_ops,
 	},
 };
 
@@ -5428,12 +5461,12 @@ static struct i915_power_well bdw_power_wells[] = {
 		.name = "always-on",
 		.always_on = 1,
 		.domains = BDW_ALWAYS_ON_POWER_DOMAINS,
+		.ops = &i9xx_always_on_power_well_ops,
 	},
 	{
 		.name = "display",
 		.domains = BDW_DISPLAY_POWER_DOMAINS,
-		.is_enabled = hsw_power_well_enabled,
-		.set = hsw_set_power_well,
+		.ops = &hsw_power_well_ops,
 	},
 };
 
@@ -5478,8 +5511,8 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
 
 	mutex_lock(&power_domains->lock);
 	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
-		if (power_well->set)
-			power_well->set(dev_priv, power_well, power_well->count > 0);
+		if (power_well->ops->sync_hw)
+			power_well->ops->sync_hw(dev_priv, power_well);
 	}
 	mutex_unlock(&power_domains->lock);
 }
@@ -5495,14 +5528,6 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
 	/* For now, we need the power well to be always enabled. */
 	intel_display_set_init_power(dev_priv, true);
 	intel_power_domains_resume(dev_priv);
-
-	if (!(IS_HASWELL(dev_priv->dev) || IS_BROADWELL(dev_priv->dev)))
-		return;
-
-	/* We're taking over the BIOS, so clear any requests made by it since
-	 * the driver is in charge now. */
-	if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
-		I915_WRITE(HSW_PWR_WELL_BIOS, 0);
 }
 
 /* Disables PC8 so we can use the GMBUS and DP AUX interrupts. */
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 06/19] drm/i915: remove power_well->always_on flag
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (4 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 05/19] drm/i915: power domains: add power well ops Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:27   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 07/19] drm/i915: add port power domains Imre Deak
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

An always-on power well can be already recognized by the lack of
is_enabled handler, so just depend on that. Suggested by Daniel.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h | 1 -
 drivers/gpu/drm/i915/intel_pm.c | 5 +----
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8c8635e..eaa9210 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1039,7 +1039,6 @@ struct i915_power_well_ops {
 /* Power well structure for haswell */
 struct i915_power_well {
 	const char *name;
-	bool always_on;
 	/* power well enable/disable usage count */
 	int count;
 	unsigned long domains;
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 7866426..faaa4ec 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5200,7 +5200,7 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
 
 	mutex_lock(&power_domains->lock);
 	for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
-		if (power_well->always_on)
+		if (!power_well->ops->is_enabled)
 			continue;
 
 		if (!power_well->ops->is_enabled(dev_priv, power_well)) {
@@ -5429,7 +5429,6 @@ static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { };
 static struct i915_power_well i9xx_always_on_power_well[] = {
 	{
 		.name = "always-on",
-		.always_on = 1,
 		.domains = POWER_DOMAIN_MASK,
 		.ops = &i9xx_always_on_power_well_ops,
 	},
@@ -5445,7 +5444,6 @@ static const struct i915_power_well_ops hsw_power_well_ops = {
 static struct i915_power_well hsw_power_wells[] = {
 	{
 		.name = "always-on",
-		.always_on = 1,
 		.domains = HSW_ALWAYS_ON_POWER_DOMAINS,
 		.ops = &i9xx_always_on_power_well_ops,
 	},
@@ -5459,7 +5457,6 @@ static struct i915_power_well hsw_power_wells[] = {
 static struct i915_power_well bdw_power_wells[] = {
 	{
 		.name = "always-on",
-		.always_on = 1,
 		.domains = BDW_ALWAYS_ON_POWER_DOMAINS,
 		.ops = &i9xx_always_on_power_well_ops,
 	},
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 07/19] drm/i915: add port power domains
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (5 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 06/19] drm/i915: remove power_well->always_on flag Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:31   ` Jesse Barnes
  2014-03-05 10:11   ` Daniel Vetter
  2014-02-17 22:02 ` [PATCH 08/19] drm/i915: get port power domain in connector detect Imre Deak
                   ` (11 subsequent siblings)
  18 siblings, 2 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

Parts that poke port specific HW blocks like the encoder HW state
readout or connector hotplug detect code need a way to check whether
required power domains are on or enable/disable these. For this purpose
add a set of power domains that refer to the port HW blocks. Get the
proper port power domains during modeset.

For now when requesting the power domain for a DDI port get it for a 4
lane configuration. This can be optimized later to request only the 2
lane power domain, when proper support is added on the VLV PHY side for
this. Atm, the PHY setup code assumes a 4 lane config in all cases.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_debugfs.c  | 22 ++++++++++++++++
 drivers/gpu/drm/i915/i915_drv.h      | 11 ++++++++
 drivers/gpu/drm/i915/intel_display.c | 51 ++++++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_drv.h     |  2 ++
 drivers/gpu/drm/i915/intel_pm.c      |  9 +++++++
 5 files changed, 90 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index d90a707..14c7730 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2030,6 +2030,28 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
 		return "TRANSCODER_C";
 	case POWER_DOMAIN_TRANSCODER_EDP:
 		return "TRANSCODER_EDP";
+	case POWER_DOMAIN_PORT_DDI_A_2_LANES:
+		return "PORT_DDI_A_2_LANES";
+	case POWER_DOMAIN_PORT_DDI_A_4_LANES:
+		return "PORT_DDI_A_4_LANES";
+	case POWER_DOMAIN_PORT_DDI_B_2_LANES:
+		return "PORT_DDI_B_2_LANES";
+	case POWER_DOMAIN_PORT_DDI_B_4_LANES:
+		return "PORT_DDI_B_4_LANES";
+	case POWER_DOMAIN_PORT_DDI_C_2_LANES:
+		return "PORT_DDI_C_2_LANES";
+	case POWER_DOMAIN_PORT_DDI_C_4_LANES:
+		return "PORT_DDI_C_4_LANES";
+	case POWER_DOMAIN_PORT_DDI_D_2_LANES:
+		return "PORT_DDI_D_2_LANES";
+	case POWER_DOMAIN_PORT_DDI_D_4_LANES:
+		return "PORT_DDI_D_4_LANES";
+	case POWER_DOMAIN_PORT_DSI:
+		return "PORT_DSI";
+	case POWER_DOMAIN_PORT_CRT:
+		return "PORT_CRT";
+	case POWER_DOMAIN_PORT_OTHER:
+		return "PORT_OTHER";
 	case POWER_DOMAIN_VGA:
 		return "VGA";
 	case POWER_DOMAIN_AUDIO:
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index eaa9210..76bd03a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -114,6 +114,17 @@ enum intel_display_power_domain {
 	POWER_DOMAIN_TRANSCODER_B,
 	POWER_DOMAIN_TRANSCODER_C,
 	POWER_DOMAIN_TRANSCODER_EDP,
+	POWER_DOMAIN_PORT_DDI_A_2_LANES,
+	POWER_DOMAIN_PORT_DDI_A_4_LANES,
+	POWER_DOMAIN_PORT_DDI_B_2_LANES,
+	POWER_DOMAIN_PORT_DDI_B_4_LANES,
+	POWER_DOMAIN_PORT_DDI_C_2_LANES,
+	POWER_DOMAIN_PORT_DDI_C_4_LANES,
+	POWER_DOMAIN_PORT_DDI_D_2_LANES,
+	POWER_DOMAIN_PORT_DDI_D_4_LANES,
+	POWER_DOMAIN_PORT_DSI,
+	POWER_DOMAIN_PORT_CRT,
+	POWER_DOMAIN_PORT_OTHER,
 	POWER_DOMAIN_VGA,
 	POWER_DOMAIN_AUDIO,
 	POWER_DOMAIN_INIT,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fa50f6e..7ef06fa 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3957,9 +3957,49 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
 	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
 		if ((1 << (domain)) & (mask))
 
-static unsigned long get_pipe_power_domains(struct drm_device *dev,
-					    enum pipe pipe, bool pfit_enabled)
+enum intel_display_power_domain
+intel_display_port_power_domain(struct intel_encoder *intel_encoder)
 {
+	struct drm_device *dev = intel_encoder->base.dev;
+	struct intel_digital_port *intel_dig_port;
+
+	switch (intel_encoder->type) {
+	case INTEL_OUTPUT_UNKNOWN:
+		/* Only DDI platforms should ever use this output type */
+		WARN_ON_ONCE(!HAS_DDI(dev));
+	case INTEL_OUTPUT_DISPLAYPORT:
+	case INTEL_OUTPUT_HDMI:
+	case INTEL_OUTPUT_EDP:
+		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
+		switch (intel_dig_port->port) {
+		case PORT_A:
+			return POWER_DOMAIN_PORT_DDI_A_4_LANES;
+		case PORT_B:
+			return POWER_DOMAIN_PORT_DDI_B_4_LANES;
+		case PORT_C:
+			return POWER_DOMAIN_PORT_DDI_C_4_LANES;
+		case PORT_D:
+			return POWER_DOMAIN_PORT_DDI_D_4_LANES;
+		default:
+			WARN_ON_ONCE(1);
+			return POWER_DOMAIN_PORT_OTHER;
+		}
+	case INTEL_OUTPUT_ANALOG:
+		return POWER_DOMAIN_PORT_CRT;
+	case INTEL_OUTPUT_DSI:
+		return POWER_DOMAIN_PORT_DSI;
+	default:
+		return POWER_DOMAIN_PORT_OTHER;
+	}
+}
+
+static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_encoder *intel_encoder;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	enum pipe pipe = intel_crtc->pipe;
+	bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
 	unsigned long mask;
 	enum transcoder transcoder;
 
@@ -3970,6 +4010,9 @@ static unsigned long get_pipe_power_domains(struct drm_device *dev,
 	if (pfit_enabled)
 		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
 
+	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
+		mask |= BIT(intel_display_port_power_domain(intel_encoder));
+
 	return mask;
 }
 
@@ -4003,9 +4046,7 @@ static void modeset_update_power_wells(struct drm_device *dev)
 		if (!crtc->base.enabled)
 			continue;
 
-		pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
-						crtc->pipe,
-						crtc->config.pch_pfit.enabled);
+		pipe_domains[crtc->pipe] = get_crtc_power_domains(&crtc->base);
 
 		for_each_power_domain(domain, pipe_domains[crtc->pipe])
 			intel_display_power_get(dev_priv, domain);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 6042797..e31eb1e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -733,6 +733,8 @@ bool intel_crtc_active(struct drm_crtc *crtc);
 void hsw_enable_ips(struct intel_crtc *crtc);
 void hsw_disable_ips(struct intel_crtc *crtc);
 void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
+enum intel_display_power_domain
+intel_display_port_power_domain(struct intel_encoder *intel_encoder);
 int valleyview_get_vco(struct drm_i915_private *dev_priv);
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_config *pipe_config);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index faaa4ec..9cb7ed6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5412,6 +5412,15 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
 #define HSW_ALWAYS_ON_POWER_DOMAINS (			\
 	BIT(POWER_DOMAIN_PIPE_A) |			\
 	BIT(POWER_DOMAIN_TRANSCODER_EDP) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |		\
+	BIT(POWER_DOMAIN_PORT_CRT) |			\
 	BIT(POWER_DOMAIN_INIT))
 #define HSW_DISPLAY_POWER_DOMAINS (				\
 	(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |	\
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 08/19] drm/i915: get port power domain in connector detect
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (6 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 07/19] drm/i915: add port power domains Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-19 12:35   ` Ville Syrjälä
  2014-02-17 22:02 ` [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state Imre Deak
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

The connector detect and get_mode handlers need to access the port
specific HW blocks to read the EDID etc. Get/put the port power domains
around these handlers.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_crt.c | 42 ++++++++++++++++++++++++++++++++--------
 drivers/gpu/drm/i915/intel_dp.c  | 16 ++++++++++++---
 drivers/gpu/drm/i915/intel_dsi.c | 13 ++++++++++++-
 3 files changed, 59 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 9864aa1..2a38429 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -630,7 +630,10 @@ static enum drm_connector_status
 intel_crt_detect(struct drm_connector *connector, bool force)
 {
 	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crt *crt = intel_attached_crt(connector);
+	struct intel_encoder *intel_encoder = &crt->base;
+	enum intel_display_power_domain power_domain;
 	enum drm_connector_status status;
 	struct intel_load_detect_pipe tmp;
 
@@ -638,6 +641,11 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 		      connector->base.id, drm_get_connector_name(connector),
 		      force);
 
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_get(dev_priv, power_domain);
+
+	status = connector_status_connected;
+
 	if (I915_HAS_HOTPLUG(dev)) {
 		/* We can not rely on the HPD pin always being correctly wired
 		 * up, for example many KVM do not pass it through, and so
@@ -645,23 +653,27 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 		 */
 		if (intel_crt_detect_hotplug(connector)) {
 			DRM_DEBUG_KMS("CRT detected via hotplug\n");
-			return connector_status_connected;
+			goto out;
 		} else
 			DRM_DEBUG_KMS("CRT not detected via hotplug\n");
 	}
 
 	if (intel_crt_detect_ddc(connector))
-		return connector_status_connected;
+		goto out;
 
 	/* Load detection is broken on HPD capable machines. Whoever wants a
 	 * broken monitor (without edid) to work behind a broken kvm (that fails
 	 * to have the right resistors for HP detection) needs to fix this up.
 	 * For now just bail out. */
-	if (I915_HAS_HOTPLUG(dev))
-		return connector_status_disconnected;
+	if (I915_HAS_HOTPLUG(dev)) {
+		status = connector_status_disconnected;
+		goto out;
+	}
 
-	if (!force)
-		return connector->status;
+	if (!force) {
+		status = connector->status;
+		goto out;
+	}
 
 	/* for pre-945g platforms use load detect */
 	if (intel_get_load_detect_pipe(connector, NULL, &tmp)) {
@@ -673,6 +685,9 @@ intel_crt_detect(struct drm_connector *connector, bool force)
 	} else
 		status = connector_status_unknown;
 
+out:
+	intel_display_power_put(dev_priv, power_domain);
+
 	return status;
 }
 
@@ -686,17 +701,28 @@ static int intel_crt_get_modes(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crt *crt = intel_attached_crt(connector);
+	struct intel_encoder *intel_encoder = &crt->base;
+	enum intel_display_power_domain power_domain;
 	int ret;
 	struct i2c_adapter *i2c;
 
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_get(dev_priv, power_domain);
+
 	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
 	ret = intel_crt_ddc_get_modes(connector, i2c);
 	if (ret || !IS_G4X(dev))
-		return ret;
+		goto out;
 
 	/* Try to probe digital port for output in DVI-I -> VGA mode. */
 	i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
-	return intel_crt_ddc_get_modes(connector, i2c);
+	ret = intel_crt_ddc_get_modes(connector, i2c);
+
+out:
+	intel_display_power_put(dev_priv, power_domain);
+
+	return ret;
 }
 
 static int intel_crt_set_property(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f53c95c..9c39425 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3224,9 +3224,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	struct drm_device *dev = connector->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum drm_connector_status status;
+	enum intel_display_power_domain power_domain;
 	struct edid *edid = NULL;
 
-	intel_runtime_pm_get(dev_priv);
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_get(dev_priv, power_domain);
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
 		      connector->base.id, drm_get_connector_name(connector));
@@ -3256,23 +3258,31 @@ intel_dp_detect(struct drm_connector *connector, bool force)
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
 	status = connector_status_connected;
-
 out:
-	intel_runtime_pm_put(dev_priv);
+	intel_display_power_put(dev_priv, power_domain);
+
 	return status;
 }
 
 static int intel_dp_get_modes(struct drm_connector *connector)
 {
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	struct intel_connector *intel_connector = to_intel_connector(connector);
 	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
 	int ret;
 
 	/* We should parse the EDID data and find out if it has an audio sink
 	 */
 
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_get(dev_priv, power_domain);
+
 	ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
+	intel_display_power_put(dev_priv, power_domain);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 3ee1db1..63b95bbd 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -488,8 +488,19 @@ static enum drm_connector_status
 intel_dsi_detect(struct drm_connector *connector, bool force)
 {
 	struct intel_dsi *intel_dsi = intel_attached_dsi(connector);
+	struct intel_encoder *intel_encoder = &intel_dsi->base;
+	enum intel_display_power_domain power_domain;
+	enum drm_connector_status connector_status;
+	struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
+
 	DRM_DEBUG_KMS("\n");
-	return intel_dsi->dev.dev_ops->detect(&intel_dsi->dev);
+	power_domain = intel_display_port_power_domain(intel_encoder);
+
+	intel_display_power_get(dev_priv, power_domain);
+	connector_status = intel_dsi->dev.dev_ops->detect(&intel_dsi->dev);
+	intel_display_power_put(dev_priv, power_domain);
+
+	return connector_status;
 }
 
 static int intel_dsi_get_modes(struct drm_connector *connector)
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (7 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 08/19] drm/i915: get port power domain in connector detect Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:36   ` Jesse Barnes
  2014-03-05 10:21   ` Daniel Vetter
  2014-02-17 22:02 ` [PATCH 10/19] drm/i915: check pipe power domain when reading its " Imre Deak
                   ` (9 subsequent siblings)
  18 siblings, 2 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

Since the encoder is tied to its port, we need to make sure the power
domain for that port is on before reading out the encoder HW state.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_ddi.c     |  2 +-
 drivers/gpu/drm/i915/intel_display.c | 23 ++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 2643d3b..f95bc3a 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1110,7 +1110,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
 	enum transcoder cpu_transcoder;
 	uint32_t tmp;
 
-	if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
+	if (!intel_encoder_get_hw_state(intel_encoder, &pipe))
 		return false;
 
 	if (port == PORT_A)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7ef06fa..ce1c00a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4519,7 +4519,7 @@ static void intel_connector_check_state(struct intel_connector *connector)
 		WARN(!encoder->connectors_active,
 		     "encoder->connectors_active not set\n");
 
-		encoder_enabled = encoder->get_hw_state(encoder, &pipe);
+		encoder_enabled = intel_encoder_get_hw_state(encoder, &pipe);
 		WARN(!encoder_enabled, "encoder not enabled\n");
 		if (WARN_ON(!encoder->base.crtc))
 			return;
@@ -4561,7 +4561,7 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)
 	enum pipe pipe = 0;
 	struct intel_encoder *encoder = connector->encoder;
 
-	return encoder->get_hw_state(encoder, &pipe);
+	return intel_encoder_get_hw_state(encoder, &pipe);
 }
 
 static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
@@ -9464,6 +9464,19 @@ check_connector_state(struct drm_device *dev)
 	}
 }
 
+bool intel_encoder_get_hw_state(struct intel_encoder *intel_encoder,
+				enum pipe *pipe)
+{
+	enum intel_display_power_domain power_domain;
+	struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
+
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	if (!intel_display_power_enabled(dev_priv, power_domain))
+		return false;
+
+	return intel_encoder->get_hw_state(intel_encoder, pipe);
+}
+
 static void
 check_encoder_state(struct drm_device *dev)
 {
@@ -9504,7 +9517,7 @@ check_encoder_state(struct drm_device *dev)
 		     "encoder's computed active state doesn't match tracked active state "
 		     "(expected %i, found %i)\n", active, encoder->connectors_active);
 
-		active = encoder->get_hw_state(encoder, &pipe);
+		active = intel_encoder_get_hw_state(encoder, &pipe);
 		WARN(active != encoder->connectors_active,
 		     "encoder's hw state doesn't match sw tracking "
 		     "(expected %i, found %i)\n",
@@ -9571,7 +9584,7 @@ check_crtc_state(struct drm_device *dev)
 			enum pipe pipe;
 			if (encoder->base.crtc != &crtc->base)
 				continue;
-			if (encoder->get_hw_state(encoder, &pipe))
+			if (intel_encoder_get_hw_state(encoder, &pipe))
 				encoder->get_config(encoder, &pipe_config);
 		}
 
@@ -11350,7 +11363,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 			    base.head) {
 		pipe = 0;
 
-		if (encoder->get_hw_state(encoder, &pipe)) {
+		if (intel_encoder_get_hw_state(encoder, &pipe)) {
 			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
 			encoder->base.crtc = &crtc->base;
 			encoder->get_config(encoder, &crtc->config);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index e31eb1e..afc01a4 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -738,6 +738,7 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder);
 int valleyview_get_vco(struct drm_i915_private *dev_priv);
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_config *pipe_config);
+bool intel_encoder_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
 
 /* intel_dp.c */
 void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 10/19] drm/i915: check pipe power domain when reading its hw state
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (8 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:37   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 11/19] drm/i915: vlv: keep first level vblank IRQs masked Imre Deak
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

We can read out the pipe HW state only if the required power domain is
on. If not we consider the pipe to be off.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ce1c00a..e3824f8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9535,6 +9535,18 @@ check_encoder_state(struct drm_device *dev)
 	}
 }
 
+static bool intel_display_get_pipe_config(struct intel_crtc *crtc,
+					  struct intel_crtc_config *pipe_config)
+{
+	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+
+	if (!intel_display_power_enabled(dev_priv,
+					 POWER_DOMAIN_PIPE(crtc->pipe)))
+		return false;
+
+	return dev_priv->display.get_pipe_config(crtc, pipe_config);
+}
+
 static void
 check_crtc_state(struct drm_device *dev)
 {
@@ -9572,8 +9584,7 @@ check_crtc_state(struct drm_device *dev)
 		     "crtc's computed enabled state doesn't match tracked enabled state "
 		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
 
-		active = dev_priv->display.get_pipe_config(crtc,
-							   &pipe_config);
+		active = intel_display_get_pipe_config(crtc, &pipe_config);
 
 		/* hw state is inconsistent with the pipe A quirk */
 		if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
@@ -11328,8 +11339,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
 			    base.head) {
 		memset(&crtc->config, 0, sizeof(crtc->config));
 
-		crtc->active = dev_priv->display.get_pipe_config(crtc,
-								 &crtc->config);
+		crtc->active = intel_display_get_pipe_config(crtc,
+							     &crtc->config);
 
 		crtc->base.enabled = crtc->active;
 		crtc->primary_enabled = crtc->active;
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 11/19] drm/i915: vlv: keep first level vblank IRQs masked
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (9 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 10/19] drm/i915: check pipe power domain when reading its " Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-18 16:54   ` Ville Syrjälä
  2014-02-17 22:02 ` [PATCH 12/19] drm/i915: sanitize PUNIT register macro definitions Imre Deak
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

This is a left-over from

commit b7e634cc8dcd320123199a18bae0937b40dc28b8
Author: Imre Deak <imre.deak@intel.com>
Date:   Tue Feb 4 21:35:45 2014 +0200

drm/i915: vlv: don't unmask IIR[DISPLAY_PIPE_A/B_VBLANK] interrupt

where we stopped unmasking the vblank IRQs, but left them enabled in the
IER register. Disable them in IER too.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f68aee3..75dd0a8 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3026,17 +3026,13 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
 
 	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
 	enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
-		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
-		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
+		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
 
 	/*
 	 *Leave vblank interrupts masked initially.  enable/disable will
 	 * toggle them based on usage.
 	 */
-	dev_priv->irq_mask = (~enable_mask) |
-		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
-		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
+	dev_priv->irq_mask = ~enable_mask;
 
 	I915_WRITE(PORT_HOTPLUG_EN, 0);
 	POSTING_READ(PORT_HOTPLUG_EN);
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 12/19] drm/i915: sanitize PUNIT register macro definitions
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (10 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 11/19] drm/i915: vlv: keep first level vblank IRQs masked Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:46   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 13/19] drm/i915: factor out reset_vblank_counter Imre Deak
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

In the upcoming patches we'll need to access the rest of the fields in
the punit power gating register, so prepare for that.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h     | 29 +++++++++++++++++++++++------
 drivers/gpu/drm/i915/intel_uncore.c |  4 +++-
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2f564ce..5a700e9 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -377,14 +377,31 @@
 #define   DSPFREQSTAT_MASK			(0x3 << DSPFREQSTAT_SHIFT)
 #define   DSPFREQGUAR_SHIFT			14
 #define   DSPFREQGUAR_MASK			(0x3 << DSPFREQGUAR_SHIFT)
+
+enum punit_power_well {
+	PUNIT_POWER_WELL_RENDER			= 0,
+	PUNIT_POWER_WELL_MEDIA			= 1,
+	PUNIT_POWER_WELL_DISP2D			= 3,
+	PUNIT_POWER_WELL_DPIO_CMN_BC		= 5,
+	PUNIT_POWER_WELL_DPIO_TX_B_LANES_01	= 6,
+	PUNIT_POWER_WELL_DPIO_TX_B_LANES_23	= 7,
+	PUNIT_POWER_WELL_DPIO_TX_C_LANES_01	= 8,
+	PUNIT_POWER_WELL_DPIO_TX_C_LANES_23	= 9,
+	PUNIT_POWER_WELL_DPIO_RX0		= 10,
+	PUNIT_POWER_WELL_DPIO_RX1		= 11,
+	PUNIT_POWER_WELL_DPIO_RX2		= 12,
+	PUNIT_POWER_WELL_DPIO_RX3		= 13,
+
+	PUNIT_POWER_WELL_NUM,
+};
+
 #define PUNIT_REG_PWRGT_CTRL			0x60
 #define PUNIT_REG_PWRGT_STATUS			0x61
-#define	  PUNIT_CLK_GATE			1
-#define	  PUNIT_PWR_RESET			2
-#define	  PUNIT_PWR_GATE			3
-#define	  RENDER_PWRGT				(PUNIT_PWR_GATE << 0)
-#define	  MEDIA_PWRGT				(PUNIT_PWR_GATE << 2)
-#define	  DISP2D_PWRGT				(PUNIT_PWR_GATE << 6)
+#define   PUNIT_PWRGT_MASK(power_well)		(3 << ((power_well) * 2))
+#define   PUNIT_PWRGT_PWR_ON(power_well)	(0 << ((power_well) * 2))
+#define   PUNIT_PWRGT_CLK_GATE(power_well)	(1 << ((power_well) * 2))
+#define   PUNIT_PWRGT_RESET(power_well)		(2 << ((power_well) * 2))
+#define   PUNIT_PWRGT_PWR_GATE(power_well)	(3 << ((power_well) * 2))
 
 #define PUNIT_REG_GPU_LFM			0xd3
 #define PUNIT_REG_GPU_FREQ_REQ			0xd4
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index c628414..4aab7c2 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -354,7 +354,9 @@ void intel_uncore_sanitize(struct drm_device *dev)
 		mutex_lock(&dev_priv->rps.hw_lock);
 		reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS);
 
-		if (reg_val & (RENDER_PWRGT | MEDIA_PWRGT | DISP2D_PWRGT))
+		if (reg_val & (PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_RENDER) |
+			       PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_MEDIA) |
+			       PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_DISP2D)))
 			vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, 0x0);
 
 		mutex_unlock(&dev_priv->rps.hw_lock);
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 13/19] drm/i915: factor out reset_vblank_counter
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (11 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 12/19] drm/i915: sanitize PUNIT register macro definitions Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-18 16:55   ` Ville Syrjälä
  2014-02-17 22:02 ` [PATCH 14/19] drm/i915: switch order of power domain init wrt. irq install Imre Deak
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

We need to do the same for other platforms in upcoming patches.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 9cb7ed6..e81e7de 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5249,11 +5249,19 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
 	}
 }
 
+static void reset_vblank_counter(struct drm_device *dev, enum pipe p)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&dev->vbl_lock, irqflags);
+	dev->vblank[p].last = 0;
+	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+}
+
 static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
 	enum pipe p;
-	unsigned long irqflags;
 
 	/*
 	 * After this, the registers on the pipes that are part of the power
@@ -5262,11 +5270,9 @@ static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
 	 *
 	 * FIXME: Should we do this in general in drm_vblank_post_modeset?
 	 */
-	spin_lock_irqsave(&dev->vbl_lock, irqflags);
 	for_each_pipe(p)
 		if (p != PIPE_A)
-			dev->vblank[p].last = 0;
-	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+			reset_vblank_counter(dev, p);
 }
 
 static void hsw_set_power_well(struct drm_i915_private *dev_priv,
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 14/19] drm/i915: switch order of power domain init wrt. irq install
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (12 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 13/19] drm/i915: factor out reset_vblank_counter Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:48   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 15/19] drm/i915: use power domain api to check vga power state Imre Deak
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

On VLV at least the display IRQ register access and functionality
depends on its power well to be on, so move the power domain HW init
before we install the IRQs.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 8177c17..f8f7a59 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1321,12 +1321,12 @@ static int i915_load_modeset_init(struct drm_device *dev)
 	if (ret)
 		goto cleanup_vga_switcheroo;
 
+	intel_power_domains_init_hw(dev_priv);
+
 	ret = drm_irq_install(dev);
 	if (ret)
 		goto cleanup_gem_stolen;
 
-	intel_power_domains_init_hw(dev_priv);
-
 	/* Important: The output setup functions called by modeset_init need
 	 * working irqs for e.g. gmbus and dp aux transfers. */
 	intel_modeset_init(dev);
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 15/19] drm/i915: use power domain api to check vga power state
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (13 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 14/19] drm/i915: switch order of power domain init wrt. irq install Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:51   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 16/19] drm/i915: sanity check power well sw state against hw state Imre Deak
                   ` (3 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

This way we can reuse the check on other platforms too. Also factor out
a version of the function that doesn't check if the power is on, we'll
need to call this from within the power domain framework.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  1 +
 drivers/gpu/drm/i915/intel_display.c | 20 +++++++++++++-------
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 76bd03a..632f9d8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2591,6 +2591,7 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern void intel_modeset_setup_hw_state(struct drm_device *dev,
 					 bool force_restore);
 extern void i915_redisable_vga(struct drm_device *dev);
+extern void i915_redisable_vga_power_on(struct drm_device *dev);
 extern bool intel_fbc_enabled(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e3824f8..ea00878 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11304,10 +11304,20 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
 	 * the crtc fixup. */
 }
 
+void i915_redisable_vga_power_on(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 vga_reg = i915_vgacntrl_reg(dev);
+
+	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
+		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
+		i915_disable_vga(dev);
+	}
+}
+
 void i915_redisable_vga(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 vga_reg = i915_vgacntrl_reg(dev);
 
 	/* This function can be called both from intel_modeset_setup_hw_state or
 	 * at a very early point in our resume sequence, where the power well
@@ -11316,14 +11326,10 @@ void i915_redisable_vga(struct drm_device *dev)
 	 * level, just check if the power well is enabled instead of trying to
 	 * follow the "don't touch the power well if we don't need it" policy
 	 * the rest of the driver uses. */
-	if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) &&
-	    (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0)
+	if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_VGA))
 		return;
 
-	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
-		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
-		i915_disable_vga(dev);
-	}
+	i915_redisable_vga_power_on(dev);
 }
 
 static void intel_modeset_readout_hw_state(struct drm_device *dev)
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 16/19] drm/i915: sanity check power well sw state against hw state
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (14 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 15/19] drm/i915: use power domain api to check vga power state Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-18 16:55   ` Ville Syrjälä
  2014-02-17 22:02 ` [PATCH 17/19] drm/i915: vlv: factor out valleyview_display_irq_install Imre Deak
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

Suggested by Daniel.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++++++++++++++++++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e81e7de..21ccf89 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5338,6 +5338,24 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
 	hsw_enable_package_c8(dev_priv);
 }
 
+static void check_power_well_state(struct drm_i915_private *dev_priv,
+				   struct i915_power_well *power_well)
+{
+	bool enabled;
+
+	if (!power_well->ops->is_enabled)
+		return;
+
+	enabled = power_well->ops->is_enabled(dev_priv, power_well);
+
+	if (enabled != (power_well->count > 0 || !i915.disable_power_well)) {
+		DRM_ERROR("state mismatch for '%s' (hw state %d use-count %d disable_power_well %d\n",
+			  power_well->name, enabled, power_well->count,
+			  i915.disable_power_well);
+		WARN_ON(1);
+	}
+}
+
 void intel_display_power_get(struct drm_i915_private *dev_priv,
 			     enum intel_display_power_domain domain)
 {
@@ -5349,9 +5367,14 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
 
 	mutex_lock(&power_domains->lock);
 
-	for_each_power_well(i, power_well, BIT(domain), power_domains)
-		if (!power_well->count++ && power_well->ops->enable)
+	for_each_power_well(i, power_well, BIT(domain), power_domains) {
+		if (!power_well->count++ && power_well->ops->enable) {
+			DRM_DEBUG_KMS("enabling %s\n", power_well->name);
 			power_well->ops->enable(dev_priv, power_well);
+		}
+
+		check_power_well_state(dev_priv, power_well);
+	}
 
 	power_domains->domain_use_count[domain]++;
 
@@ -5376,8 +5399,12 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
 		WARN_ON(!power_well->count);
 
 		if (!--power_well->count && power_well->ops->disable &&
-		    i915.disable_power_well)
+		    i915.disable_power_well) {
+			DRM_DEBUG_KMS("disabling %s\n", power_well->name);
 			power_well->ops->disable(dev_priv, power_well);
+		}
+
+		check_power_well_state(dev_priv, power_well);
 	}
 
 	mutex_unlock(&power_domains->lock);
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 17/19] drm/i915: vlv: factor out valleyview_display_irq_install
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (15 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 16/19] drm/i915: sanity check power well sw state against hw state Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:56   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 18/19] drm/i915: move hsw power domain comment to its right place Imre Deak
  2014-02-17 22:02 ` [PATCH 19/19] drm/i915: power domains: add vlv power wells Imre Deak
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

We'll need to disable/re-enable the display-side IRQs when turning
off/on the VLV display power well. Factor out the helper functions
for this. For now keep the display IRQs enabled by default, so the
functionality doesn't change. This will be changed to enable/disable
the IRQs on-demand when adding support for VLV power wells in an
upcoming patch.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c |   1 +
 drivers/gpu/drm/i915/i915_drv.h |   5 ++
 drivers/gpu/drm/i915/i915_irq.c | 122 ++++++++++++++++++++++++++++++++--------
 3 files changed, 103 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index f8f7a59..dca4dc3 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1668,6 +1668,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 		goto out_mtrrfree;
 	}
 
+	dev_priv->display_irqs_enabled = true;
 	intel_irq_init(dev);
 	intel_uncore_sanitize(dev);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 632f9d8..227c349 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1454,6 +1454,8 @@ typedef struct drm_i915_private {
 	/* protects the irq masks */
 	spinlock_t irq_lock;
 
+	bool display_irqs_enabled;
+
 	/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
 	struct pm_qos_request pm_qos;
 
@@ -2052,6 +2054,9 @@ void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
 		      u32 status_mask);
 
+void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
+void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
+
 /* i915_gem.c */
 int i915_gem_init_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 75dd0a8..6078d06 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -3016,41 +3016,109 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 	return 0;
 }
 
+static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv)
+{
+	unsigned long irqflags;
+	u32 pipestat_mask;
+	u32 iir_mask;
+
+	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
+			PIPE_FIFO_UNDERRUN_STATUS;
+	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
+	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
+	POSTING_READ(PIPESTAT(PIPE_A));
+
+	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
+			PIPE_CRC_DONE_INTERRUPT_STATUS;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	i915_enable_pipestat(dev_priv, PIPE_A, pipestat_mask |
+					       PIPE_GMBUS_INTERRUPT_STATUS);
+	i915_enable_pipestat(dev_priv, PIPE_B, pipestat_mask);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+	iir_mask = I915_DISPLAY_PORT_INTERRUPT |
+		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+		   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
+	dev_priv->irq_mask &= ~iir_mask;
+
+	I915_WRITE(VLV_IIR, iir_mask);
+	I915_WRITE(VLV_IIR, iir_mask);
+	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
+	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
+	POSTING_READ(VLV_IER);
+}
+
+static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
+{
+	unsigned long irqflags;
+	u32 pipestat_mask;
+	u32 iir_mask;
+
+	iir_mask = I915_DISPLAY_PORT_INTERRUPT |
+		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
+		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
+	dev_priv->irq_mask |= iir_mask;
+	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
+	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
+	I915_WRITE(VLV_IIR, iir_mask);
+	I915_WRITE(VLV_IIR, iir_mask);
+	POSTING_READ(VLV_IIR);
+
+	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
+			PIPE_CRC_DONE_INTERRUPT_STATUS;
+
+	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	i915_disable_pipestat(dev_priv, PIPE_A, pipestat_mask |
+					        PIPE_GMBUS_INTERRUPT_STATUS);
+	i915_disable_pipestat(dev_priv, PIPE_B, pipestat_mask);
+	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
+	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
+			PIPE_FIFO_UNDERRUN_STATUS;
+	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
+	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
+	POSTING_READ(PIPESTAT(PIPE_A));
+}
+
+void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
+{
+	if (dev_priv->display_irqs_enabled)
+		return;
+
+	dev_priv->display_irqs_enabled = true;
+
+	if (dev_priv->dev->irq_enabled)
+		valleyview_display_irqs_install(dev_priv);
+}
+
+void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
+{
+	if (!dev_priv->display_irqs_enabled)
+		return;
+
+	dev_priv->display_irqs_enabled = false;
+
+	if (dev_priv->dev->irq_enabled)
+		valleyview_display_irqs_uninstall(dev_priv);
+}
+
 static int valleyview_irq_postinstall(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	u32 enable_mask;
-	u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
-		PIPE_CRC_DONE_INTERRUPT_STATUS;
-	unsigned long irqflags;
 
-	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
-	enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
-		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
-
-	/*
-	 *Leave vblank interrupts masked initially.  enable/disable will
-	 * toggle them based on usage.
-	 */
-	dev_priv->irq_mask = ~enable_mask;
+	dev_priv->irq_mask = ~0;
 
 	I915_WRITE(PORT_HOTPLUG_EN, 0);
 	POSTING_READ(PORT_HOTPLUG_EN);
 
 	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
-	I915_WRITE(VLV_IER, enable_mask);
+	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
 	I915_WRITE(VLV_IIR, 0xffffffff);
-	I915_WRITE(PIPESTAT(0), 0xffff);
-	I915_WRITE(PIPESTAT(1), 0xffff);
 	POSTING_READ(VLV_IER);
 
-	/* Interrupt setup is already guaranteed to be single-threaded, this is
-	 * just to make the assert_spin_locked check happy. */
-	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-	i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable);
-	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
-	i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable);
-	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+	if (dev_priv->display_irqs_enabled)
+		valleyview_display_irqs_install(dev_priv);
 
 	I915_WRITE(VLV_IIR, 0xffffffff);
 	I915_WRITE(VLV_IIR, 0xffffffff);
@@ -3193,8 +3261,12 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
 	I915_WRITE(HWSTAM, 0xffffffff);
 	I915_WRITE(PORT_HOTPLUG_EN, 0);
 	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
-	for_each_pipe(pipe)
-		I915_WRITE(PIPESTAT(pipe), 0xffff);
+
+	if (dev_priv->display_irqs_enabled)
+		valleyview_display_irqs_uninstall(dev_priv);
+
+	dev_priv->irq_mask = 0;
+
 	I915_WRITE(VLV_IIR, 0xffffffff);
 	I915_WRITE(VLV_IMR, 0xffffffff);
 	I915_WRITE(VLV_IER, 0x0);
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 18/19] drm/i915: move hsw power domain comment to its right place
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (16 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 17/19] drm/i915: vlv: factor out valleyview_display_irq_install Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-20 19:53   ` Jesse Barnes
  2014-02-17 22:02 ` [PATCH 19/19] drm/i915: power domains: add vlv power wells Imre Deak
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/intel_pm.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 21ccf89..68f58e5 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5213,6 +5213,12 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
 	return is_enabled;
 }
 
+/*
+ * 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
+ * to be enabled, and it will only be disabled if none of the registers is
+ * requesting it to be enabled.
+ */
 static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
 {
 	struct drm_device *dev = dev_priv->dev;
@@ -5556,12 +5562,6 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
 	mutex_unlock(&power_domains->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
- * to be enabled, and it will only be disabled if none of the registers is
- * requesting it to be enabled.
- */
 void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
 {
 	/* For now, we need the power well to be always enabled. */
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* [PATCH 19/19] drm/i915: power domains: add vlv power wells
  2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
                   ` (17 preceding siblings ...)
  2014-02-17 22:02 ` [PATCH 18/19] drm/i915: move hsw power domain comment to its right place Imre Deak
@ 2014-02-17 22:02 ` Imre Deak
  2014-02-19 12:29   ` Ville Syrjälä
  18 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-17 22:02 UTC (permalink / raw)
  To: intel-gfx

Based on an early draft from Jesse.

Add support for powering on/off the dynamic power wells on VLV by
registering its display and dpio dynamic power wells with the power
domain framework.

For now power on all PHY TX lanes regardless of the actual lane
configuration. Later this can be optimized when the PHY side setup
enables only the required lanes. Atm, it enables all lanes in all
cases.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c      |   1 -
 drivers/gpu/drm/i915/i915_drv.h      |   2 +-
 drivers/gpu/drm/i915/intel_display.c |   1 +
 drivers/gpu/drm/i915/intel_pm.c      | 228 +++++++++++++++++++++++++++++++++++
 4 files changed, 230 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index dca4dc3..f8f7a59 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1668,7 +1668,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 		goto out_mtrrfree;
 	}
 
-	dev_priv->display_irqs_enabled = true;
 	intel_irq_init(dev);
 	intel_uncore_sanitize(dev);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 227c349..804334e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1053,7 +1053,7 @@ struct i915_power_well {
 	/* power well enable/disable usage count */
 	int count;
 	unsigned long domains;
-	void *data;
+	unsigned long data;
 	const struct i915_power_well_ops *ops;
 };
 
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ea00878..d6661c4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -4224,6 +4224,7 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
 
 	if (req_cdclk != cur_cdclk)
 		valleyview_set_cdclk(dev, req_cdclk);
+	modeset_update_power_wells(dev);
 }
 
 static void valleyview_crtc_enable(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 68f58e5..e4416a7 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5344,6 +5344,133 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
 	hsw_enable_package_c8(dev_priv);
 }
 
+static void vlv_set_power_well(struct drm_i915_private *dev_priv,
+			       struct i915_power_well *power_well, bool enable)
+{
+	enum punit_power_well power_well_id = power_well->data;
+	u32 mask;
+	u32 state;
+	u32 ctrl;
+
+	mask = PUNIT_PWRGT_MASK(power_well_id);
+	state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
+			 PUNIT_PWRGT_PWR_GATE(power_well_id);
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+
+#define COND \
+	((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
+
+	if (COND)
+		goto out;
+
+	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
+	ctrl &= ~mask;
+	ctrl |= state;
+	vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
+
+	if (wait_for(COND, 100))
+		DRM_ERROR("timout setting power well state %08x (%08x)\n",
+			  state,
+			  vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
+
+out:
+	mutex_unlock(&dev_priv->rps.hw_lock);
+}
+
+static void vlv_power_well_sync_hw(struct drm_i915_private *dev_priv,
+				   struct i915_power_well *power_well)
+{
+	vlv_set_power_well(dev_priv, power_well, power_well->count > 0);
+}
+
+static void vlv_power_well_enable(struct drm_i915_private *dev_priv,
+				  struct i915_power_well *power_well)
+{
+	vlv_set_power_well(dev_priv, power_well, true);
+}
+
+static void vlv_power_well_disable(struct drm_i915_private *dev_priv,
+				   struct i915_power_well *power_well)
+{
+	vlv_set_power_well(dev_priv, power_well, false);
+}
+
+static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv,
+				   struct i915_power_well *power_well)
+{
+	int power_well_id = power_well->data;
+	bool enabled = false;
+	u32 gating_mask;
+	u32 gating_val;
+	u32 val;
+
+	gating_mask = PUNIT_PWRGT_MASK(power_well_id);
+	gating_val = PUNIT_PWRGT_PWR_ON(power_well_id);
+
+	mutex_lock(&dev_priv->rps.hw_lock);
+
+	val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & gating_mask;
+	/*
+	 * We only ever set the power-on and power-gate states, anything
+	 * else is unexpected.
+	 */
+	WARN_ON(val != PUNIT_PWRGT_PWR_ON(power_well_id) &&
+		val != PUNIT_PWRGT_PWR_GATE(power_well_id));
+	if (val == gating_val)
+		enabled = true;
+
+	/*
+	 * A transient state at this point would mean some unexpected party
+	 * is poking at the power controls too.
+	 */
+	gating_val = val;
+	val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & gating_mask;
+	WARN_ON(val != gating_val);
+
+	mutex_unlock(&dev_priv->rps.hw_lock);
+
+	return enabled;
+}
+
+static void vlv_display_power_well_enable(struct drm_i915_private *dev_priv,
+				          struct i915_power_well *power_well)
+{
+
+	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
+
+	vlv_set_power_well(dev_priv, power_well, true);
+	valleyview_enable_display_irqs(dev_priv);
+
+	/*
+	 * During driver initialization we need to defer enabling hotplug
+	 * processing until fbdev is set up.
+	 */
+	if (dev_priv->enable_hotplug_processing)
+		intel_hpd_init(dev_priv->dev);
+
+	i915_redisable_vga_power_on(dev_priv->dev);
+}
+
+static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
+				           struct i915_power_well *power_well)
+{
+	struct drm_device *dev = dev_priv->dev;
+	enum pipe pipe;
+
+	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DISP2D);
+
+	for_each_pipe(pipe)
+		intel_set_cpu_fifo_underrun_reporting(dev, pipe, false);
+
+	valleyview_disable_display_irqs(dev_priv);
+
+	for_each_pipe(pipe)
+		reset_vblank_counter(dev, pipe);
+
+	vlv_set_power_well(dev_priv, power_well, false);
+}
+
 static void check_power_well_state(struct drm_i915_private *dev_priv,
 				   struct i915_power_well *power_well)
 {
@@ -5472,6 +5599,35 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
 	(POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |	\
 	BIT(POWER_DOMAIN_INIT))
 
+#define VLV_ALWAYS_ON_POWER_DOMAINS	BIT(POWER_DOMAIN_INIT)
+#define VLV_DISPLAY_POWER_DOMAINS	POWER_DOMAIN_MASK
+
+#define VLV_DPIO_CMN_BC_POWER_DOMAINS (		\
+	BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_CRT) |		\
+	BIT(POWER_DOMAIN_INIT))
+
+#define VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS (	\
+	BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |	\
+	BIT(POWER_DOMAIN_INIT))
+
+#define VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS (	\
+	BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |	\
+	BIT(POWER_DOMAIN_INIT))
+
+#define VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS (	\
+	BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |	\
+	BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |	\
+	BIT(POWER_DOMAIN_INIT))
+
+#define VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS (	\
+	BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |	\
+	BIT(POWER_DOMAIN_INIT))
+
 static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { };
 
 static struct i915_power_well i9xx_always_on_power_well[] = {
@@ -5515,6 +5671,76 @@ static struct i915_power_well bdw_power_wells[] = {
 	},
 };
 
+static const struct i915_power_well_ops vlv_display_power_well_ops = {
+	.sync_hw = vlv_power_well_sync_hw,
+	.enable = vlv_display_power_well_enable,
+	.disable = vlv_display_power_well_disable,
+	.is_enabled = vlv_power_well_enabled,
+};
+
+static const struct i915_power_well_ops vlv_dpio_power_well_ops = {
+	.sync_hw = vlv_power_well_sync_hw,
+	.enable = vlv_power_well_enable,
+	.disable = vlv_power_well_disable,
+	.is_enabled = vlv_power_well_enabled,
+};
+
+static struct i915_power_well vlv_power_wells[] = {
+	{
+		.name = "always-on",
+		.domains = VLV_ALWAYS_ON_POWER_DOMAINS,
+		.ops = &i9xx_always_on_power_well_ops,
+	},
+	{
+		.name = "display",
+		.domains = VLV_DISPLAY_POWER_DOMAINS,
+		.data = PUNIT_POWER_WELL_DISP2D,
+		.ops = &vlv_display_power_well_ops,
+	},
+	{
+		.name = "dpio-common",
+		.domains = VLV_DPIO_CMN_BC_POWER_DOMAINS,
+		.data = PUNIT_POWER_WELL_DPIO_CMN_BC,
+		.ops = &vlv_dpio_power_well_ops,
+	},
+	{
+		.name = "dpio-tx-b-01",
+		.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
+			   VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
+			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
+			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
+		.ops = &vlv_dpio_power_well_ops,
+		.data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_01,
+	},
+	{
+		.name = "dpio-tx-b-23",
+		.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
+			   VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
+			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
+			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
+		.ops = &vlv_dpio_power_well_ops,
+		.data = PUNIT_POWER_WELL_DPIO_TX_B_LANES_23,
+	},
+	{
+		.name = "dpio-tx-c-01",
+		.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
+			   VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
+			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
+			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
+		.ops = &vlv_dpio_power_well_ops,
+		.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_01,
+	},
+	{
+		.name = "dpio-tx-c-23",
+		.domains = VLV_DPIO_TX_B_LANES_01_POWER_DOMAINS |
+			   VLV_DPIO_TX_B_LANES_23_POWER_DOMAINS |
+			   VLV_DPIO_TX_C_LANES_01_POWER_DOMAINS |
+			   VLV_DPIO_TX_C_LANES_23_POWER_DOMAINS,
+		.ops = &vlv_dpio_power_well_ops,
+		.data = PUNIT_POWER_WELL_DPIO_TX_C_LANES_23,
+	},
+};
+
 #define set_power_wells(power_domains, __power_wells) ({		\
 	(power_domains)->power_wells = (__power_wells);			\
 	(power_domains)->power_well_count = ARRAY_SIZE(__power_wells);	\
@@ -5536,6 +5762,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
 	} else if (IS_BROADWELL(dev_priv->dev)) {
 		set_power_wells(power_domains, bdw_power_wells);
 		hsw_pwr = power_domains;
+	} else if (IS_VALLEYVIEW(dev_priv->dev)) {
+		set_power_wells(power_domains, vlv_power_wells);
 	} else {
 		set_power_wells(power_domains, i9xx_always_on_power_well);
 	}
-- 
1.8.4

^ permalink raw reply related	[flat|nested] 68+ messages in thread

* Re: [PATCH 11/19] drm/i915: vlv: keep first level vblank IRQs masked
  2014-02-17 22:02 ` [PATCH 11/19] drm/i915: vlv: keep first level vblank IRQs masked Imre Deak
@ 2014-02-18 16:54   ` Ville Syrjälä
  0 siblings, 0 replies; 68+ messages in thread
From: Ville Syrjälä @ 2014-02-18 16:54 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 12:02:12AM +0200, Imre Deak wrote:
> This is a left-over from
> 
> commit b7e634cc8dcd320123199a18bae0937b40dc28b8
> Author: Imre Deak <imre.deak@intel.com>
> Date:   Tue Feb 4 21:35:45 2014 +0200
> 
> drm/i915: vlv: don't unmask IIR[DISPLAY_PIPE_A/B_VBLANK] interrupt
> 
> where we stopped unmasking the vblank IRQs, but left them enabled in the
> IER register. Disable them in IER too.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_irq.c | 8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index f68aee3..75dd0a8 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -3026,17 +3026,13 @@ static int valleyview_irq_postinstall(struct drm_device *dev)
>  
>  	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
>  	enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> -		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
> -		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
> -		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
> +		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
>  
>  	/*
>  	 *Leave vblank interrupts masked initially.  enable/disable will
>  	 * toggle them based on usage.
>  	 */

This comment is now stale.

> -	dev_priv->irq_mask = (~enable_mask) |
> -		I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT |
> -		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
> +	dev_priv->irq_mask = ~enable_mask;
>  
>  	I915_WRITE(PORT_HOTPLUG_EN, 0);
>  	POSTING_READ(PORT_HOTPLUG_EN);
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 13/19] drm/i915: factor out reset_vblank_counter
  2014-02-17 22:02 ` [PATCH 13/19] drm/i915: factor out reset_vblank_counter Imre Deak
@ 2014-02-18 16:55   ` Ville Syrjälä
  0 siblings, 0 replies; 68+ messages in thread
From: Ville Syrjälä @ 2014-02-18 16:55 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 12:02:14AM +0200, Imre Deak wrote:
> We need to do the same for other platforms in upcoming patches.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 9cb7ed6..e81e7de 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5249,11 +5249,19 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
>  	}
>  }
>  
> +static void reset_vblank_counter(struct drm_device *dev, enum pipe p)

Could just call the parameter 'pipe' while we're at it.

> +{
> +	unsigned long irqflags;
> +
> +	spin_lock_irqsave(&dev->vbl_lock, irqflags);
> +	dev->vblank[p].last = 0;
> +	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
> +}
> +
>  static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
>  	enum pipe p;
> -	unsigned long irqflags;
>  
>  	/*
>  	 * After this, the registers on the pipes that are part of the power
> @@ -5262,11 +5270,9 @@ static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
>  	 *
>  	 * FIXME: Should we do this in general in drm_vblank_post_modeset?
>  	 */
> -	spin_lock_irqsave(&dev->vbl_lock, irqflags);
>  	for_each_pipe(p)
>  		if (p != PIPE_A)
> -			dev->vblank[p].last = 0;
> -	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
> +			reset_vblank_counter(dev, p);
>  }
>  
>  static void hsw_set_power_well(struct drm_i915_private *dev_priv,
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 16/19] drm/i915: sanity check power well sw state against hw state
  2014-02-17 22:02 ` [PATCH 16/19] drm/i915: sanity check power well sw state against hw state Imre Deak
@ 2014-02-18 16:55   ` Ville Syrjälä
  2014-02-18 17:37     ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Ville Syrjälä @ 2014-02-18 16:55 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 12:02:17AM +0200, Imre Deak wrote:
> Suggested by Daniel.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++++++++++++++++++---
>  1 file changed, 30 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index e81e7de..21ccf89 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5338,6 +5338,24 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
>  	hsw_enable_package_c8(dev_priv);
>  }
>  
> +static void check_power_well_state(struct drm_i915_private *dev_priv,
> +				   struct i915_power_well *power_well)
> +{
> +	bool enabled;
> +
> +	if (!power_well->ops->is_enabled)
> +		return;
> +
> +	enabled = power_well->ops->is_enabled(dev_priv, power_well);
> +
> +	if (enabled != (power_well->count > 0 || !i915.disable_power_well)) {

Doesn't i915.disable_power_well==true mean "leave power wells always
enabled"? So I think the '!' needs to be removed.

> +		DRM_ERROR("state mismatch for '%s' (hw state %d use-count %d disable_power_well %d\n",
> +			  power_well->name, enabled, power_well->count,
> +			  i915.disable_power_well);
> +		WARN_ON(1);
> +	}

For an error message + backtrace, you could just use WARN().

> +}
> +
>  void intel_display_power_get(struct drm_i915_private *dev_priv,
>  			     enum intel_display_power_domain domain)
>  {
> @@ -5349,9 +5367,14 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
>  
>  	mutex_lock(&power_domains->lock);
>  
> -	for_each_power_well(i, power_well, BIT(domain), power_domains)
> -		if (!power_well->count++ && power_well->ops->enable)
> +	for_each_power_well(i, power_well, BIT(domain), power_domains) {
> +		if (!power_well->count++ && power_well->ops->enable) {
> +			DRM_DEBUG_KMS("enabling %s\n", power_well->name);
>  			power_well->ops->enable(dev_priv, power_well);
> +		}
> +
> +		check_power_well_state(dev_priv, power_well);
> +	}
>  
>  	power_domains->domain_use_count[domain]++;
>  
> @@ -5376,8 +5399,12 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
>  		WARN_ON(!power_well->count);
>  
>  		if (!--power_well->count && power_well->ops->disable &&
> -		    i915.disable_power_well)
> +		    i915.disable_power_well) {
> +			DRM_DEBUG_KMS("disabling %s\n", power_well->name);
>  			power_well->ops->disable(dev_priv, power_well);
> +		}
> +
> +		check_power_well_state(dev_priv, power_well);
>  	}
>  
>  	mutex_unlock(&power_domains->lock);
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 16/19] drm/i915: sanity check power well sw state against hw state
  2014-02-18 16:55   ` Ville Syrjälä
@ 2014-02-18 17:37     ` Imre Deak
  2014-02-18 17:59       ` Ville Syrjälä
  0 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-18 17:37 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 3327 bytes --]

On Tue, 2014-02-18 at 18:55 +0200, Ville Syrjälä wrote:
> On Tue, Feb 18, 2014 at 12:02:17AM +0200, Imre Deak wrote:
> > Suggested by Daniel.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++++++++++++++++++---
> >  1 file changed, 30 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index e81e7de..21ccf89 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -5338,6 +5338,24 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> >  	hsw_enable_package_c8(dev_priv);
> >  }
> >  
> > +static void check_power_well_state(struct drm_i915_private *dev_priv,
> > +				   struct i915_power_well *power_well)
> > +{
> > +	bool enabled;
> > +
> > +	if (!power_well->ops->is_enabled)
> > +		return;
> > +
> > +	enabled = power_well->ops->is_enabled(dev_priv, power_well);
> > +
> > +	if (enabled != (power_well->count > 0 || !i915.disable_power_well)) {
> 
> Doesn't i915.disable_power_well==true mean "leave power wells always
> enabled"? So I think the '!' needs to be removed.

No, i915.disable_power_well==true means disable power wells when the
refcount goes to 0. Perhaps not the best name/semantics for this kind of
option, the default for it should be 0 and mean normal operation, which
is to disable power wells when possible.

> > +		DRM_ERROR("state mismatch for '%s' (hw state %d use-count %d disable_power_well %d\n",
> > +			  power_well->name, enabled, power_well->count,
> > +			  i915.disable_power_well);
> > +		WARN_ON(1);
> > +	}
> 
> For an error message + backtrace, you could just use WARN().

Ok.

> > +}
> > +
> >  void intel_display_power_get(struct drm_i915_private *dev_priv,
> >  			     enum intel_display_power_domain domain)
> >  {
> > @@ -5349,9 +5367,14 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
> >  
> >  	mutex_lock(&power_domains->lock);
> >  
> > -	for_each_power_well(i, power_well, BIT(domain), power_domains)
> > -		if (!power_well->count++ && power_well->ops->enable)
> > +	for_each_power_well(i, power_well, BIT(domain), power_domains) {
> > +		if (!power_well->count++ && power_well->ops->enable) {
> > +			DRM_DEBUG_KMS("enabling %s\n", power_well->name);
> >  			power_well->ops->enable(dev_priv, power_well);
> > +		}
> > +
> > +		check_power_well_state(dev_priv, power_well);
> > +	}
> >  
> >  	power_domains->domain_use_count[domain]++;
> >  
> > @@ -5376,8 +5399,12 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
> >  		WARN_ON(!power_well->count);
> >  
> >  		if (!--power_well->count && power_well->ops->disable &&
> > -		    i915.disable_power_well)
> > +		    i915.disable_power_well) {
> > +			DRM_DEBUG_KMS("disabling %s\n", power_well->name);
> >  			power_well->ops->disable(dev_priv, power_well);
> > +		}
> > +
> > +		check_power_well_state(dev_priv, power_well);
> >  	}
> >  
> >  	mutex_unlock(&power_domains->lock);
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 16/19] drm/i915: sanity check power well sw state against hw state
  2014-02-18 17:37     ` Imre Deak
@ 2014-02-18 17:59       ` Ville Syrjälä
  2014-03-05 10:32         ` Daniel Vetter
  0 siblings, 1 reply; 68+ messages in thread
From: Ville Syrjälä @ 2014-02-18 17:59 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 07:37:01PM +0200, Imre Deak wrote:
> On Tue, 2014-02-18 at 18:55 +0200, Ville Syrjälä wrote:
> > On Tue, Feb 18, 2014 at 12:02:17AM +0200, Imre Deak wrote:
> > > Suggested by Daniel.
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++++++++++++++++++---
> > >  1 file changed, 30 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > index e81e7de..21ccf89 100644
> > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > @@ -5338,6 +5338,24 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> > >  	hsw_enable_package_c8(dev_priv);
> > >  }
> > >  
> > > +static void check_power_well_state(struct drm_i915_private *dev_priv,
> > > +				   struct i915_power_well *power_well)
> > > +{
> > > +	bool enabled;
> > > +
> > > +	if (!power_well->ops->is_enabled)
> > > +		return;
> > > +
> > > +	enabled = power_well->ops->is_enabled(dev_priv, power_well);
> > > +
> > > +	if (enabled != (power_well->count > 0 || !i915.disable_power_well)) {
> > 
> > Doesn't i915.disable_power_well==true mean "leave power wells always
> > enabled"? So I think the '!' needs to be removed.
> 
> No, i915.disable_power_well==true means disable power wells when the
> refcount goes to 0. Perhaps not the best name/semantics for this kind of
> option, the default for it should be 0 and mean normal operation, which
> is to disable power wells when possible.

Oh I had the impression it was the other way around, but you're right.
Seems I keep getting confused by this thing. It has happened before and
I'm guessing it will happen again after I've forgotten the details
again.

> 
> > > +		DRM_ERROR("state mismatch for '%s' (hw state %d use-count %d disable_power_well %d\n",
> > > +			  power_well->name, enabled, power_well->count,
> > > +			  i915.disable_power_well);
> > > +		WARN_ON(1);
> > > +	}
> > 
> > For an error message + backtrace, you could just use WARN().
> 
> Ok.
> 
> > > +}
> > > +
> > >  void intel_display_power_get(struct drm_i915_private *dev_priv,
> > >  			     enum intel_display_power_domain domain)
> > >  {
> > > @@ -5349,9 +5367,14 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
> > >  
> > >  	mutex_lock(&power_domains->lock);
> > >  
> > > -	for_each_power_well(i, power_well, BIT(domain), power_domains)
> > > -		if (!power_well->count++ && power_well->ops->enable)
> > > +	for_each_power_well(i, power_well, BIT(domain), power_domains) {
> > > +		if (!power_well->count++ && power_well->ops->enable) {
> > > +			DRM_DEBUG_KMS("enabling %s\n", power_well->name);
> > >  			power_well->ops->enable(dev_priv, power_well);
> > > +		}
> > > +
> > > +		check_power_well_state(dev_priv, power_well);
> > > +	}
> > >  
> > >  	power_domains->domain_use_count[domain]++;
> > >  
> > > @@ -5376,8 +5399,12 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
> > >  		WARN_ON(!power_well->count);
> > >  
> > >  		if (!--power_well->count && power_well->ops->disable &&
> > > -		    i915.disable_power_well)
> > > +		    i915.disable_power_well) {
> > > +			DRM_DEBUG_KMS("disabling %s\n", power_well->name);
> > >  			power_well->ops->disable(dev_priv, power_well);
> > > +		}
> > > +
> > > +		check_power_well_state(dev_priv, power_well);
> > >  	}
> > >  
> > >  	mutex_unlock(&power_domains->lock);
> > > -- 
> > > 1.8.4
> > > 
> > > _______________________________________________
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > 
> 



-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 19/19] drm/i915: power domains: add vlv power wells
  2014-02-17 22:02 ` [PATCH 19/19] drm/i915: power domains: add vlv power wells Imre Deak
@ 2014-02-19 12:29   ` Ville Syrjälä
  2014-02-20 19:58     ` Jesse Barnes
  0 siblings, 1 reply; 68+ messages in thread
From: Ville Syrjälä @ 2014-02-19 12:29 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 12:02:20AM +0200, Imre Deak wrote:
> Based on an early draft from Jesse.
> 
> Add support for powering on/off the dynamic power wells on VLV by
> registering its display and dpio dynamic power wells with the power
> domain framework.
> 
> For now power on all PHY TX lanes regardless of the actual lane
> configuration. Later this can be optimized when the PHY side setup
> enables only the required lanes. Atm, it enables all lanes in all
> cases.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c      |   1 -
>  drivers/gpu/drm/i915/i915_drv.h      |   2 +-
>  drivers/gpu/drm/i915/intel_display.c |   1 +
>  drivers/gpu/drm/i915/intel_pm.c      | 228 +++++++++++++++++++++++++++++++++++
>  4 files changed, 230 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index dca4dc3..f8f7a59 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1668,7 +1668,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  		goto out_mtrrfree;
>  	}
>  
> -	dev_priv->display_irqs_enabled = true;
>  	intel_irq_init(dev);
>  	intel_uncore_sanitize(dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 227c349..804334e 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1053,7 +1053,7 @@ struct i915_power_well {
>  	/* power well enable/disable usage count */
>  	int count;
>  	unsigned long domains;
> -	void *data;
> +	unsigned long data;
>  	const struct i915_power_well_ops *ops;
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ea00878..d6661c4 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -4224,6 +4224,7 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
>  
>  	if (req_cdclk != cur_cdclk)
>  		valleyview_set_cdclk(dev, req_cdclk);
> +	modeset_update_power_wells(dev);
>  }
>  
>  static void valleyview_crtc_enable(struct drm_crtc *crtc)
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 68f58e5..e4416a7 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5344,6 +5344,133 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
>  	hsw_enable_package_c8(dev_priv);
>  }
>  
> +static void vlv_set_power_well(struct drm_i915_private *dev_priv,
> +			       struct i915_power_well *power_well, bool enable)
> +{
> +	enum punit_power_well power_well_id = power_well->data;
> +	u32 mask;
> +	u32 state;
> +	u32 ctrl;
> +
> +	mask = PUNIT_PWRGT_MASK(power_well_id);
> +	state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
> +			 PUNIT_PWRGT_PWR_GATE(power_well_id);
> +
> +	mutex_lock(&dev_priv->rps.hw_lock);
> +
> +#define COND \
> +	((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
> +
> +	if (COND)
> +		goto out;
> +
> +	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
> +	ctrl &= ~mask;
> +	ctrl |= state;
> +	vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
> +
> +	if (wait_for(COND, 100))
> +		DRM_ERROR("timout setting power well state %08x (%08x)\n",
> +			  state,
> +			  vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));

#undef COND somewhere to avoid suprises further down in the code?

> +
> +out:
> +	mutex_unlock(&dev_priv->rps.hw_lock);
> +}
> +
<snip>

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 08/19] drm/i915: get port power domain in connector detect
  2014-02-17 22:02 ` [PATCH 08/19] drm/i915: get port power domain in connector detect Imre Deak
@ 2014-02-19 12:35   ` Ville Syrjälä
  2014-02-19 12:39     ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Ville Syrjälä @ 2014-02-19 12:35 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 12:02:09AM +0200, Imre Deak wrote:
> The connector detect and get_mode handlers need to access the port
> specific HW blocks to read the EDID etc. Get/put the port power domains
> around these handlers.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_crt.c | 42 ++++++++++++++++++++++++++++++++--------
>  drivers/gpu/drm/i915/intel_dp.c  | 16 ++++++++++++---
>  drivers/gpu/drm/i915/intel_dsi.c | 13 ++++++++++++-

And what about HDMI?

>  3 files changed, 59 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 9864aa1..2a38429 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -630,7 +630,10 @@ static enum drm_connector_status
>  intel_crt_detect(struct drm_connector *connector, bool force)
>  {
>  	struct drm_device *dev = connector->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct intel_crt *crt = intel_attached_crt(connector);
> +	struct intel_encoder *intel_encoder = &crt->base;
> +	enum intel_display_power_domain power_domain;
>  	enum drm_connector_status status;
>  	struct intel_load_detect_pipe tmp;
>  
> @@ -638,6 +641,11 @@ intel_crt_detect(struct drm_connector *connector, bool force)
>  		      connector->base.id, drm_get_connector_name(connector),
>  		      force);
>  
> +	power_domain = intel_display_port_power_domain(intel_encoder);
> +	intel_display_power_get(dev_priv, power_domain);
> +
> +	status = connector_status_connected;
> +
>  	if (I915_HAS_HOTPLUG(dev)) {
>  		/* We can not rely on the HPD pin always being correctly wired
>  		 * up, for example many KVM do not pass it through, and so
> @@ -645,23 +653,27 @@ intel_crt_detect(struct drm_connector *connector, bool force)
>  		 */
>  		if (intel_crt_detect_hotplug(connector)) {
>  			DRM_DEBUG_KMS("CRT detected via hotplug\n");
> -			return connector_status_connected;
> +			goto out;
>  		} else
>  			DRM_DEBUG_KMS("CRT not detected via hotplug\n");
>  	}
>  
>  	if (intel_crt_detect_ddc(connector))
> -		return connector_status_connected;
> +		goto out;
>  
>  	/* Load detection is broken on HPD capable machines. Whoever wants a
>  	 * broken monitor (without edid) to work behind a broken kvm (that fails
>  	 * to have the right resistors for HP detection) needs to fix this up.
>  	 * For now just bail out. */
> -	if (I915_HAS_HOTPLUG(dev))
> -		return connector_status_disconnected;
> +	if (I915_HAS_HOTPLUG(dev)) {
> +		status = connector_status_disconnected;
> +		goto out;
> +	}
>  
> -	if (!force)
> -		return connector->status;
> +	if (!force) {
> +		status = connector->status;
> +		goto out;
> +	}
>  
>  	/* for pre-945g platforms use load detect */
>  	if (intel_get_load_detect_pipe(connector, NULL, &tmp)) {
> @@ -673,6 +685,9 @@ intel_crt_detect(struct drm_connector *connector, bool force)
>  	} else
>  		status = connector_status_unknown;
>  
> +out:
> +	intel_display_power_put(dev_priv, power_domain);
> +
>  	return status;
>  }
>  
> @@ -686,17 +701,28 @@ static int intel_crt_get_modes(struct drm_connector *connector)
>  {
>  	struct drm_device *dev = connector->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crt *crt = intel_attached_crt(connector);
> +	struct intel_encoder *intel_encoder = &crt->base;
> +	enum intel_display_power_domain power_domain;
>  	int ret;
>  	struct i2c_adapter *i2c;
>  
> +	power_domain = intel_display_port_power_domain(intel_encoder);
> +	intel_display_power_get(dev_priv, power_domain);
> +
>  	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
>  	ret = intel_crt_ddc_get_modes(connector, i2c);
>  	if (ret || !IS_G4X(dev))
> -		return ret;
> +		goto out;
>  
>  	/* Try to probe digital port for output in DVI-I -> VGA mode. */
>  	i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
> -	return intel_crt_ddc_get_modes(connector, i2c);
> +	ret = intel_crt_ddc_get_modes(connector, i2c);
> +
> +out:
> +	intel_display_power_put(dev_priv, power_domain);
> +
> +	return ret;
>  }
>  
>  static int intel_crt_set_property(struct drm_connector *connector,
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index f53c95c..9c39425 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3224,9 +3224,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  	struct drm_device *dev = connector->dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	enum drm_connector_status status;
> +	enum intel_display_power_domain power_domain;
>  	struct edid *edid = NULL;
>  
> -	intel_runtime_pm_get(dev_priv);
> +	power_domain = intel_display_port_power_domain(intel_encoder);
> +	intel_display_power_get(dev_priv, power_domain);
>  
>  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
>  		      connector->base.id, drm_get_connector_name(connector));
> @@ -3256,23 +3258,31 @@ intel_dp_detect(struct drm_connector *connector, bool force)
>  	if (intel_encoder->type != INTEL_OUTPUT_EDP)
>  		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
>  	status = connector_status_connected;
> -
>  out:
> -	intel_runtime_pm_put(dev_priv);
> +	intel_display_power_put(dev_priv, power_domain);
> +
>  	return status;
>  }
>  
>  static int intel_dp_get_modes(struct drm_connector *connector)
>  {
>  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +	struct intel_encoder *intel_encoder = &intel_dig_port->base;
>  	struct intel_connector *intel_connector = to_intel_connector(connector);
>  	struct drm_device *dev = connector->dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	enum intel_display_power_domain power_domain;
>  	int ret;
>  
>  	/* We should parse the EDID data and find out if it has an audio sink
>  	 */
>  
> +	power_domain = intel_display_port_power_domain(intel_encoder);
> +	intel_display_power_get(dev_priv, power_domain);
> +
>  	ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
> +	intel_display_power_put(dev_priv, power_domain);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
> index 3ee1db1..63b95bbd 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.c
> +++ b/drivers/gpu/drm/i915/intel_dsi.c
> @@ -488,8 +488,19 @@ static enum drm_connector_status
>  intel_dsi_detect(struct drm_connector *connector, bool force)
>  {
>  	struct intel_dsi *intel_dsi = intel_attached_dsi(connector);
> +	struct intel_encoder *intel_encoder = &intel_dsi->base;
> +	enum intel_display_power_domain power_domain;
> +	enum drm_connector_status connector_status;
> +	struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
> +
>  	DRM_DEBUG_KMS("\n");
> -	return intel_dsi->dev.dev_ops->detect(&intel_dsi->dev);
> +	power_domain = intel_display_port_power_domain(intel_encoder);
> +
> +	intel_display_power_get(dev_priv, power_domain);
> +	connector_status = intel_dsi->dev.dev_ops->detect(&intel_dsi->dev);
> +	intel_display_power_put(dev_priv, power_domain);
> +
> +	return connector_status;
>  }
>  
>  static int intel_dsi_get_modes(struct drm_connector *connector)
> -- 
> 1.8.4
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 08/19] drm/i915: get port power domain in connector detect
  2014-02-19 12:35   ` Ville Syrjälä
@ 2014-02-19 12:39     ` Imre Deak
  2014-02-20 19:33       ` Jesse Barnes
  0 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-19 12:39 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 8159 bytes --]

On Wed, 2014-02-19 at 14:35 +0200, Ville Syrjälä wrote:
> On Tue, Feb 18, 2014 at 12:02:09AM +0200, Imre Deak wrote:
> > The connector detect and get_mode handlers need to access the port
> > specific HW blocks to read the EDID etc. Get/put the port power domains
> > around these handlers.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_crt.c | 42 ++++++++++++++++++++++++++++++++--------
> >  drivers/gpu/drm/i915/intel_dp.c  | 16 ++++++++++++---
> >  drivers/gpu/drm/i915/intel_dsi.c | 13 ++++++++++++-
> 
> And what about HDMI?

Good catch, I missed that one.

--Imre

> >  3 files changed, 59 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> > index 9864aa1..2a38429 100644
> > --- a/drivers/gpu/drm/i915/intel_crt.c
> > +++ b/drivers/gpu/drm/i915/intel_crt.c
> > @@ -630,7 +630,10 @@ static enum drm_connector_status
> >  intel_crt_detect(struct drm_connector *connector, bool force)
> >  {
> >  	struct drm_device *dev = connector->dev;
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	struct intel_crt *crt = intel_attached_crt(connector);
> > +	struct intel_encoder *intel_encoder = &crt->base;
> > +	enum intel_display_power_domain power_domain;
> >  	enum drm_connector_status status;
> >  	struct intel_load_detect_pipe tmp;
> >  
> > @@ -638,6 +641,11 @@ intel_crt_detect(struct drm_connector *connector, bool force)
> >  		      connector->base.id, drm_get_connector_name(connector),
> >  		      force);
> >  
> > +	power_domain = intel_display_port_power_domain(intel_encoder);
> > +	intel_display_power_get(dev_priv, power_domain);
> > +
> > +	status = connector_status_connected;
> > +
> >  	if (I915_HAS_HOTPLUG(dev)) {
> >  		/* We can not rely on the HPD pin always being correctly wired
> >  		 * up, for example many KVM do not pass it through, and so
> > @@ -645,23 +653,27 @@ intel_crt_detect(struct drm_connector *connector, bool force)
> >  		 */
> >  		if (intel_crt_detect_hotplug(connector)) {
> >  			DRM_DEBUG_KMS("CRT detected via hotplug\n");
> > -			return connector_status_connected;
> > +			goto out;
> >  		} else
> >  			DRM_DEBUG_KMS("CRT not detected via hotplug\n");
> >  	}
> >  
> >  	if (intel_crt_detect_ddc(connector))
> > -		return connector_status_connected;
> > +		goto out;
> >  
> >  	/* Load detection is broken on HPD capable machines. Whoever wants a
> >  	 * broken monitor (without edid) to work behind a broken kvm (that fails
> >  	 * to have the right resistors for HP detection) needs to fix this up.
> >  	 * For now just bail out. */
> > -	if (I915_HAS_HOTPLUG(dev))
> > -		return connector_status_disconnected;
> > +	if (I915_HAS_HOTPLUG(dev)) {
> > +		status = connector_status_disconnected;
> > +		goto out;
> > +	}
> >  
> > -	if (!force)
> > -		return connector->status;
> > +	if (!force) {
> > +		status = connector->status;
> > +		goto out;
> > +	}
> >  
> >  	/* for pre-945g platforms use load detect */
> >  	if (intel_get_load_detect_pipe(connector, NULL, &tmp)) {
> > @@ -673,6 +685,9 @@ intel_crt_detect(struct drm_connector *connector, bool force)
> >  	} else
> >  		status = connector_status_unknown;
> >  
> > +out:
> > +	intel_display_power_put(dev_priv, power_domain);
> > +
> >  	return status;
> >  }
> >  
> > @@ -686,17 +701,28 @@ static int intel_crt_get_modes(struct drm_connector *connector)
> >  {
> >  	struct drm_device *dev = connector->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	struct intel_crt *crt = intel_attached_crt(connector);
> > +	struct intel_encoder *intel_encoder = &crt->base;
> > +	enum intel_display_power_domain power_domain;
> >  	int ret;
> >  	struct i2c_adapter *i2c;
> >  
> > +	power_domain = intel_display_port_power_domain(intel_encoder);
> > +	intel_display_power_get(dev_priv, power_domain);
> > +
> >  	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
> >  	ret = intel_crt_ddc_get_modes(connector, i2c);
> >  	if (ret || !IS_G4X(dev))
> > -		return ret;
> > +		goto out;
> >  
> >  	/* Try to probe digital port for output in DVI-I -> VGA mode. */
> >  	i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);
> > -	return intel_crt_ddc_get_modes(connector, i2c);
> > +	ret = intel_crt_ddc_get_modes(connector, i2c);
> > +
> > +out:
> > +	intel_display_power_put(dev_priv, power_domain);
> > +
> > +	return ret;
> >  }
> >  
> >  static int intel_crt_set_property(struct drm_connector *connector,
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index f53c95c..9c39425 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -3224,9 +3224,11 @@ intel_dp_detect(struct drm_connector *connector, bool force)
> >  	struct drm_device *dev = connector->dev;
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	enum drm_connector_status status;
> > +	enum intel_display_power_domain power_domain;
> >  	struct edid *edid = NULL;
> >  
> > -	intel_runtime_pm_get(dev_priv);
> > +	power_domain = intel_display_port_power_domain(intel_encoder);
> > +	intel_display_power_get(dev_priv, power_domain);
> >  
> >  	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> >  		      connector->base.id, drm_get_connector_name(connector));
> > @@ -3256,23 +3258,31 @@ intel_dp_detect(struct drm_connector *connector, bool force)
> >  	if (intel_encoder->type != INTEL_OUTPUT_EDP)
> >  		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
> >  	status = connector_status_connected;
> > -
> >  out:
> > -	intel_runtime_pm_put(dev_priv);
> > +	intel_display_power_put(dev_priv, power_domain);
> > +
> >  	return status;
> >  }
> >  
> >  static int intel_dp_get_modes(struct drm_connector *connector)
> >  {
> >  	struct intel_dp *intel_dp = intel_attached_dp(connector);
> > +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> > +	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> >  	struct intel_connector *intel_connector = to_intel_connector(connector);
> >  	struct drm_device *dev = connector->dev;
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	enum intel_display_power_domain power_domain;
> >  	int ret;
> >  
> >  	/* We should parse the EDID data and find out if it has an audio sink
> >  	 */
> >  
> > +	power_domain = intel_display_port_power_domain(intel_encoder);
> > +	intel_display_power_get(dev_priv, power_domain);
> > +
> >  	ret = intel_dp_get_edid_modes(connector, &intel_dp->adapter);
> > +	intel_display_power_put(dev_priv, power_domain);
> >  	if (ret)
> >  		return ret;
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
> > index 3ee1db1..63b95bbd 100644
> > --- a/drivers/gpu/drm/i915/intel_dsi.c
> > +++ b/drivers/gpu/drm/i915/intel_dsi.c
> > @@ -488,8 +488,19 @@ static enum drm_connector_status
> >  intel_dsi_detect(struct drm_connector *connector, bool force)
> >  {
> >  	struct intel_dsi *intel_dsi = intel_attached_dsi(connector);
> > +	struct intel_encoder *intel_encoder = &intel_dsi->base;
> > +	enum intel_display_power_domain power_domain;
> > +	enum drm_connector_status connector_status;
> > +	struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
> > +
> >  	DRM_DEBUG_KMS("\n");
> > -	return intel_dsi->dev.dev_ops->detect(&intel_dsi->dev);
> > +	power_domain = intel_display_port_power_domain(intel_encoder);
> > +
> > +	intel_display_power_get(dev_priv, power_domain);
> > +	connector_status = intel_dsi->dev.dev_ops->detect(&intel_dsi->dev);
> > +	intel_display_power_put(dev_priv, power_domain);
> > +
> > +	return connector_status;
> >  }
> >  
> >  static int intel_dsi_get_modes(struct drm_connector *connector)
> > -- 
> > 1.8.4
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 01/19] drm/i915: use drm_i915_private everywhere in the power domain api
  2014-02-17 22:02 ` [PATCH 01/19] drm/i915: use drm_i915_private everywhere in the power domain api Imre Deak
@ 2014-02-20 19:16   ` Jesse Barnes
  0 siblings, 0 replies; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:16 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:02 +0200
Imre Deak <imre.deak@intel.com> wrote:

> The power domains framework is internal to the i915 driver, so pass
> drm_i915_private instead of drm_device to its functions.
> 
> Also remove a dangling intel_set_power_well() declaration.
> 
> No functional change.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c      | 14 ++++----
>  drivers/gpu/drm/i915/i915_drv.c      |  4 +--
>  drivers/gpu/drm/i915/i915_drv.h      |  4 +--
>  drivers/gpu/drm/i915/intel_display.c | 27 +++++++--------
>  drivers/gpu/drm/i915/intel_drv.h     | 17 +++++-----
>  drivers/gpu/drm/i915/intel_pm.c      | 65 ++++++++++++++----------------------
>  6 files changed, 58 insertions(+), 73 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 7688abc..8177c17 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1325,7 +1325,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  	if (ret)
>  		goto cleanup_gem_stolen;
>  
> -	intel_power_domains_init_hw(dev);
> +	intel_power_domains_init_hw(dev_priv);
>  
>  	/* Important: The output setup functions called by modeset_init need
>  	 * working irqs for e.g. gmbus and dp aux transfers. */
> @@ -1343,7 +1343,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  	/* FIXME: do pre/post-mode set stuff in core KMS code */
>  	dev->vblank_disable_allowed = true;
>  	if (INTEL_INFO(dev)->num_pipes == 0) {
> -		intel_display_power_put(dev, POWER_DOMAIN_VGA);
> +		intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
>  		return 0;
>  	}
>  
> @@ -1381,7 +1381,7 @@ cleanup_gem:
>  	WARN_ON(dev_priv->mm.aliasing_ppgtt);
>  	drm_mm_takedown(&dev_priv->gtt.base.mm);
>  cleanup_power:
> -	intel_display_power_put(dev, POWER_DOMAIN_VGA);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_VGA);
>  	drm_irq_uninstall(dev);
>  cleanup_gem_stolen:
>  	i915_gem_cleanup_stolen(dev);
> @@ -1702,7 +1702,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  			goto out_gem_unload;
>  	}
>  
> -	intel_power_domains_init(dev);
> +	intel_power_domains_init(dev_priv);
>  
>  	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
>  		ret = i915_load_modeset_init(dev);
> @@ -1731,7 +1731,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  	return 0;
>  
>  out_power_well:
> -	intel_power_domains_remove(dev);
> +	intel_power_domains_remove(dev_priv);
>  	drm_vblank_cleanup(dev);
>  out_gem_unload:
>  	if (dev_priv->mm.inactive_shrinker.scan_objects)
> @@ -1781,8 +1781,8 @@ int i915_driver_unload(struct drm_device *dev)
>  	/* The i915.ko module is still not prepared to be loaded when
>  	 * the power well is not enabled, so just enable it in case
>  	 * we're going to unload/reload. */
> -	intel_display_set_init_power(dev, true);
> -	intel_power_domains_remove(dev);
> +	intel_display_set_init_power(dev_priv, true);
> +	intel_power_domains_remove(dev_priv);
>  
>  	i915_teardown_sysfs(dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 08052f3d..ce898af 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -429,7 +429,7 @@ static int i915_drm_freeze(struct drm_device *dev)
>  	/* We do a lot of poking in a lot of registers, make sure they work
>  	 * properly. */
>  	hsw_disable_package_c8(dev_priv);
> -	intel_display_set_init_power(dev, true);
> +	intel_display_set_init_power(dev_priv, true);
>  
>  	drm_kms_helper_poll_disable(dev);
>  
> @@ -551,7 +551,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings)
>  		mutex_unlock(&dev->struct_mutex);
>  	}
>  
> -	intel_power_domains_init_hw(dev);
> +	intel_power_domains_init_hw(dev_priv);
>  
>  	i915_restore_state(dev);
>  	intel_opregion_setup(dev);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 8c64831..796f971 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1024,9 +1024,9 @@ struct i915_power_well {
>  	int count;
>  	unsigned long domains;
>  	void *data;
> -	void (*set)(struct drm_device *dev, struct i915_power_well *power_well,
> +	void (*set)(struct drm_i915_private *dev_priv, struct i915_power_well *power_well,
>  		    bool enable);
> -	bool (*is_enabled)(struct drm_device *dev,
> +	bool (*is_enabled)(struct drm_i915_private *dev_priv,
>  			   struct i915_power_well *power_well);
>  };
>  
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index f19e6ea..17c2033 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1122,7 +1122,7 @@ void assert_pipe(struct drm_i915_private *dev_priv,
>  	if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
>  		state = true;
>  
> -	if (!intel_display_power_enabled(dev_priv->dev,
> +	if (!intel_display_power_enabled(dev_priv,
>  				POWER_DOMAIN_TRANSCODER(cpu_transcoder))) {
>  		cur_state = false;
>  	} else {
> @@ -6858,23 +6858,23 @@ static unsigned long get_pipe_power_domains(struct drm_device *dev,
>  	return mask;
>  }
>  
> -void intel_display_set_init_power(struct drm_device *dev, bool enable)
> +void intel_display_set_init_power(struct drm_i915_private *dev_priv,
> +				  bool enable)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
>  	if (dev_priv->power_domains.init_power_on == enable)
>  		return;
>  
>  	if (enable)
> -		intel_display_power_get(dev, POWER_DOMAIN_INIT);
> +		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
>  	else
> -		intel_display_power_put(dev, POWER_DOMAIN_INIT);
> +		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
>  
>  	dev_priv->power_domains.init_power_on = enable;
>  }
>  
>  static void modeset_update_power_wells(struct drm_device *dev)
>  {
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  	unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
>  	struct intel_crtc *crtc;
>  
> @@ -6893,19 +6893,19 @@ static void modeset_update_power_wells(struct drm_device *dev)
>  						crtc->config.pch_pfit.enabled);
>  
>  		for_each_power_domain(domain, pipe_domains[crtc->pipe])
> -			intel_display_power_get(dev, domain);
> +			intel_display_power_get(dev_priv, domain);
>  	}
>  
>  	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
>  		enum intel_display_power_domain domain;
>  
>  		for_each_power_domain(domain, crtc->enabled_power_domains)
> -			intel_display_power_put(dev, domain);
> +			intel_display_power_put(dev_priv, domain);
>  
>  		crtc->enabled_power_domains = pipe_domains[crtc->pipe];
>  	}
>  
> -	intel_display_set_init_power(dev, false);
> +	intel_display_set_init_power(dev_priv, false);
>  }
>  
>  static void haswell_modeset_global_resources(struct drm_device *dev)
> @@ -6986,7 +6986,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>  			pipe_config->cpu_transcoder = TRANSCODER_EDP;
>  	}
>  
> -	if (!intel_display_power_enabled(dev,
> +	if (!intel_display_power_enabled(dev_priv,
>  			POWER_DOMAIN_TRANSCODER(pipe_config->cpu_transcoder)))
>  		return false;
>  
> @@ -7014,7 +7014,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
>  	intel_get_pipe_timings(crtc, pipe_config);
>  
>  	pfit_domain = POWER_DOMAIN_PIPE_PANEL_FITTER(crtc->pipe);
> -	if (intel_display_power_enabled(dev, pfit_domain))
> +	if (intel_display_power_enabled(dev_priv, pfit_domain))
>  		ironlake_get_pfit_config(crtc, pipe_config);
>  
>  	if (IS_HASWELL(dev))
> @@ -11602,7 +11602,8 @@ intel_display_capture_error_state(struct drm_device *dev)
>  
>  	for_each_pipe(i) {
>  		error->pipe[i].power_domain_on =
> -			intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
> +			intel_display_power_enabled_sw(dev_priv,
> +						       POWER_DOMAIN_PIPE(i));
>  		if (!error->pipe[i].power_domain_on)
>  			continue;
>  
> @@ -11640,7 +11641,7 @@ intel_display_capture_error_state(struct drm_device *dev)
>  		enum transcoder cpu_transcoder = transcoders[i];
>  
>  		error->transcoder[i].power_domain_on =
> -			intel_display_power_enabled_sw(dev,
> +			intel_display_power_enabled_sw(dev_priv,
>  				POWER_DOMAIN_TRANSCODER(cpu_transcoder));
>  		if (!error->transcoder[i].power_domain_on)
>  			continue;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index a4ffc02..6042797 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -732,7 +732,7 @@ ironlake_check_encoder_dotclock(const struct intel_crtc_config *pipe_config,
>  bool intel_crtc_active(struct drm_crtc *crtc);
>  void hsw_enable_ips(struct intel_crtc *crtc);
>  void hsw_disable_ips(struct intel_crtc *crtc);
> -void intel_display_set_init_power(struct drm_device *dev, bool enable);
> +void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
>  int valleyview_get_vco(struct drm_i915_private *dev_priv);
>  void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>  				 struct intel_crtc_config *pipe_config);
> @@ -871,18 +871,17 @@ bool intel_fbc_enabled(struct drm_device *dev);
>  void intel_update_fbc(struct drm_device *dev);
>  void intel_gpu_ips_init(struct drm_i915_private *dev_priv);
>  void intel_gpu_ips_teardown(void);
> -int intel_power_domains_init(struct drm_device *dev);
> -void intel_power_domains_remove(struct drm_device *dev);
> -bool intel_display_power_enabled(struct drm_device *dev,
> +int intel_power_domains_init(struct drm_i915_private *);
> +void intel_power_domains_remove(struct drm_i915_private *);
> +bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
>  				 enum intel_display_power_domain domain);
> -bool intel_display_power_enabled_sw(struct drm_device *dev,
> +bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
>  				    enum intel_display_power_domain domain);
> -void intel_display_power_get(struct drm_device *dev,
> +void intel_display_power_get(struct drm_i915_private *dev_priv,
>  			     enum intel_display_power_domain domain);
> -void intel_display_power_put(struct drm_device *dev,
> +void intel_display_power_put(struct drm_i915_private *dev_priv,
>  			     enum intel_display_power_domain domain);
> -void intel_power_domains_init_hw(struct drm_device *dev);
> -void intel_set_power_well(struct drm_device *dev, bool enable);
> +void intel_power_domains_init_hw(struct drm_i915_private *dev_priv);
>  void intel_enable_gt_powersave(struct drm_device *dev);
>  void intel_disable_gt_powersave(struct drm_device *dev);
>  void ironlake_teardown_rc6(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index c8347ae..aa9c2df 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5169,19 +5169,16 @@ void intel_suspend_hw(struct drm_device *dev)
>   * enable it, so check if it's enabled and also check if we've requested it to
>   * be enabled.
>   */
> -static bool hsw_power_well_enabled(struct drm_device *dev,
> +static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
>  				   struct i915_power_well *power_well)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
>  	return I915_READ(HSW_PWR_WELL_DRIVER) ==
>  		     (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
>  }
>  
> -bool intel_display_power_enabled_sw(struct drm_device *dev,
> +bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
>  				    enum intel_display_power_domain domain)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct i915_power_domains *power_domains;
>  
>  	power_domains = &dev_priv->power_domains;
> @@ -5189,10 +5186,9 @@ bool intel_display_power_enabled_sw(struct drm_device *dev,
>  	return power_domains->domain_use_count[domain];
>  }
>  
> -bool intel_display_power_enabled(struct drm_device *dev,
> +bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
>  				 enum intel_display_power_domain domain)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct i915_power_domains *power_domains;
>  	struct i915_power_well *power_well;
>  	bool is_enabled;
> @@ -5207,7 +5203,7 @@ bool intel_display_power_enabled(struct drm_device *dev,
>  		if (power_well->always_on)
>  			continue;
>  
> -		if (!power_well->is_enabled(dev, power_well)) {
> +		if (!power_well->is_enabled(dev_priv, power_well)) {
>  			is_enabled = false;
>  			break;
>  		}
> @@ -5273,10 +5269,9 @@ static void hsw_power_well_post_disable(struct drm_i915_private *dev_priv)
>  	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
>  }
>  
> -static void hsw_set_power_well(struct drm_device *dev,
> +static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  			       struct i915_power_well *power_well, bool enable)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  	bool is_enabled, enable_requested;
>  	uint32_t tmp;
>  
> @@ -5310,35 +5305,30 @@ static void hsw_set_power_well(struct drm_device *dev,
>  	}
>  }
>  
> -static void __intel_power_well_get(struct drm_device *dev,
> +static void __intel_power_well_get(struct drm_i915_private *dev_priv,
>  				   struct i915_power_well *power_well)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
>  	if (!power_well->count++ && power_well->set) {
>  		hsw_disable_package_c8(dev_priv);
> -		power_well->set(dev, power_well, true);
> +		power_well->set(dev_priv, power_well, true);
>  	}
>  }
>  
> -static void __intel_power_well_put(struct drm_device *dev,
> +static void __intel_power_well_put(struct drm_i915_private *dev_priv,
>  				   struct i915_power_well *power_well)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
>  	WARN_ON(!power_well->count);
>  
>  	if (!--power_well->count && power_well->set &&
>  	    i915.disable_power_well) {
> -		power_well->set(dev, power_well, false);
> +		power_well->set(dev_priv, power_well, false);
>  		hsw_enable_package_c8(dev_priv);
>  	}
>  }
>  
> -void intel_display_power_get(struct drm_device *dev,
> +void intel_display_power_get(struct drm_i915_private *dev_priv,
>  			     enum intel_display_power_domain domain)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct i915_power_domains *power_domains;
>  	struct i915_power_well *power_well;
>  	int i;
> @@ -5348,17 +5338,16 @@ void intel_display_power_get(struct drm_device *dev,
>  	mutex_lock(&power_domains->lock);
>  
>  	for_each_power_well(i, power_well, BIT(domain), power_domains)
> -		__intel_power_well_get(dev, power_well);
> +		__intel_power_well_get(dev_priv, power_well);
>  
>  	power_domains->domain_use_count[domain]++;
>  
>  	mutex_unlock(&power_domains->lock);
>  }
>  
> -void intel_display_power_put(struct drm_device *dev,
> +void intel_display_power_put(struct drm_i915_private *dev_priv,
>  			     enum intel_display_power_domain domain)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct i915_power_domains *power_domains;
>  	struct i915_power_well *power_well;
>  	int i;
> @@ -5371,7 +5360,7 @@ void intel_display_power_put(struct drm_device *dev,
>  	power_domains->domain_use_count[domain]--;
>  
>  	for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
> -		__intel_power_well_put(dev, power_well);
> +		__intel_power_well_put(dev_priv, power_well);
>  
>  	mutex_unlock(&power_domains->lock);
>  }
> @@ -5388,7 +5377,7 @@ void i915_request_power_well(void)
>  
>  	dev_priv = container_of(hsw_pwr, struct drm_i915_private,
>  				power_domains);
> -	intel_display_power_get(dev_priv->dev, POWER_DOMAIN_AUDIO);
> +	intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
>  }
>  EXPORT_SYMBOL_GPL(i915_request_power_well);
>  
> @@ -5402,7 +5391,7 @@ void i915_release_power_well(void)
>  
>  	dev_priv = container_of(hsw_pwr, struct drm_i915_private,
>  				power_domains);
> -	intel_display_power_put(dev_priv->dev, POWER_DOMAIN_AUDIO);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO);
>  }
>  EXPORT_SYMBOL_GPL(i915_release_power_well);
>  
> @@ -5447,9 +5436,8 @@ static struct i915_power_well bdw_power_wells[] = {
>  	(power_domains)->power_well_count = ARRAY_SIZE(__power_wells);	\
>  })
>  
> -int intel_power_domains_init(struct drm_device *dev)
> +int intel_power_domains_init(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct i915_power_domains *power_domains = &dev_priv->power_domains;
>  
>  	mutex_init(&power_domains->lock);
> @@ -5458,10 +5446,10 @@ int intel_power_domains_init(struct drm_device *dev)
>  	 * The enabling order will be from lower to higher indexed wells,
>  	 * the disabling order is reversed.
>  	 */
> -	if (IS_HASWELL(dev)) {
> +	if (IS_HASWELL(dev_priv->dev)) {
>  		set_power_wells(power_domains, hsw_power_wells);
>  		hsw_pwr = power_domains;
> -	} else if (IS_BROADWELL(dev)) {
> +	} else if (IS_BROADWELL(dev_priv->dev)) {
>  		set_power_wells(power_domains, bdw_power_wells);
>  		hsw_pwr = power_domains;
>  	} else {
> @@ -5471,14 +5459,13 @@ int intel_power_domains_init(struct drm_device *dev)
>  	return 0;
>  }
>  
> -void intel_power_domains_remove(struct drm_device *dev)
> +void intel_power_domains_remove(struct drm_i915_private *dev_priv)
>  {
>  	hsw_pwr = NULL;
>  }
>  
> -static void intel_power_domains_resume(struct drm_device *dev)
> +static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  	struct i915_power_domains *power_domains = &dev_priv->power_domains;
>  	struct i915_power_well *power_well;
>  	int i;
> @@ -5486,7 +5473,7 @@ static void intel_power_domains_resume(struct drm_device *dev)
>  	mutex_lock(&power_domains->lock);
>  	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
>  		if (power_well->set)
> -			power_well->set(dev, power_well, power_well->count > 0);
> +			power_well->set(dev_priv, power_well, power_well->count > 0);
>  	}
>  	mutex_unlock(&power_domains->lock);
>  }
> @@ -5497,15 +5484,13 @@ static void intel_power_domains_resume(struct drm_device *dev)
>   * to be enabled, and it will only be disabled if none of the registers is
>   * requesting it to be enabled.
>   */
> -void intel_power_domains_init_hw(struct drm_device *dev)
> +void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
>  {
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
>  	/* For now, we need the power well to be always enabled. */
> -	intel_display_set_init_power(dev, true);
> -	intel_power_domains_resume(dev);
> +	intel_display_set_init_power(dev_priv, true);
> +	intel_power_domains_resume(dev_priv);
>  
> -	if (!(IS_HASWELL(dev) || IS_BROADWELL(dev)))
> +	if (!(IS_HASWELL(dev_priv->dev) || IS_BROADWELL(dev_priv->dev)))
>  		return;
>  
>  	/* We're taking over the BIOS, so clear any requests made by it since

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions
  2014-02-17 22:02 ` [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions Imre Deak
@ 2014-02-20 19:17   ` Jesse Barnes
  2014-02-20 19:44     ` Chris Wilson
  2014-02-24 13:23   ` Paulo Zanoni
  1 sibling, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:17 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:03 +0200
Imre Deak <imre.deak@intel.com> wrote:

> These functions are used only by a single call site and are simple
> enough to just fold them in.
> 
> No functional change.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 37 +++++++++++++------------------------
>  1 file changed, 13 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index aa9c2df..db48d55 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5305,27 +5305,6 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  	}
>  }
>  
> -static void __intel_power_well_get(struct drm_i915_private *dev_priv,
> -				   struct i915_power_well *power_well)
> -{
> -	if (!power_well->count++ && power_well->set) {
> -		hsw_disable_package_c8(dev_priv);
> -		power_well->set(dev_priv, power_well, true);
> -	}
> -}
> -
> -static void __intel_power_well_put(struct drm_i915_private *dev_priv,
> -				   struct i915_power_well *power_well)
> -{
> -	WARN_ON(!power_well->count);
> -
> -	if (!--power_well->count && power_well->set &&
> -	    i915.disable_power_well) {
> -		power_well->set(dev_priv, power_well, false);
> -		hsw_enable_package_c8(dev_priv);
> -	}
> -}
> -
>  void intel_display_power_get(struct drm_i915_private *dev_priv,
>  			     enum intel_display_power_domain domain)
>  {
> @@ -5338,7 +5317,10 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
>  	mutex_lock(&power_domains->lock);
>  
>  	for_each_power_well(i, power_well, BIT(domain), power_domains)
> -		__intel_power_well_get(dev_priv, power_well);
> +		if (!power_well->count++ && power_well->set) {
> +			hsw_disable_package_c8(dev_priv);
> +			power_well->set(dev_priv, power_well, true);
> +		}
>  
>  	power_domains->domain_use_count[domain]++;
>  
> @@ -5359,8 +5341,15 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
>  	WARN_ON(!power_domains->domain_use_count[domain]);
>  	power_domains->domain_use_count[domain]--;
>  
> -	for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
> -		__intel_power_well_put(dev_priv, power_well);
> +	for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> +		WARN_ON(!power_well->count);
> +
> +		if (!--power_well->count && power_well->set &&
> +				i915.disable_power_well) {
> +			power_well->set(dev_priv, power_well, false);
> +			hsw_enable_package_c8(dev_priv);
> +		}
> +	}
>  
>  	mutex_unlock(&power_domains->lock);
>  }

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 03/19] drm/i915: move modeset_update_power_wells earlier
  2014-02-17 22:02 ` [PATCH 03/19] drm/i915: move modeset_update_power_wells earlier Imre Deak
@ 2014-02-20 19:18   ` Jesse Barnes
  0 siblings, 0 replies; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:18 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:04 +0200
Imre Deak <imre.deak@intel.com> wrote:

> These functions will be needed by the valleyview specific power well
> update functionality added in an upcoming patch, so move them earlier.
> 
> No functional change.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 140 +++++++++++++++++------------------
>  1 file changed, 70 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 17c2033..fa50f6e 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3953,6 +3953,76 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
>  	I915_WRITE(BCLRPAT(crtc->pipe), 0);
>  }
>  
> +#define for_each_power_domain(domain, mask)				\
> +	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
> +		if ((1 << (domain)) & (mask))
> +
> +static unsigned long get_pipe_power_domains(struct drm_device *dev,
> +					    enum pipe pipe, bool pfit_enabled)
> +{
> +	unsigned long mask;
> +	enum transcoder transcoder;
> +
> +	transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
> +
> +	mask = BIT(POWER_DOMAIN_PIPE(pipe));
> +	mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
> +	if (pfit_enabled)
> +		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
> +
> +	return mask;
> +}
> +
> +void intel_display_set_init_power(struct drm_i915_private *dev_priv,
> +				  bool enable)
> +{
> +	if (dev_priv->power_domains.init_power_on == enable)
> +		return;
> +
> +	if (enable)
> +		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> +	else
> +		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> +
> +	dev_priv->power_domains.init_power_on = enable;
> +}
> +
> +static void modeset_update_power_wells(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
> +	struct intel_crtc *crtc;
> +
> +	/*
> +	 * First get all needed power domains, then put all unneeded, to avoid
> +	 * any unnecessary toggling of the power wells.
> +	 */
> +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
> +		enum intel_display_power_domain domain;
> +
> +		if (!crtc->base.enabled)
> +			continue;
> +
> +		pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
> +						crtc->pipe,
> +						crtc->config.pch_pfit.enabled);
> +
> +		for_each_power_domain(domain, pipe_domains[crtc->pipe])
> +			intel_display_power_get(dev_priv, domain);
> +	}
> +
> +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
> +		enum intel_display_power_domain domain;
> +
> +		for_each_power_domain(domain, crtc->enabled_power_domains)
> +			intel_display_power_put(dev_priv, domain);
> +
> +		crtc->enabled_power_domains = pipe_domains[crtc->pipe];
> +	}
> +
> +	intel_display_set_init_power(dev_priv, false);
> +}
> +
>  int valleyview_get_vco(struct drm_i915_private *dev_priv)
>  {
>  	int hpll_freq, vco_freq[] = { 800, 1600, 2000, 2400 };
> @@ -6838,76 +6908,6 @@ static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv)
>  	mutex_unlock(&dev_priv->pc8.lock);
>  }
>  
> -#define for_each_power_domain(domain, mask)				\
> -	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
> -		if ((1 << (domain)) & (mask))
> -
> -static unsigned long get_pipe_power_domains(struct drm_device *dev,
> -					    enum pipe pipe, bool pfit_enabled)
> -{
> -	unsigned long mask;
> -	enum transcoder transcoder;
> -
> -	transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe);
> -
> -	mask = BIT(POWER_DOMAIN_PIPE(pipe));
> -	mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder));
> -	if (pfit_enabled)
> -		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
> -
> -	return mask;
> -}
> -
> -void intel_display_set_init_power(struct drm_i915_private *dev_priv,
> -				  bool enable)
> -{
> -	if (dev_priv->power_domains.init_power_on == enable)
> -		return;
> -
> -	if (enable)
> -		intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
> -	else
> -		intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
> -
> -	dev_priv->power_domains.init_power_on = enable;
> -}
> -
> -static void modeset_update_power_wells(struct drm_device *dev)
> -{
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	unsigned long pipe_domains[I915_MAX_PIPES] = { 0, };
> -	struct intel_crtc *crtc;
> -
> -	/*
> -	 * First get all needed power domains, then put all unneeded, to avoid
> -	 * any unnecessary toggling of the power wells.
> -	 */
> -	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
> -		enum intel_display_power_domain domain;
> -
> -		if (!crtc->base.enabled)
> -			continue;
> -
> -		pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
> -						crtc->pipe,
> -						crtc->config.pch_pfit.enabled);
> -
> -		for_each_power_domain(domain, pipe_domains[crtc->pipe])
> -			intel_display_power_get(dev_priv, domain);
> -	}
> -
> -	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
> -		enum intel_display_power_domain domain;
> -
> -		for_each_power_domain(domain, crtc->enabled_power_domains)
> -			intel_display_power_put(dev_priv, domain);
> -
> -		crtc->enabled_power_domains = pipe_domains[crtc->pipe];
> -	}
> -
> -	intel_display_set_init_power(dev_priv, false);
> -}
> -
>  static void haswell_modeset_global_resources(struct drm_device *dev)
>  {
>  	modeset_update_power_wells(dev);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 04/19] drm/i915: move power domain macros to intel_pm.c
  2014-02-17 22:02 ` [PATCH 04/19] drm/i915: move power domain macros to intel_pm.c Imre Deak
@ 2014-02-20 19:21   ` Jesse Barnes
  2014-02-24 13:38     ` Paulo Zanoni
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:21 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:05 +0200
Imre Deak <imre.deak@intel.com> wrote:

> These macros are used only locally, so move them to the .c file.
> 
> Also since logically the init power domain should be part of all power
> wells add it to the always-on power wells too for consistency. Since
> always-on power wells have noop handlers, this doesn't change the
> functionality.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h | 10 ----------
>  drivers/gpu/drm/i915/intel_pm.c | 21 +++++++++++++++++++--
>  2 files changed, 19 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 796f971..de0c0e0 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -121,8 +121,6 @@ enum intel_display_power_domain {
>  	POWER_DOMAIN_NUM,
>  };
>  
> -#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
> -
>  #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
>  #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
>  		((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
> @@ -130,14 +128,6 @@ enum intel_display_power_domain {
>  	((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
>  	 (tran) + POWER_DOMAIN_TRANSCODER_A)
>  
> -#define HSW_ALWAYS_ON_POWER_DOMAINS (		\
> -	BIT(POWER_DOMAIN_PIPE_A) |		\
> -	BIT(POWER_DOMAIN_TRANSCODER_EDP))
> -#define BDW_ALWAYS_ON_POWER_DOMAINS (		\
> -	BIT(POWER_DOMAIN_PIPE_A) |		\
> -	BIT(POWER_DOMAIN_TRANSCODER_EDP) |	\
> -	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
> -
>  enum hpd_pin {
>  	HPD_NONE = 0,
>  	HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index db48d55..9a608f1 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5384,6 +5384,23 @@ void i915_release_power_well(void)
>  }
>  EXPORT_SYMBOL_GPL(i915_release_power_well);
>  
> +#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
> +
> +#define HSW_ALWAYS_ON_POWER_DOMAINS (			\
> +	BIT(POWER_DOMAIN_PIPE_A) |			\
> +	BIT(POWER_DOMAIN_TRANSCODER_EDP) |		\
> +	BIT(POWER_DOMAIN_INIT))
> +#define HSW_DISPLAY_POWER_DOMAINS (				\
> +	(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |	\
> +	BIT(POWER_DOMAIN_INIT))
> +
> +#define BDW_ALWAYS_ON_POWER_DOMAINS (			\
> +	HSW_ALWAYS_ON_POWER_DOMAINS |			\
> +	BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
> +#define BDW_DISPLAY_POWER_DOMAINS (				\
> +	(POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |	\
> +	BIT(POWER_DOMAIN_INIT))
> +
>  static struct i915_power_well i9xx_always_on_power_well[] = {
>  	{
>  		.name = "always-on",
> @@ -5400,7 +5417,7 @@ static struct i915_power_well hsw_power_wells[] = {
>  	},
>  	{
>  		.name = "display",
> -		.domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS,
> +		.domains = HSW_DISPLAY_POWER_DOMAINS,
>  		.is_enabled = hsw_power_well_enabled,
>  		.set = hsw_set_power_well,
>  	},
> @@ -5414,7 +5431,7 @@ static struct i915_power_well bdw_power_wells[] = {
>  	},
>  	{
>  		.name = "display",
> -		.domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS,
> +		.domains = BDW_DISPLAY_POWER_DOMAINS,
>  		.is_enabled = hsw_power_well_enabled,
>  		.set = hsw_set_power_well,
>  	},

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 05/19] drm/i915: power domains: add power well ops
  2014-02-17 22:02 ` [PATCH 05/19] drm/i915: power domains: add power well ops Imre Deak
@ 2014-02-20 19:26   ` Jesse Barnes
  2014-02-24 11:42     ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:26 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:06 +0200
Imre Deak <imre.deak@intel.com> wrote:

> Split the 'set' power well handler into an 'enable', 'disable' and
> 'sync_hw' handler. This maps more conveniently to higher level
> operations, for example it allows us to push the hsw package c8 handling
> into the corresponding hsw/bdw enable/disable handlers and the hsw BIOS
> hand-over setting into the hsw/bdw sync_hw handler.
> 
> No functional change.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h | 35 +++++++++++++++++---
>  drivers/gpu/drm/i915/intel_pm.c | 73 +++++++++++++++++++++++++++--------------
>  2 files changed, 80 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index de0c0e0..8c8635e 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1006,6 +1006,36 @@ struct intel_ilk_power_mgmt {
>  	struct drm_i915_gem_object *renderctx;
>  };
>  
> +struct drm_i915_private;
> +struct i915_power_well;
> +
> +struct i915_power_well_ops {
> +	/*
> +	 * Synchronize the well's hw state to match the current sw state, for
> +	 * example enable/disable it based on the current refcount. Called
> +	 * during driver init and resume time, possibly after first calling
> +	 * the enable/disable handlers.
> +	 */
> +	void (*sync_hw)(struct drm_i915_private *dev_priv,
> +		        struct i915_power_well *power_well);
> +	/*
> +	 * Enable the well and resources that depend on it (for example
> +	 * interrupts located on the well). Called after the 0->1 refcount
> +	 * transition.
> +	 */
> +	void (*enable)(struct drm_i915_private *dev_priv,
> +		       struct i915_power_well *power_well);
> +	/*
> +	 * Disable the well and resources that depend on it. Called after
> +	 * the 1->0 refcount transition.
> +	 */
> +	void (*disable)(struct drm_i915_private *dev_priv,
> +		        struct i915_power_well *power_well);
> +	/* Returns the hw enabled state. */
> +	bool (*is_enabled)(struct drm_i915_private *dev_priv,
> +			   struct i915_power_well *power_well);
> +};
> +
>  /* Power well structure for haswell */
>  struct i915_power_well {
>  	const char *name;
> @@ -1014,10 +1044,7 @@ struct i915_power_well {
>  	int count;
>  	unsigned long domains;
>  	void *data;
> -	void (*set)(struct drm_i915_private *dev_priv, struct i915_power_well *power_well,
> -		    bool enable);
> -	bool (*is_enabled)(struct drm_i915_private *dev_priv,
> -			   struct i915_power_well *power_well);
> +	const struct i915_power_well_ops *ops;
>  };
>  
>  struct i915_power_domains {
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 9a608f1..7866426 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5203,7 +5203,7 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
>  		if (power_well->always_on)
>  			continue;
>  
> -		if (!power_well->is_enabled(dev_priv, power_well)) {
> +		if (!power_well->ops->is_enabled(dev_priv, power_well)) {
>  			is_enabled = false;
>  			break;
>  		}
> @@ -5305,6 +5305,33 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>  	}
>  }
>  
> +static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
> +			           struct i915_power_well *power_well)
> +{
> +	hsw_set_power_well(dev_priv, power_well, power_well->count > 0);
> +
> +	/*
> +	 * We're taking over the BIOS, so clear any requests made by it since
> +	 * the driver is in charge now.
> +	 */
> +	if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
> +		I915_WRITE(HSW_PWR_WELL_BIOS, 0);
> +}
> +
> +static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
> +				  struct i915_power_well *power_well)
> +{
> +	hsw_disable_package_c8(dev_priv);
> +	hsw_set_power_well(dev_priv, power_well, true);
> +}
> +
> +static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> +				   struct i915_power_well *power_well)
> +{
> +	hsw_set_power_well(dev_priv, power_well, false);
> +	hsw_enable_package_c8(dev_priv);
> +}
> +
>  void intel_display_power_get(struct drm_i915_private *dev_priv,
>  			     enum intel_display_power_domain domain)
>  {
> @@ -5317,10 +5344,8 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
>  	mutex_lock(&power_domains->lock);
>  
>  	for_each_power_well(i, power_well, BIT(domain), power_domains)
> -		if (!power_well->count++ && power_well->set) {
> -			hsw_disable_package_c8(dev_priv);
> -			power_well->set(dev_priv, power_well, true);
> -		}
> +		if (!power_well->count++ && power_well->ops->enable)
> +			power_well->ops->enable(dev_priv, power_well);
>  
>  	power_domains->domain_use_count[domain]++;
>  
> @@ -5344,11 +5369,9 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
>  	for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
>  		WARN_ON(!power_well->count);
>  
> -		if (!--power_well->count && power_well->set &&
> -				i915.disable_power_well) {
> -			power_well->set(dev_priv, power_well, false);
> -			hsw_enable_package_c8(dev_priv);
> -		}
> +		if (!--power_well->count && power_well->ops->disable &&
> +		    i915.disable_power_well)
> +			power_well->ops->disable(dev_priv, power_well);
>  	}
>  
>  	mutex_unlock(&power_domains->lock);
> @@ -5401,25 +5424,35 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
>  	(POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |	\
>  	BIT(POWER_DOMAIN_INIT))
>  
> +static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { };
> +
>  static struct i915_power_well i9xx_always_on_power_well[] = {
>  	{
>  		.name = "always-on",
>  		.always_on = 1,
>  		.domains = POWER_DOMAIN_MASK,
> +		.ops = &i9xx_always_on_power_well_ops,
>  	},
>  };
>  
> +static const struct i915_power_well_ops hsw_power_well_ops = {
> +	.sync_hw = hsw_power_well_sync_hw,
> +	.enable = hsw_power_well_enable,
> +	.disable = hsw_power_well_disable,
> +	.is_enabled = hsw_power_well_enabled,
> +};
> +
>  static struct i915_power_well hsw_power_wells[] = {
>  	{
>  		.name = "always-on",
>  		.always_on = 1,
>  		.domains = HSW_ALWAYS_ON_POWER_DOMAINS,
> +		.ops = &i9xx_always_on_power_well_ops,
>  	},
>  	{
>  		.name = "display",
>  		.domains = HSW_DISPLAY_POWER_DOMAINS,
> -		.is_enabled = hsw_power_well_enabled,
> -		.set = hsw_set_power_well,
> +		.ops = &hsw_power_well_ops,
>  	},
>  };
>  
> @@ -5428,12 +5461,12 @@ static struct i915_power_well bdw_power_wells[] = {
>  		.name = "always-on",
>  		.always_on = 1,
>  		.domains = BDW_ALWAYS_ON_POWER_DOMAINS,
> +		.ops = &i9xx_always_on_power_well_ops,
>  	},
>  	{
>  		.name = "display",
>  		.domains = BDW_DISPLAY_POWER_DOMAINS,
> -		.is_enabled = hsw_power_well_enabled,
> -		.set = hsw_set_power_well,
> +		.ops = &hsw_power_well_ops,
>  	},
>  };
>  
> @@ -5478,8 +5511,8 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
>  
>  	mutex_lock(&power_domains->lock);
>  	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> -		if (power_well->set)
> -			power_well->set(dev_priv, power_well, power_well->count > 0);
> +		if (power_well->ops->sync_hw)
> +			power_well->ops->sync_hw(dev_priv, power_well);
>  	}
>  	mutex_unlock(&power_domains->lock);
>  }
> @@ -5495,14 +5528,6 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
>  	/* For now, we need the power well to be always enabled. */
>  	intel_display_set_init_power(dev_priv, true);
>  	intel_power_domains_resume(dev_priv);
> -
> -	if (!(IS_HASWELL(dev_priv->dev) || IS_BROADWELL(dev_priv->dev)))
> -		return;
> -
> -	/* We're taking over the BIOS, so clear any requests made by it since
> -	 * the driver is in charge now. */
> -	if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
> -		I915_WRITE(HSW_PWR_WELL_BIOS, 0);
>  }
>  
>  /* Disables PC8 so we can use the GMBUS and DP AUX interrupts. */

Looks good.  Only nitpick might be to have no-op ops for the 9xx case
and get rid of the checks for whether the ops function exists.  Going
forward that might force us to think about things a bit at least.  But
that's really just a style issue, the rest looks like a good change and
pulls some of the HSW bits out of the generic routines.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 06/19] drm/i915: remove power_well->always_on flag
  2014-02-17 22:02 ` [PATCH 06/19] drm/i915: remove power_well->always_on flag Imre Deak
@ 2014-02-20 19:27   ` Jesse Barnes
  0 siblings, 0 replies; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:27 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:07 +0200
Imre Deak <imre.deak@intel.com> wrote:

> An always-on power well can be already recognized by the lack of
> is_enabled handler, so just depend on that. Suggested by Daniel.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h | 1 -
>  drivers/gpu/drm/i915/intel_pm.c | 5 +----
>  2 files changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 8c8635e..eaa9210 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1039,7 +1039,6 @@ struct i915_power_well_ops {
>  /* Power well structure for haswell */
>  struct i915_power_well {
>  	const char *name;
> -	bool always_on;
>  	/* power well enable/disable usage count */
>  	int count;
>  	unsigned long domains;
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 7866426..faaa4ec 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5200,7 +5200,7 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
>  
>  	mutex_lock(&power_domains->lock);
>  	for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> -		if (power_well->always_on)
> +		if (!power_well->ops->is_enabled)
>  			continue;
>  
>  		if (!power_well->ops->is_enabled(dev_priv, power_well)) {
> @@ -5429,7 +5429,6 @@ static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { };
>  static struct i915_power_well i9xx_always_on_power_well[] = {
>  	{
>  		.name = "always-on",
> -		.always_on = 1,
>  		.domains = POWER_DOMAIN_MASK,
>  		.ops = &i9xx_always_on_power_well_ops,
>  	},
> @@ -5445,7 +5444,6 @@ static const struct i915_power_well_ops hsw_power_well_ops = {
>  static struct i915_power_well hsw_power_wells[] = {
>  	{
>  		.name = "always-on",
> -		.always_on = 1,
>  		.domains = HSW_ALWAYS_ON_POWER_DOMAINS,
>  		.ops = &i9xx_always_on_power_well_ops,
>  	},
> @@ -5459,7 +5457,6 @@ static struct i915_power_well hsw_power_wells[] = {
>  static struct i915_power_well bdw_power_wells[] = {
>  	{
>  		.name = "always-on",
> -		.always_on = 1,
>  		.domains = BDW_ALWAYS_ON_POWER_DOMAINS,
>  		.ops = &i9xx_always_on_power_well_ops,
>  	},

As in the previous mail, I think I'd prefer a no-op function that just
returns true instead, but meh.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 07/19] drm/i915: add port power domains
  2014-02-17 22:02 ` [PATCH 07/19] drm/i915: add port power domains Imre Deak
@ 2014-02-20 19:31   ` Jesse Barnes
  2014-02-24 11:52     ` Imre Deak
  2014-03-05 10:11   ` Daniel Vetter
  1 sibling, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:31 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:08 +0200
Imre Deak <imre.deak@intel.com> wrote:

> Parts that poke port specific HW blocks like the encoder HW state
> readout or connector hotplug detect code need a way to check whether
> required power domains are on or enable/disable these. For this purpose
> add a set of power domains that refer to the port HW blocks. Get the
> proper port power domains during modeset.
> 
> For now when requesting the power domain for a DDI port get it for a 4
> lane configuration. This can be optimized later to request only the 2
> lane power domain, when proper support is added on the VLV PHY side for
> this. Atm, the PHY setup code assumes a 4 lane config in all cases.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_debugfs.c  | 22 ++++++++++++++++
>  drivers/gpu/drm/i915/i915_drv.h      | 11 ++++++++
>  drivers/gpu/drm/i915/intel_display.c | 51 ++++++++++++++++++++++++++++++++----
>  drivers/gpu/drm/i915/intel_drv.h     |  2 ++
>  drivers/gpu/drm/i915/intel_pm.c      |  9 +++++++
>  5 files changed, 90 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> index d90a707..14c7730 100644
> --- a/drivers/gpu/drm/i915/i915_debugfs.c
> +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> @@ -2030,6 +2030,28 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
>  		return "TRANSCODER_C";
>  	case POWER_DOMAIN_TRANSCODER_EDP:
>  		return "TRANSCODER_EDP";
> +	case POWER_DOMAIN_PORT_DDI_A_2_LANES:
> +		return "PORT_DDI_A_2_LANES";
> +	case POWER_DOMAIN_PORT_DDI_A_4_LANES:
> +		return "PORT_DDI_A_4_LANES";
> +	case POWER_DOMAIN_PORT_DDI_B_2_LANES:
> +		return "PORT_DDI_B_2_LANES";
> +	case POWER_DOMAIN_PORT_DDI_B_4_LANES:
> +		return "PORT_DDI_B_4_LANES";
> +	case POWER_DOMAIN_PORT_DDI_C_2_LANES:
> +		return "PORT_DDI_C_2_LANES";
> +	case POWER_DOMAIN_PORT_DDI_C_4_LANES:
> +		return "PORT_DDI_C_4_LANES";
> +	case POWER_DOMAIN_PORT_DDI_D_2_LANES:
> +		return "PORT_DDI_D_2_LANES";
> +	case POWER_DOMAIN_PORT_DDI_D_4_LANES:
> +		return "PORT_DDI_D_4_LANES";
> +	case POWER_DOMAIN_PORT_DSI:
> +		return "PORT_DSI";
> +	case POWER_DOMAIN_PORT_CRT:
> +		return "PORT_CRT";
> +	case POWER_DOMAIN_PORT_OTHER:
> +		return "PORT_OTHER";
>  	case POWER_DOMAIN_VGA:
>  		return "VGA";
>  	case POWER_DOMAIN_AUDIO:
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index eaa9210..76bd03a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -114,6 +114,17 @@ enum intel_display_power_domain {
>  	POWER_DOMAIN_TRANSCODER_B,
>  	POWER_DOMAIN_TRANSCODER_C,
>  	POWER_DOMAIN_TRANSCODER_EDP,
> +	POWER_DOMAIN_PORT_DDI_A_2_LANES,
> +	POWER_DOMAIN_PORT_DDI_A_4_LANES,
> +	POWER_DOMAIN_PORT_DDI_B_2_LANES,
> +	POWER_DOMAIN_PORT_DDI_B_4_LANES,
> +	POWER_DOMAIN_PORT_DDI_C_2_LANES,
> +	POWER_DOMAIN_PORT_DDI_C_4_LANES,
> +	POWER_DOMAIN_PORT_DDI_D_2_LANES,
> +	POWER_DOMAIN_PORT_DDI_D_4_LANES,
> +	POWER_DOMAIN_PORT_DSI,
> +	POWER_DOMAIN_PORT_CRT,
> +	POWER_DOMAIN_PORT_OTHER,
>  	POWER_DOMAIN_VGA,
>  	POWER_DOMAIN_AUDIO,
>  	POWER_DOMAIN_INIT,
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index fa50f6e..7ef06fa 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3957,9 +3957,49 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
>  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
>  		if ((1 << (domain)) & (mask))
>  
> -static unsigned long get_pipe_power_domains(struct drm_device *dev,
> -					    enum pipe pipe, bool pfit_enabled)
> +enum intel_display_power_domain
> +intel_display_port_power_domain(struct intel_encoder *intel_encoder)
>  {
> +	struct drm_device *dev = intel_encoder->base.dev;
> +	struct intel_digital_port *intel_dig_port;
> +
> +	switch (intel_encoder->type) {
> +	case INTEL_OUTPUT_UNKNOWN:
> +		/* Only DDI platforms should ever use this output type */
> +		WARN_ON_ONCE(!HAS_DDI(dev));
> +	case INTEL_OUTPUT_DISPLAYPORT:
> +	case INTEL_OUTPUT_HDMI:
> +	case INTEL_OUTPUT_EDP:
> +		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
> +		switch (intel_dig_port->port) {
> +		case PORT_A:
> +			return POWER_DOMAIN_PORT_DDI_A_4_LANES;
> +		case PORT_B:
> +			return POWER_DOMAIN_PORT_DDI_B_4_LANES;
> +		case PORT_C:
> +			return POWER_DOMAIN_PORT_DDI_C_4_LANES;
> +		case PORT_D:
> +			return POWER_DOMAIN_PORT_DDI_D_4_LANES;
> +		default:
> +			WARN_ON_ONCE(1);
> +			return POWER_DOMAIN_PORT_OTHER;
> +		}
> +	case INTEL_OUTPUT_ANALOG:
> +		return POWER_DOMAIN_PORT_CRT;
> +	case INTEL_OUTPUT_DSI:
> +		return POWER_DOMAIN_PORT_DSI;
> +	default:
> +		return POWER_DOMAIN_PORT_OTHER;
> +	}
> +}
> +
> +static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
> +{
> +	struct drm_device *dev = crtc->dev;
> +	struct intel_encoder *intel_encoder;
> +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> +	enum pipe pipe = intel_crtc->pipe;
> +	bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
>  	unsigned long mask;
>  	enum transcoder transcoder;
>  
> @@ -3970,6 +4010,9 @@ static unsigned long get_pipe_power_domains(struct drm_device *dev,
>  	if (pfit_enabled)
>  		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
>  
> +	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
> +		mask |= BIT(intel_display_port_power_domain(intel_encoder));
> +
>  	return mask;
>  }
>  
> @@ -4003,9 +4046,7 @@ static void modeset_update_power_wells(struct drm_device *dev)
>  		if (!crtc->base.enabled)
>  			continue;
>  
> -		pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
> -						crtc->pipe,
> -						crtc->config.pch_pfit.enabled);
> +		pipe_domains[crtc->pipe] = get_crtc_power_domains(&crtc->base);
>  
>  		for_each_power_domain(domain, pipe_domains[crtc->pipe])
>  			intel_display_power_get(dev_priv, domain);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 6042797..e31eb1e 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -733,6 +733,8 @@ bool intel_crtc_active(struct drm_crtc *crtc);
>  void hsw_enable_ips(struct intel_crtc *crtc);
>  void hsw_disable_ips(struct intel_crtc *crtc);
>  void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
> +enum intel_display_power_domain
> +intel_display_port_power_domain(struct intel_encoder *intel_encoder);
>  int valleyview_get_vco(struct drm_i915_private *dev_priv);
>  void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>  				 struct intel_crtc_config *pipe_config);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index faaa4ec..9cb7ed6 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5412,6 +5412,15 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
>  #define HSW_ALWAYS_ON_POWER_DOMAINS (			\
>  	BIT(POWER_DOMAIN_PIPE_A) |			\
>  	BIT(POWER_DOMAIN_TRANSCODER_EDP) |		\
> +	BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) |		\
> +	BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) |		\
> +	BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |		\
> +	BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |		\
> +	BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |		\
> +	BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |		\
> +	BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |		\
> +	BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |		\
> +	BIT(POWER_DOMAIN_PORT_CRT) |			\
>  	BIT(POWER_DOMAIN_INIT))
>  #define HSW_DISPLAY_POWER_DOMAINS (				\
>  	(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |	\

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

I wonder if we want a way to parameterize the lane count instead, in
case we end up doing 1 lane for example in the future, or have some
other power domain that can provide multiple levels of power.

But I suppose we can deal with that if/when we come to it.

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 08/19] drm/i915: get port power domain in connector detect
  2014-02-19 12:39     ` Imre Deak
@ 2014-02-20 19:33       ` Jesse Barnes
  2014-02-24 11:56         ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:33 UTC (permalink / raw)
  To: imre.deak; +Cc: intel-gfx

On Wed, 19 Feb 2014 14:39:58 +0200
Imre Deak <imre.deak@intel.com> wrote:

> On Wed, 2014-02-19 at 14:35 +0200, Ville Syrjälä wrote:
> > On Tue, Feb 18, 2014 at 12:02:09AM +0200, Imre Deak wrote:
> > > The connector detect and get_mode handlers need to access the port
> > > specific HW blocks to read the EDID etc. Get/put the port power domains
> > > around these handlers.
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_crt.c | 42 ++++++++++++++++++++++++++++++++--------
> > >  drivers/gpu/drm/i915/intel_dp.c  | 16 ++++++++++++---
> > >  drivers/gpu/drm/i915/intel_dsi.c | 13 ++++++++++++-
> > 
> > And what about HDMI?
> 
> Good catch, I missed that one.

I wonder if we can catch bits like that using our display reg base
bits.  We could have a platform specific power check for each block to
do some basic sanity checking on whether the appropriate well was
enabled and squak if not.

I just know we'll miss this more than once, and I'm not sure if the
unclaimed reg stuff will save us on all platforms.

-- 
Jesse Barnes, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state
  2014-02-17 22:02 ` [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state Imre Deak
@ 2014-02-20 19:36   ` Jesse Barnes
  2014-02-24 12:53     ` Imre Deak
  2014-03-05 10:21   ` Daniel Vetter
  1 sibling, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:36 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:10 +0200
Imre Deak <imre.deak@intel.com> wrote:

> Since the encoder is tied to its port, we need to make sure the power
> domain for that port is on before reading out the encoder HW state.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_ddi.c     |  2 +-
>  drivers/gpu/drm/i915/intel_display.c | 23 ++++++++++++++++++-----
>  drivers/gpu/drm/i915/intel_drv.h     |  1 +
>  3 files changed, 20 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> index 2643d3b..f95bc3a 100644
> --- a/drivers/gpu/drm/i915/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/intel_ddi.c
> @@ -1110,7 +1110,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
>  	enum transcoder cpu_transcoder;
>  	uint32_t tmp;
>  
> -	if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
> +	if (!intel_encoder_get_hw_state(intel_encoder, &pipe))
>  		return false;
>  
>  	if (port == PORT_A)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 7ef06fa..ce1c00a 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -4519,7 +4519,7 @@ static void intel_connector_check_state(struct intel_connector *connector)
>  		WARN(!encoder->connectors_active,
>  		     "encoder->connectors_active not set\n");
>  
> -		encoder_enabled = encoder->get_hw_state(encoder, &pipe);
> +		encoder_enabled = intel_encoder_get_hw_state(encoder, &pipe);
>  		WARN(!encoder_enabled, "encoder not enabled\n");
>  		if (WARN_ON(!encoder->base.crtc))
>  			return;
> @@ -4561,7 +4561,7 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)
>  	enum pipe pipe = 0;
>  	struct intel_encoder *encoder = connector->encoder;
>  
> -	return encoder->get_hw_state(encoder, &pipe);
> +	return intel_encoder_get_hw_state(encoder, &pipe);
>  }
>  
>  static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> @@ -9464,6 +9464,19 @@ check_connector_state(struct drm_device *dev)
>  	}
>  }
>  
> +bool intel_encoder_get_hw_state(struct intel_encoder *intel_encoder,
> +				enum pipe *pipe)
> +{
> +	enum intel_display_power_domain power_domain;
> +	struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
> +
> +	power_domain = intel_display_port_power_domain(intel_encoder);
> +	if (!intel_display_power_enabled(dev_priv, power_domain))
> +		return false;
> +
> +	return intel_encoder->get_hw_state(intel_encoder, pipe);
> +}
> +
>  static void
>  check_encoder_state(struct drm_device *dev)
>  {
> @@ -9504,7 +9517,7 @@ check_encoder_state(struct drm_device *dev)
>  		     "encoder's computed active state doesn't match tracked active state "
>  		     "(expected %i, found %i)\n", active, encoder->connectors_active);
>  
> -		active = encoder->get_hw_state(encoder, &pipe);
> +		active = intel_encoder_get_hw_state(encoder, &pipe);
>  		WARN(active != encoder->connectors_active,
>  		     "encoder's hw state doesn't match sw tracking "
>  		     "(expected %i, found %i)\n",
> @@ -9571,7 +9584,7 @@ check_crtc_state(struct drm_device *dev)
>  			enum pipe pipe;
>  			if (encoder->base.crtc != &crtc->base)
>  				continue;
> -			if (encoder->get_hw_state(encoder, &pipe))
> +			if (intel_encoder_get_hw_state(encoder, &pipe))
>  				encoder->get_config(encoder, &pipe_config);
>  		}
>  
> @@ -11350,7 +11363,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>  			    base.head) {
>  		pipe = 0;
>  
> -		if (encoder->get_hw_state(encoder, &pipe)) {
> +		if (intel_encoder_get_hw_state(encoder, &pipe)) {
>  			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
>  			encoder->base.crtc = &crtc->base;
>  			encoder->get_config(encoder, &crtc->config);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index e31eb1e..afc01a4 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -738,6 +738,7 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder);
>  int valleyview_get_vco(struct drm_i915_private *dev_priv);
>  void intel_mode_from_pipe_config(struct drm_display_mode *mode,
>  				 struct intel_crtc_config *pipe_config);
> +bool intel_encoder_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
>  
>  /* intel_dp.c */
>  void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);

I think there are a few more places to switch over, e.g.
connector_check_state and connector_get_hw_state?  Maybe we should
rename the fn pointer field to include a __ in the front so the
compiler will catch them all and we'll know they're not to be called
directly.

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 10/19] drm/i915: check pipe power domain when reading its hw state
  2014-02-17 22:02 ` [PATCH 10/19] drm/i915: check pipe power domain when reading its " Imre Deak
@ 2014-02-20 19:37   ` Jesse Barnes
  2014-03-05 10:24     ` Daniel Vetter
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:37 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:11 +0200
Imre Deak <imre.deak@intel.com> wrote:

> We can read out the pipe HW state only if the required power domain is
> on. If not we consider the pipe to be off.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++++----
>  1 file changed, 15 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index ce1c00a..e3824f8 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -9535,6 +9535,18 @@ check_encoder_state(struct drm_device *dev)
>  	}
>  }
>  
> +static bool intel_display_get_pipe_config(struct intel_crtc *crtc,
> +					  struct intel_crtc_config *pipe_config)
> +{
> +	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> +
> +	if (!intel_display_power_enabled(dev_priv,
> +					 POWER_DOMAIN_PIPE(crtc->pipe)))
> +		return false;
> +
> +	return dev_priv->display.get_pipe_config(crtc, pipe_config);
> +}
> +
>  static void
>  check_crtc_state(struct drm_device *dev)
>  {
> @@ -9572,8 +9584,7 @@ check_crtc_state(struct drm_device *dev)
>  		     "crtc's computed enabled state doesn't match tracked enabled state "
>  		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
>  
> -		active = dev_priv->display.get_pipe_config(crtc,
> -							   &pipe_config);
> +		active = intel_display_get_pipe_config(crtc, &pipe_config);
>  
>  		/* hw state is inconsistent with the pipe A quirk */
>  		if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
> @@ -11328,8 +11339,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
>  			    base.head) {
>  		memset(&crtc->config, 0, sizeof(crtc->config));
>  
> -		crtc->active = dev_priv->display.get_pipe_config(crtc,
> -								 &crtc->config);
> +		crtc->active = intel_display_get_pipe_config(crtc,
> +							     &crtc->config);
>  
>  		crtc->base.enabled = crtc->active;
>  		crtc->primary_enabled = crtc->active;

Same comment about renaming .get_pipe_config applies here too, but I
think you got them all in this case, so that could be done on top.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions
  2014-02-20 19:17   ` Jesse Barnes
@ 2014-02-20 19:44     ` Chris Wilson
  0 siblings, 0 replies; 68+ messages in thread
From: Chris Wilson @ 2014-02-20 19:44 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Thu, Feb 20, 2014 at 11:17:31AM -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:03 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > These functions are used only by a single call site and are simple
> > enough to just fold them in.
> > 
> > No functional change.

There should be a much better reason (or any reason at all!) for removing
self-descriptive code.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 12/19] drm/i915: sanitize PUNIT register macro definitions
  2014-02-17 22:02 ` [PATCH 12/19] drm/i915: sanitize PUNIT register macro definitions Imre Deak
@ 2014-02-20 19:46   ` Jesse Barnes
  2014-02-24 13:12     ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:46 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:13 +0200
Imre Deak <imre.deak@intel.com> wrote:

> In the upcoming patches we'll need to access the rest of the fields in
> the punit power gating register, so prepare for that.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h     | 29 +++++++++++++++++++++++------
>  drivers/gpu/drm/i915/intel_uncore.c |  4 +++-
>  2 files changed, 26 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 2f564ce..5a700e9 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -377,14 +377,31 @@
>  #define   DSPFREQSTAT_MASK			(0x3 << DSPFREQSTAT_SHIFT)
>  #define   DSPFREQGUAR_SHIFT			14
>  #define   DSPFREQGUAR_MASK			(0x3 << DSPFREQGUAR_SHIFT)
> +
> +enum punit_power_well {
> +	PUNIT_POWER_WELL_RENDER			= 0,
> +	PUNIT_POWER_WELL_MEDIA			= 1,
> +	PUNIT_POWER_WELL_DISP2D			= 3,
> +	PUNIT_POWER_WELL_DPIO_CMN_BC		= 5,
> +	PUNIT_POWER_WELL_DPIO_TX_B_LANES_01	= 6,
> +	PUNIT_POWER_WELL_DPIO_TX_B_LANES_23	= 7,
> +	PUNIT_POWER_WELL_DPIO_TX_C_LANES_01	= 8,
> +	PUNIT_POWER_WELL_DPIO_TX_C_LANES_23	= 9,
> +	PUNIT_POWER_WELL_DPIO_RX0		= 10,
> +	PUNIT_POWER_WELL_DPIO_RX1		= 11,
> +	PUNIT_POWER_WELL_DPIO_RX2		= 12,
> +	PUNIT_POWER_WELL_DPIO_RX3		= 13,
> +
> +	PUNIT_POWER_WELL_NUM,
> +};
> +
>  #define PUNIT_REG_PWRGT_CTRL			0x60
>  #define PUNIT_REG_PWRGT_STATUS			0x61
> -#define	  PUNIT_CLK_GATE			1
> -#define	  PUNIT_PWR_RESET			2
> -#define	  PUNIT_PWR_GATE			3
> -#define	  RENDER_PWRGT				(PUNIT_PWR_GATE << 0)
> -#define	  MEDIA_PWRGT				(PUNIT_PWR_GATE << 2)
> -#define	  DISP2D_PWRGT				(PUNIT_PWR_GATE << 6)
> +#define   PUNIT_PWRGT_MASK(power_well)		(3 << ((power_well) * 2))
> +#define   PUNIT_PWRGT_PWR_ON(power_well)	(0 << ((power_well) * 2))
> +#define   PUNIT_PWRGT_CLK_GATE(power_well)	(1 << ((power_well) * 2))
> +#define   PUNIT_PWRGT_RESET(power_well)		(2 << ((power_well) * 2))
> +#define   PUNIT_PWRGT_PWR_GATE(power_well)	(3 << ((power_well) * 2))
>  
>  #define PUNIT_REG_GPU_LFM			0xd3
>  #define PUNIT_REG_GPU_FREQ_REQ			0xd4
> diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> index c628414..4aab7c2 100644
> --- a/drivers/gpu/drm/i915/intel_uncore.c
> +++ b/drivers/gpu/drm/i915/intel_uncore.c
> @@ -354,7 +354,9 @@ void intel_uncore_sanitize(struct drm_device *dev)
>  		mutex_lock(&dev_priv->rps.hw_lock);
>  		reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS);
>  
> -		if (reg_val & (RENDER_PWRGT | MEDIA_PWRGT | DISP2D_PWRGT))
> +		if (reg_val & (PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_RENDER) |
> +			       PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_MEDIA) |
> +			       PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_DISP2D)))
>  			vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, 0x0);
>  
>  		mutex_unlock(&dev_priv->rps.hw_lock);

I'd like to see a doc reference here, as I never remember which one has
these bits...  Also, are you sure about the RX bits?  The
PUNIT_HAS_0.8 doc says only subsystems 10-11 cover RX, maybe in a ganged
config?

Otherwise:
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 14/19] drm/i915: switch order of power domain init wrt. irq install
  2014-02-17 22:02 ` [PATCH 14/19] drm/i915: switch order of power domain init wrt. irq install Imre Deak
@ 2014-02-20 19:48   ` Jesse Barnes
  2014-02-24 13:23     ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:48 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:15 +0200
Imre Deak <imre.deak@intel.com> wrote:

> On VLV at least the display IRQ register access and functionality
> depends on its power well to be on, so move the power domain HW init
> before we install the IRQs.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 8177c17..f8f7a59 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1321,12 +1321,12 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  	if (ret)
>  		goto cleanup_vga_switcheroo;
>  
> +	intel_power_domains_init_hw(dev_priv);
> +
>  	ret = drm_irq_install(dev);
>  	if (ret)
>  		goto cleanup_gem_stolen;
>  
> -	intel_power_domains_init_hw(dev_priv);
> -
>  	/* Important: The output setup functions called by modeset_init need
>  	 * working irqs for e.g. gmbus and dp aux transfers. */
>  	intel_modeset_init(dev);

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

That said, this was always one part of the PM code that confused me and
caused some refcounts to get messed up last time I worked on it.

I think it would be better to not treat init specially, and let the
power wells get turned on and off through normal power well get/put
calls during init and resume.

It's a bit noisy, power wise, but ultimately it might make for clearer
code and one less special case.

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 15/19] drm/i915: use power domain api to check vga power state
  2014-02-17 22:02 ` [PATCH 15/19] drm/i915: use power domain api to check vga power state Imre Deak
@ 2014-02-20 19:51   ` Jesse Barnes
  2014-03-05 10:31     ` Daniel Vetter
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:51 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:16 +0200
Imre Deak <imre.deak@intel.com> wrote:

> This way we can reuse the check on other platforms too. Also factor out
> a version of the function that doesn't check if the power is on, we'll
> need to call this from within the power domain framework.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |  1 +
>  drivers/gpu/drm/i915/intel_display.c | 20 +++++++++++++-------
>  2 files changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 76bd03a..632f9d8 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2591,6 +2591,7 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
>  extern void intel_modeset_setup_hw_state(struct drm_device *dev,
>  					 bool force_restore);
>  extern void i915_redisable_vga(struct drm_device *dev);
> +extern void i915_redisable_vga_power_on(struct drm_device *dev);
>  extern bool intel_fbc_enabled(struct drm_device *dev);
>  extern void intel_disable_fbc(struct drm_device *dev);
>  extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index e3824f8..ea00878 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -11304,10 +11304,20 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
>  	 * the crtc fixup. */
>  }
>  
> +void i915_redisable_vga_power_on(struct drm_device *dev)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	u32 vga_reg = i915_vgacntrl_reg(dev);
> +
> +	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
> +		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
> +		i915_disable_vga(dev);
> +	}
> +}
> +
>  void i915_redisable_vga(struct drm_device *dev)
>  {
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	u32 vga_reg = i915_vgacntrl_reg(dev);
>  
>  	/* This function can be called both from intel_modeset_setup_hw_state or
>  	 * at a very early point in our resume sequence, where the power well
> @@ -11316,14 +11326,10 @@ void i915_redisable_vga(struct drm_device *dev)
>  	 * level, just check if the power well is enabled instead of trying to
>  	 * follow the "don't touch the power well if we don't need it" policy
>  	 * the rest of the driver uses. */
> -	if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) &&
> -	    (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0)
> +	if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_VGA))
>  		return;
>  
> -	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
> -		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
> -		i915_disable_vga(dev);
> -	}
> +	i915_redisable_vga_power_on(dev);
>  }
>  
>  static void intel_modeset_readout_hw_state(struct drm_device *dev)

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 18/19] drm/i915: move hsw power domain comment to its right place
  2014-02-17 22:02 ` [PATCH 18/19] drm/i915: move hsw power domain comment to its right place Imre Deak
@ 2014-02-20 19:53   ` Jesse Barnes
  2014-03-05 10:34     ` Daniel Vetter
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:53 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:19 +0200
Imre Deak <imre.deak@intel.com> wrote:

> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/intel_pm.c | 12 ++++++------
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 21ccf89..68f58e5 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5213,6 +5213,12 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
>  	return is_enabled;
>  }
>  
> +/*
> + * 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
> + * to be enabled, and it will only be disabled if none of the registers is
> + * requesting it to be enabled.
> + */
>  static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
>  {
>  	struct drm_device *dev = dev_priv->dev;
> @@ -5556,12 +5562,6 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
>  	mutex_unlock(&power_domains->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
> - * to be enabled, and it will only be disabled if none of the registers is
> - * requesting it to be enabled.
> - */
>  void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
>  {
>  	/* For now, we need the power well to be always enabled. */

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 17/19] drm/i915: vlv: factor out valleyview_display_irq_install
  2014-02-17 22:02 ` [PATCH 17/19] drm/i915: vlv: factor out valleyview_display_irq_install Imre Deak
@ 2014-02-20 19:56   ` Jesse Barnes
  2014-02-24 13:34     ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:56 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, 18 Feb 2014 00:02:18 +0200
Imre Deak <imre.deak@intel.com> wrote:

> We'll need to disable/re-enable the display-side IRQs when turning
> off/on the VLV display power well. Factor out the helper functions
> for this. For now keep the display IRQs enabled by default, so the
> functionality doesn't change. This will be changed to enable/disable
> the IRQs on-demand when adding support for VLV power wells in an
> upcoming patch.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_dma.c |   1 +
>  drivers/gpu/drm/i915/i915_drv.h |   5 ++
>  drivers/gpu/drm/i915/i915_irq.c | 122 ++++++++++++++++++++++++++++++++--------
>  3 files changed, 103 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index f8f7a59..dca4dc3 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1668,6 +1668,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>  		goto out_mtrrfree;
>  	}
>  
> +	dev_priv->display_irqs_enabled = true;
>  	intel_irq_init(dev);
>  	intel_uncore_sanitize(dev);
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 632f9d8..227c349 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1454,6 +1454,8 @@ typedef struct drm_i915_private {
>  	/* protects the irq masks */
>  	spinlock_t irq_lock;
>  
> +	bool display_irqs_enabled;
> +
>  	/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
>  	struct pm_qos_request pm_qos;
>  
> @@ -2052,6 +2054,9 @@ void
>  i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
>  		      u32 status_mask);
>  
> +void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
> +void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
> +
>  /* i915_gem.c */
>  int i915_gem_init_ioctl(struct drm_device *dev, void *data,
>  			struct drm_file *file_priv);
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 75dd0a8..6078d06 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -3016,41 +3016,109 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
>  	return 0;
>  }
>  
> +static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv)
> +{
> +	unsigned long irqflags;
> +	u32 pipestat_mask;
> +	u32 iir_mask;
> +
> +	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
> +			PIPE_FIFO_UNDERRUN_STATUS;
> +	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
> +	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
> +	POSTING_READ(PIPESTAT(PIPE_A));
> +
> +	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
> +			PIPE_CRC_DONE_INTERRUPT_STATUS;
> +
> +	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
> +	i915_enable_pipestat(dev_priv, PIPE_A, pipestat_mask |
> +					       PIPE_GMBUS_INTERRUPT_STATUS);
> +	i915_enable_pipestat(dev_priv, PIPE_B, pipestat_mask);
> +	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
> +
> +	iir_mask = I915_DISPLAY_PORT_INTERRUPT |
> +		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> +		   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
> +	dev_priv->irq_mask &= ~iir_mask;
> +
> +	I915_WRITE(VLV_IIR, iir_mask);
> +	I915_WRITE(VLV_IIR, iir_mask);
> +	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
> +	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
> +	POSTING_READ(VLV_IER);
> +}
> +
> +static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
> +{
> +	unsigned long irqflags;
> +	u32 pipestat_mask;
> +	u32 iir_mask;
> +
> +	iir_mask = I915_DISPLAY_PORT_INTERRUPT |
> +		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> +		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
> +	dev_priv->irq_mask |= iir_mask;
> +	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
> +	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
> +	I915_WRITE(VLV_IIR, iir_mask);
> +	I915_WRITE(VLV_IIR, iir_mask);
> +	POSTING_READ(VLV_IIR);
> +
> +	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
> +			PIPE_CRC_DONE_INTERRUPT_STATUS;
> +
> +	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
> +	i915_disable_pipestat(dev_priv, PIPE_A, pipestat_mask |
> +					        PIPE_GMBUS_INTERRUPT_STATUS);
> +	i915_disable_pipestat(dev_priv, PIPE_B, pipestat_mask);
> +	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
> +
> +	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
> +			PIPE_FIFO_UNDERRUN_STATUS;
> +	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
> +	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
> +	POSTING_READ(PIPESTAT(PIPE_A));
> +}
> +
> +void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
> +{
> +	if (dev_priv->display_irqs_enabled)
> +		return;
> +
> +	dev_priv->display_irqs_enabled = true;
> +
> +	if (dev_priv->dev->irq_enabled)
> +		valleyview_display_irqs_install(dev_priv);
> +}
> +
> +void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
> +{
> +	if (!dev_priv->display_irqs_enabled)
> +		return;
> +
> +	dev_priv->display_irqs_enabled = false;
> +
> +	if (dev_priv->dev->irq_enabled)
> +		valleyview_display_irqs_uninstall(dev_priv);
> +}
> +
>  static int valleyview_irq_postinstall(struct drm_device *dev)
>  {
>  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
> -	u32 enable_mask;
> -	u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
> -		PIPE_CRC_DONE_INTERRUPT_STATUS;
> -	unsigned long irqflags;
>  
> -	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
> -	enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> -		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
> -
> -	/*
> -	 *Leave vblank interrupts masked initially.  enable/disable will
> -	 * toggle them based on usage.
> -	 */
> -	dev_priv->irq_mask = ~enable_mask;
> +	dev_priv->irq_mask = ~0;
>  
>  	I915_WRITE(PORT_HOTPLUG_EN, 0);
>  	POSTING_READ(PORT_HOTPLUG_EN);
>  
>  	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
> -	I915_WRITE(VLV_IER, enable_mask);
> +	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
>  	I915_WRITE(VLV_IIR, 0xffffffff);
> -	I915_WRITE(PIPESTAT(0), 0xffff);
> -	I915_WRITE(PIPESTAT(1), 0xffff);
>  	POSTING_READ(VLV_IER);
>  
> -	/* Interrupt setup is already guaranteed to be single-threaded, this is
> -	 * just to make the assert_spin_locked check happy. */
> -	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
> -	i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable);
> -	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
> -	i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable);
> -	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
> +	if (dev_priv->display_irqs_enabled)
> +		valleyview_display_irqs_install(dev_priv);
>  
>  	I915_WRITE(VLV_IIR, 0xffffffff);
>  	I915_WRITE(VLV_IIR, 0xffffffff);
> @@ -3193,8 +3261,12 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
>  	I915_WRITE(HWSTAM, 0xffffffff);
>  	I915_WRITE(PORT_HOTPLUG_EN, 0);
>  	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
> -	for_each_pipe(pipe)
> -		I915_WRITE(PIPESTAT(pipe), 0xffff);
> +
> +	if (dev_priv->display_irqs_enabled)
> +		valleyview_display_irqs_uninstall(dev_priv);
> +
> +	dev_priv->irq_mask = 0;
> +
>  	I915_WRITE(VLV_IIR, 0xffffffff);
>  	I915_WRITE(VLV_IMR, 0xffffffff);
>  	I915_WRITE(VLV_IER, 0x0);

IRQ enable state and reg state may be another good thing to cross
check.  And on disable, it might be a good thing to just write all of
the pipestat irq status bits to avoid stuck interrupts (I think the
order is ok though).  But you've probably tested it already so I assume
it works ok.

Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

-- 
Jesse Barnes, Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 19/19] drm/i915: power domains: add vlv power wells
  2014-02-19 12:29   ` Ville Syrjälä
@ 2014-02-20 19:58     ` Jesse Barnes
  2014-02-26 18:02       ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Jesse Barnes @ 2014-02-20 19:58 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, 19 Feb 2014 14:29:44 +0200
Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:

> On Tue, Feb 18, 2014 at 12:02:20AM +0200, Imre Deak wrote:
> > Based on an early draft from Jesse.
> > 
> > Add support for powering on/off the dynamic power wells on VLV by
> > registering its display and dpio dynamic power wells with the power
> > domain framework.
> > 
> > For now power on all PHY TX lanes regardless of the actual lane
> > configuration. Later this can be optimized when the PHY side setup
> > enables only the required lanes. Atm, it enables all lanes in all
> > cases.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_dma.c      |   1 -
> >  drivers/gpu/drm/i915/i915_drv.h      |   2 +-
> >  drivers/gpu/drm/i915/intel_display.c |   1 +
> >  drivers/gpu/drm/i915/intel_pm.c      | 228 +++++++++++++++++++++++++++++++++++
> >  4 files changed, 230 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > index dca4dc3..f8f7a59 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -1668,7 +1668,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> >  		goto out_mtrrfree;
> >  	}
> >  
> > -	dev_priv->display_irqs_enabled = true;
> >  	intel_irq_init(dev);
> >  	intel_uncore_sanitize(dev);
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 227c349..804334e 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1053,7 +1053,7 @@ struct i915_power_well {
> >  	/* power well enable/disable usage count */
> >  	int count;
> >  	unsigned long domains;
> > -	void *data;
> > +	unsigned long data;
> >  	const struct i915_power_well_ops *ops;
> >  };
> >  
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index ea00878..d6661c4 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -4224,6 +4224,7 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
> >  
> >  	if (req_cdclk != cur_cdclk)
> >  		valleyview_set_cdclk(dev, req_cdclk);
> > +	modeset_update_power_wells(dev);
> >  }
> >  
> >  static void valleyview_crtc_enable(struct drm_crtc *crtc)
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 68f58e5..e4416a7 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -5344,6 +5344,133 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> >  	hsw_enable_package_c8(dev_priv);
> >  }
> >  
> > +static void vlv_set_power_well(struct drm_i915_private *dev_priv,
> > +			       struct i915_power_well *power_well, bool enable)
> > +{
> > +	enum punit_power_well power_well_id = power_well->data;
> > +	u32 mask;
> > +	u32 state;
> > +	u32 ctrl;
> > +
> > +	mask = PUNIT_PWRGT_MASK(power_well_id);
> > +	state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
> > +			 PUNIT_PWRGT_PWR_GATE(power_well_id);
> > +
> > +	mutex_lock(&dev_priv->rps.hw_lock);
> > +
> > +#define COND \
> > +	((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
> > +
> > +	if (COND)
> > +		goto out;
> > +
> > +	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
> > +	ctrl &= ~mask;
> > +	ctrl |= state;
> > +	vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
> > +
> > +	if (wait_for(COND, 100))
> > +		DRM_ERROR("timout setting power well state %08x (%08x)\n",
> > +			  state,
> > +			  vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
> 
> #undef COND somewhere to avoid suprises further down in the code?
> 
> > +
> > +out:
> > +	mutex_unlock(&dev_priv->rps.hw_lock);
> > +}
> > +
> <snip>
> 

I'd like to see the code for re-enabling the display state land
eventually too, so we can get savings when userspace uses DPMS instead
of NULL mode sets for things.  But to do that nicely requires some more
work in the mode set code to pull out more PLL bits (also needed for
atomic mode setting).

-- 
Jesse Barnes, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 05/19] drm/i915: power domains: add power well ops
  2014-02-20 19:26   ` Jesse Barnes
@ 2014-02-24 11:42     ` Imre Deak
  0 siblings, 0 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-24 11:42 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 9467 bytes --]

On Thu, 2014-02-20 at 11:26 -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:06 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > Split the 'set' power well handler into an 'enable', 'disable' and
> > 'sync_hw' handler. This maps more conveniently to higher level
> > operations, for example it allows us to push the hsw package c8 handling
> > into the corresponding hsw/bdw enable/disable handlers and the hsw BIOS
> > hand-over setting into the hsw/bdw sync_hw handler.
> > 
> > No functional change.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h | 35 +++++++++++++++++---
> >  drivers/gpu/drm/i915/intel_pm.c | 73 +++++++++++++++++++++++++++--------------
> >  2 files changed, 80 insertions(+), 28 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index de0c0e0..8c8635e 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1006,6 +1006,36 @@ struct intel_ilk_power_mgmt {
> >  	struct drm_i915_gem_object *renderctx;
> >  };
> >  
> > +struct drm_i915_private;
> > +struct i915_power_well;
> > +
> > +struct i915_power_well_ops {
> > +	/*
> > +	 * Synchronize the well's hw state to match the current sw state, for
> > +	 * example enable/disable it based on the current refcount. Called
> > +	 * during driver init and resume time, possibly after first calling
> > +	 * the enable/disable handlers.
> > +	 */
> > +	void (*sync_hw)(struct drm_i915_private *dev_priv,
> > +		        struct i915_power_well *power_well);
> > +	/*
> > +	 * Enable the well and resources that depend on it (for example
> > +	 * interrupts located on the well). Called after the 0->1 refcount
> > +	 * transition.
> > +	 */
> > +	void (*enable)(struct drm_i915_private *dev_priv,
> > +		       struct i915_power_well *power_well);
> > +	/*
> > +	 * Disable the well and resources that depend on it. Called after
> > +	 * the 1->0 refcount transition.
> > +	 */
> > +	void (*disable)(struct drm_i915_private *dev_priv,
> > +		        struct i915_power_well *power_well);
> > +	/* Returns the hw enabled state. */
> > +	bool (*is_enabled)(struct drm_i915_private *dev_priv,
> > +			   struct i915_power_well *power_well);
> > +};
> > +
> >  /* Power well structure for haswell */
> >  struct i915_power_well {
> >  	const char *name;
> > @@ -1014,10 +1044,7 @@ struct i915_power_well {
> >  	int count;
> >  	unsigned long domains;
> >  	void *data;
> > -	void (*set)(struct drm_i915_private *dev_priv, struct i915_power_well *power_well,
> > -		    bool enable);
> > -	bool (*is_enabled)(struct drm_i915_private *dev_priv,
> > -			   struct i915_power_well *power_well);
> > +	const struct i915_power_well_ops *ops;
> >  };
> >  
> >  struct i915_power_domains {
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 9a608f1..7866426 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -5203,7 +5203,7 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
> >  		if (power_well->always_on)
> >  			continue;
> >  
> > -		if (!power_well->is_enabled(dev_priv, power_well)) {
> > +		if (!power_well->ops->is_enabled(dev_priv, power_well)) {
> >  			is_enabled = false;
> >  			break;
> >  		}
> > @@ -5305,6 +5305,33 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
> >  	}
> >  }
> >  
> > +static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv,
> > +			           struct i915_power_well *power_well)
> > +{
> > +	hsw_set_power_well(dev_priv, power_well, power_well->count > 0);
> > +
> > +	/*
> > +	 * We're taking over the BIOS, so clear any requests made by it since
> > +	 * the driver is in charge now.
> > +	 */
> > +	if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
> > +		I915_WRITE(HSW_PWR_WELL_BIOS, 0);
> > +}
> > +
> > +static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
> > +				  struct i915_power_well *power_well)
> > +{
> > +	hsw_disable_package_c8(dev_priv);
> > +	hsw_set_power_well(dev_priv, power_well, true);
> > +}
> > +
> > +static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> > +				   struct i915_power_well *power_well)
> > +{
> > +	hsw_set_power_well(dev_priv, power_well, false);
> > +	hsw_enable_package_c8(dev_priv);
> > +}
> > +
> >  void intel_display_power_get(struct drm_i915_private *dev_priv,
> >  			     enum intel_display_power_domain domain)
> >  {
> > @@ -5317,10 +5344,8 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
> >  	mutex_lock(&power_domains->lock);
> >  
> >  	for_each_power_well(i, power_well, BIT(domain), power_domains)
> > -		if (!power_well->count++ && power_well->set) {
> > -			hsw_disable_package_c8(dev_priv);
> > -			power_well->set(dev_priv, power_well, true);
> > -		}
> > +		if (!power_well->count++ && power_well->ops->enable)
> > +			power_well->ops->enable(dev_priv, power_well);
> >  
> >  	power_domains->domain_use_count[domain]++;
> >  
> > @@ -5344,11 +5369,9 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
> >  	for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> >  		WARN_ON(!power_well->count);
> >  
> > -		if (!--power_well->count && power_well->set &&
> > -				i915.disable_power_well) {
> > -			power_well->set(dev_priv, power_well, false);
> > -			hsw_enable_package_c8(dev_priv);
> > -		}
> > +		if (!--power_well->count && power_well->ops->disable &&
> > +		    i915.disable_power_well)
> > +			power_well->ops->disable(dev_priv, power_well);
> >  	}
> >  
> >  	mutex_unlock(&power_domains->lock);
> > @@ -5401,25 +5424,35 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
> >  	(POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |	\
> >  	BIT(POWER_DOMAIN_INIT))
> >  
> > +static const struct i915_power_well_ops i9xx_always_on_power_well_ops = { };
> > +
> >  static struct i915_power_well i9xx_always_on_power_well[] = {
> >  	{
> >  		.name = "always-on",
> >  		.always_on = 1,
> >  		.domains = POWER_DOMAIN_MASK,
> > +		.ops = &i9xx_always_on_power_well_ops,
> >  	},
> >  };
> >  
> > +static const struct i915_power_well_ops hsw_power_well_ops = {
> > +	.sync_hw = hsw_power_well_sync_hw,
> > +	.enable = hsw_power_well_enable,
> > +	.disable = hsw_power_well_disable,
> > +	.is_enabled = hsw_power_well_enabled,
> > +};
> > +
> >  static struct i915_power_well hsw_power_wells[] = {
> >  	{
> >  		.name = "always-on",
> >  		.always_on = 1,
> >  		.domains = HSW_ALWAYS_ON_POWER_DOMAINS,
> > +		.ops = &i9xx_always_on_power_well_ops,
> >  	},
> >  	{
> >  		.name = "display",
> >  		.domains = HSW_DISPLAY_POWER_DOMAINS,
> > -		.is_enabled = hsw_power_well_enabled,
> > -		.set = hsw_set_power_well,
> > +		.ops = &hsw_power_well_ops,
> >  	},
> >  };
> >  
> > @@ -5428,12 +5461,12 @@ static struct i915_power_well bdw_power_wells[] = {
> >  		.name = "always-on",
> >  		.always_on = 1,
> >  		.domains = BDW_ALWAYS_ON_POWER_DOMAINS,
> > +		.ops = &i9xx_always_on_power_well_ops,
> >  	},
> >  	{
> >  		.name = "display",
> >  		.domains = BDW_DISPLAY_POWER_DOMAINS,
> > -		.is_enabled = hsw_power_well_enabled,
> > -		.set = hsw_set_power_well,
> > +		.ops = &hsw_power_well_ops,
> >  	},
> >  };
> >  
> > @@ -5478,8 +5511,8 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
> >  
> >  	mutex_lock(&power_domains->lock);
> >  	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> > -		if (power_well->set)
> > -			power_well->set(dev_priv, power_well, power_well->count > 0);
> > +		if (power_well->ops->sync_hw)
> > +			power_well->ops->sync_hw(dev_priv, power_well);
> >  	}
> >  	mutex_unlock(&power_domains->lock);
> >  }
> > @@ -5495,14 +5528,6 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
> >  	/* For now, we need the power well to be always enabled. */
> >  	intel_display_set_init_power(dev_priv, true);
> >  	intel_power_domains_resume(dev_priv);
> > -
> > -	if (!(IS_HASWELL(dev_priv->dev) || IS_BROADWELL(dev_priv->dev)))
> > -		return;
> > -
> > -	/* We're taking over the BIOS, so clear any requests made by it since
> > -	 * the driver is in charge now. */
> > -	if (I915_READ(HSW_PWR_WELL_BIOS) & HSW_PWR_WELL_ENABLE_REQUEST)
> > -		I915_WRITE(HSW_PWR_WELL_BIOS, 0);
> >  }
> >  
> >  /* Disables PC8 so we can use the GMBUS and DP AUX interrupts. */
> 
> Looks good.  Only nitpick might be to have no-op ops for the 9xx case
> and get rid of the checks for whether the ops function exists.  Going
> forward that might force us to think about things a bit at least.  But
> that's really just a style issue, the rest looks like a good change and
> pulls some of the HSW bits out of the generic routines.

Yea, I was going back and forth between allowing a NULL handler or not,
but I guess with less special casing in the generic path, it's easier to
read the code which is a big plus. And because we have to enable/disable
runtime PM even for always-on wells we'll have to anyway add a proper
handlers eventually. So I'll update this adding the empty stubs for now.

--Imre

> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 07/19] drm/i915: add port power domains
  2014-02-20 19:31   ` Jesse Barnes
@ 2014-02-24 11:52     ` Imre Deak
  0 siblings, 0 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-24 11:52 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 8865 bytes --]

On Thu, 2014-02-20 at 11:31 -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:08 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > Parts that poke port specific HW blocks like the encoder HW state
> > readout or connector hotplug detect code need a way to check whether
> > required power domains are on or enable/disable these. For this purpose
> > add a set of power domains that refer to the port HW blocks. Get the
> > proper port power domains during modeset.
> > 
> > For now when requesting the power domain for a DDI port get it for a 4
> > lane configuration. This can be optimized later to request only the 2
> > lane power domain, when proper support is added on the VLV PHY side for
> > this. Atm, the PHY setup code assumes a 4 lane config in all cases.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c  | 22 ++++++++++++++++
> >  drivers/gpu/drm/i915/i915_drv.h      | 11 ++++++++
> >  drivers/gpu/drm/i915/intel_display.c | 51 ++++++++++++++++++++++++++++++++----
> >  drivers/gpu/drm/i915/intel_drv.h     |  2 ++
> >  drivers/gpu/drm/i915/intel_pm.c      |  9 +++++++
> >  5 files changed, 90 insertions(+), 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > index d90a707..14c7730 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -2030,6 +2030,28 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
> >  		return "TRANSCODER_C";
> >  	case POWER_DOMAIN_TRANSCODER_EDP:
> >  		return "TRANSCODER_EDP";
> > +	case POWER_DOMAIN_PORT_DDI_A_2_LANES:
> > +		return "PORT_DDI_A_2_LANES";
> > +	case POWER_DOMAIN_PORT_DDI_A_4_LANES:
> > +		return "PORT_DDI_A_4_LANES";
> > +	case POWER_DOMAIN_PORT_DDI_B_2_LANES:
> > +		return "PORT_DDI_B_2_LANES";
> > +	case POWER_DOMAIN_PORT_DDI_B_4_LANES:
> > +		return "PORT_DDI_B_4_LANES";
> > +	case POWER_DOMAIN_PORT_DDI_C_2_LANES:
> > +		return "PORT_DDI_C_2_LANES";
> > +	case POWER_DOMAIN_PORT_DDI_C_4_LANES:
> > +		return "PORT_DDI_C_4_LANES";
> > +	case POWER_DOMAIN_PORT_DDI_D_2_LANES:
> > +		return "PORT_DDI_D_2_LANES";
> > +	case POWER_DOMAIN_PORT_DDI_D_4_LANES:
> > +		return "PORT_DDI_D_4_LANES";
> > +	case POWER_DOMAIN_PORT_DSI:
> > +		return "PORT_DSI";
> > +	case POWER_DOMAIN_PORT_CRT:
> > +		return "PORT_CRT";
> > +	case POWER_DOMAIN_PORT_OTHER:
> > +		return "PORT_OTHER";
> >  	case POWER_DOMAIN_VGA:
> >  		return "VGA";
> >  	case POWER_DOMAIN_AUDIO:
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index eaa9210..76bd03a 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -114,6 +114,17 @@ enum intel_display_power_domain {
> >  	POWER_DOMAIN_TRANSCODER_B,
> >  	POWER_DOMAIN_TRANSCODER_C,
> >  	POWER_DOMAIN_TRANSCODER_EDP,
> > +	POWER_DOMAIN_PORT_DDI_A_2_LANES,
> > +	POWER_DOMAIN_PORT_DDI_A_4_LANES,
> > +	POWER_DOMAIN_PORT_DDI_B_2_LANES,
> > +	POWER_DOMAIN_PORT_DDI_B_4_LANES,
> > +	POWER_DOMAIN_PORT_DDI_C_2_LANES,
> > +	POWER_DOMAIN_PORT_DDI_C_4_LANES,
> > +	POWER_DOMAIN_PORT_DDI_D_2_LANES,
> > +	POWER_DOMAIN_PORT_DDI_D_4_LANES,
> > +	POWER_DOMAIN_PORT_DSI,
> > +	POWER_DOMAIN_PORT_CRT,
> > +	POWER_DOMAIN_PORT_OTHER,
> >  	POWER_DOMAIN_VGA,
> >  	POWER_DOMAIN_AUDIO,
> >  	POWER_DOMAIN_INIT,
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index fa50f6e..7ef06fa 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -3957,9 +3957,49 @@ static void i9xx_pfit_enable(struct intel_crtc *crtc)
> >  	for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++)	\
> >  		if ((1 << (domain)) & (mask))
> >  
> > -static unsigned long get_pipe_power_domains(struct drm_device *dev,
> > -					    enum pipe pipe, bool pfit_enabled)
> > +enum intel_display_power_domain
> > +intel_display_port_power_domain(struct intel_encoder *intel_encoder)
> >  {
> > +	struct drm_device *dev = intel_encoder->base.dev;
> > +	struct intel_digital_port *intel_dig_port;
> > +
> > +	switch (intel_encoder->type) {
> > +	case INTEL_OUTPUT_UNKNOWN:
> > +		/* Only DDI platforms should ever use this output type */
> > +		WARN_ON_ONCE(!HAS_DDI(dev));
> > +	case INTEL_OUTPUT_DISPLAYPORT:
> > +	case INTEL_OUTPUT_HDMI:
> > +	case INTEL_OUTPUT_EDP:
> > +		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
> > +		switch (intel_dig_port->port) {
> > +		case PORT_A:
> > +			return POWER_DOMAIN_PORT_DDI_A_4_LANES;
> > +		case PORT_B:
> > +			return POWER_DOMAIN_PORT_DDI_B_4_LANES;
> > +		case PORT_C:
> > +			return POWER_DOMAIN_PORT_DDI_C_4_LANES;
> > +		case PORT_D:
> > +			return POWER_DOMAIN_PORT_DDI_D_4_LANES;
> > +		default:
> > +			WARN_ON_ONCE(1);
> > +			return POWER_DOMAIN_PORT_OTHER;
> > +		}
> > +	case INTEL_OUTPUT_ANALOG:
> > +		return POWER_DOMAIN_PORT_CRT;
> > +	case INTEL_OUTPUT_DSI:
> > +		return POWER_DOMAIN_PORT_DSI;
> > +	default:
> > +		return POWER_DOMAIN_PORT_OTHER;
> > +	}
> > +}
> > +
> > +static unsigned long get_crtc_power_domains(struct drm_crtc *crtc)
> > +{
> > +	struct drm_device *dev = crtc->dev;
> > +	struct intel_encoder *intel_encoder;
> > +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
> > +	enum pipe pipe = intel_crtc->pipe;
> > +	bool pfit_enabled = intel_crtc->config.pch_pfit.enabled;
> >  	unsigned long mask;
> >  	enum transcoder transcoder;
> >  
> > @@ -3970,6 +4010,9 @@ static unsigned long get_pipe_power_domains(struct drm_device *dev,
> >  	if (pfit_enabled)
> >  		mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe));
> >  
> > +	for_each_encoder_on_crtc(dev, crtc, intel_encoder)
> > +		mask |= BIT(intel_display_port_power_domain(intel_encoder));
> > +
> >  	return mask;
> >  }
> >  
> > @@ -4003,9 +4046,7 @@ static void modeset_update_power_wells(struct drm_device *dev)
> >  		if (!crtc->base.enabled)
> >  			continue;
> >  
> > -		pipe_domains[crtc->pipe] = get_pipe_power_domains(dev,
> > -						crtc->pipe,
> > -						crtc->config.pch_pfit.enabled);
> > +		pipe_domains[crtc->pipe] = get_crtc_power_domains(&crtc->base);
> >  
> >  		for_each_power_domain(domain, pipe_domains[crtc->pipe])
> >  			intel_display_power_get(dev_priv, domain);
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 6042797..e31eb1e 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -733,6 +733,8 @@ bool intel_crtc_active(struct drm_crtc *crtc);
> >  void hsw_enable_ips(struct intel_crtc *crtc);
> >  void hsw_disable_ips(struct intel_crtc *crtc);
> >  void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
> > +enum intel_display_power_domain
> > +intel_display_port_power_domain(struct intel_encoder *intel_encoder);
> >  int valleyview_get_vco(struct drm_i915_private *dev_priv);
> >  void intel_mode_from_pipe_config(struct drm_display_mode *mode,
> >  				 struct intel_crtc_config *pipe_config);
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index faaa4ec..9cb7ed6 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -5412,6 +5412,15 @@ EXPORT_SYMBOL_GPL(i915_release_power_well);
> >  #define HSW_ALWAYS_ON_POWER_DOMAINS (			\
> >  	BIT(POWER_DOMAIN_PIPE_A) |			\
> >  	BIT(POWER_DOMAIN_TRANSCODER_EDP) |		\
> > +	BIT(POWER_DOMAIN_PORT_DDI_A_2_LANES) |		\
> > +	BIT(POWER_DOMAIN_PORT_DDI_A_4_LANES) |		\
> > +	BIT(POWER_DOMAIN_PORT_DDI_B_2_LANES) |		\
> > +	BIT(POWER_DOMAIN_PORT_DDI_B_4_LANES) |		\
> > +	BIT(POWER_DOMAIN_PORT_DDI_C_2_LANES) |		\
> > +	BIT(POWER_DOMAIN_PORT_DDI_C_4_LANES) |		\
> > +	BIT(POWER_DOMAIN_PORT_DDI_D_2_LANES) |		\
> > +	BIT(POWER_DOMAIN_PORT_DDI_D_4_LANES) |		\
> > +	BIT(POWER_DOMAIN_PORT_CRT) |			\
> >  	BIT(POWER_DOMAIN_INIT))
> >  #define HSW_DISPLAY_POWER_DOMAINS (				\
> >  	(POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |	\
> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 
> I wonder if we want a way to parameterize the lane count instead, in
> case we end up doing 1 lane for example in the future, or have some
> other power domain that can provide multiple levels of power.

On the requesting side I added a helper that maps an encoder to its
power domain (except for the lane count for now), so that kind of does
what you say. As for the actual macros, I guess we could add ones taking
parameters when - as you point out - the possible configurations grow
and the above definitions become too messy.

--Imre

> But I suppose we can deal with that if/when we come to it.

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 08/19] drm/i915: get port power domain in connector detect
  2014-02-20 19:33       ` Jesse Barnes
@ 2014-02-24 11:56         ` Imre Deak
  2014-03-05 10:15           ` Daniel Vetter
  0 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-24 11:56 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 1393 bytes --]

On Thu, 2014-02-20 at 11:33 -0800, Jesse Barnes wrote:
> On Wed, 19 Feb 2014 14:39:58 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > On Wed, 2014-02-19 at 14:35 +0200, Ville Syrjälä wrote:
> > > On Tue, Feb 18, 2014 at 12:02:09AM +0200, Imre Deak wrote:
> > > > The connector detect and get_mode handlers need to access the port
> > > > specific HW blocks to read the EDID etc. Get/put the port power domains
> > > > around these handlers.
> > > > 
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_crt.c | 42 ++++++++++++++++++++++++++++++++--------
> > > >  drivers/gpu/drm/i915/intel_dp.c  | 16 ++++++++++++---
> > > >  drivers/gpu/drm/i915/intel_dsi.c | 13 ++++++++++++-
> > > 
> > > And what about HDMI?
> > 
> > Good catch, I missed that one.
> 
> I wonder if we can catch bits like that using our display reg base
> bits.  We could have a platform specific power check for each block to
> do some basic sanity checking on whether the appropriate well was
> enabled and squak if not.
> 
> I just know we'll miss this more than once, and I'm not sure if the
> unclaimed reg stuff will save us on all platforms.

Yea, good idea. The register->power well mapping could be part of the
platform specific power well struct and we could assert on the SW state
of the well being 'enabled'.

--Imre


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state
  2014-02-20 19:36   ` Jesse Barnes
@ 2014-02-24 12:53     ` Imre Deak
  0 siblings, 0 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-24 12:53 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 6026 bytes --]

On Thu, 2014-02-20 at 11:36 -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:10 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > Since the encoder is tied to its port, we need to make sure the power
> > domain for that port is on before reading out the encoder HW state.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_ddi.c     |  2 +-
> >  drivers/gpu/drm/i915/intel_display.c | 23 ++++++++++++++++++-----
> >  drivers/gpu/drm/i915/intel_drv.h     |  1 +
> >  3 files changed, 20 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
> > index 2643d3b..f95bc3a 100644
> > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > @@ -1110,7 +1110,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)
> >  	enum transcoder cpu_transcoder;
> >  	uint32_t tmp;
> >  
> > -	if (!intel_encoder->get_hw_state(intel_encoder, &pipe))
> > +	if (!intel_encoder_get_hw_state(intel_encoder, &pipe))
> >  		return false;
> >  
> >  	if (port == PORT_A)
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 7ef06fa..ce1c00a 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -4519,7 +4519,7 @@ static void intel_connector_check_state(struct intel_connector *connector)
> >  		WARN(!encoder->connectors_active,
> >  		     "encoder->connectors_active not set\n");
> >  
> > -		encoder_enabled = encoder->get_hw_state(encoder, &pipe);
> > +		encoder_enabled = intel_encoder_get_hw_state(encoder, &pipe);
> >  		WARN(!encoder_enabled, "encoder not enabled\n");
> >  		if (WARN_ON(!encoder->base.crtc))
> >  			return;
> > @@ -4561,7 +4561,7 @@ bool intel_connector_get_hw_state(struct intel_connector *connector)
> >  	enum pipe pipe = 0;
> >  	struct intel_encoder *encoder = connector->encoder;
> >  
> > -	return encoder->get_hw_state(encoder, &pipe);
> > +	return intel_encoder_get_hw_state(encoder, &pipe);
> >  }
> >  
> >  static bool ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe,
> > @@ -9464,6 +9464,19 @@ check_connector_state(struct drm_device *dev)
> >  	}
> >  }
> >  
> > +bool intel_encoder_get_hw_state(struct intel_encoder *intel_encoder,
> > +				enum pipe *pipe)
> > +{
> > +	enum intel_display_power_domain power_domain;
> > +	struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
> > +
> > +	power_domain = intel_display_port_power_domain(intel_encoder);
> > +	if (!intel_display_power_enabled(dev_priv, power_domain))
> > +		return false;
> > +
> > +	return intel_encoder->get_hw_state(intel_encoder, pipe);
> > +}
> > +
> >  static void
> >  check_encoder_state(struct drm_device *dev)
> >  {
> > @@ -9504,7 +9517,7 @@ check_encoder_state(struct drm_device *dev)
> >  		     "encoder's computed active state doesn't match tracked active state "
> >  		     "(expected %i, found %i)\n", active, encoder->connectors_active);
> >  
> > -		active = encoder->get_hw_state(encoder, &pipe);
> > +		active = intel_encoder_get_hw_state(encoder, &pipe);
> >  		WARN(active != encoder->connectors_active,
> >  		     "encoder's hw state doesn't match sw tracking "
> >  		     "(expected %i, found %i)\n",
> > @@ -9571,7 +9584,7 @@ check_crtc_state(struct drm_device *dev)
> >  			enum pipe pipe;
> >  			if (encoder->base.crtc != &crtc->base)
> >  				continue;
> > -			if (encoder->get_hw_state(encoder, &pipe))
> > +			if (intel_encoder_get_hw_state(encoder, &pipe))
> >  				encoder->get_config(encoder, &pipe_config);
> >  		}
> >  
> > @@ -11350,7 +11363,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
> >  			    base.head) {
> >  		pipe = 0;
> >  
> > -		if (encoder->get_hw_state(encoder, &pipe)) {
> > +		if (intel_encoder_get_hw_state(encoder, &pipe)) {
> >  			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
> >  			encoder->base.crtc = &crtc->base;
> >  			encoder->get_config(encoder, &crtc->config);
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index e31eb1e..afc01a4 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -738,6 +738,7 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder);
> >  int valleyview_get_vco(struct drm_i915_private *dev_priv);
> >  void intel_mode_from_pipe_config(struct drm_display_mode *mode,
> >  				 struct intel_crtc_config *pipe_config);
> > +bool intel_encoder_get_hw_state(struct intel_encoder *encoder, enum pipe *pipe);
> >  
> >  /* intel_dp.c */
> >  void intel_dp_init(struct drm_device *dev, int output_reg, enum port port);
> 
> I think there are a few more places to switch over, e.g.
> connector_check_state and connector_get_hw_state?

I haven't added a high level power domain check for those, because they
only call the encoder check-state and get-hw-state handler internally,
and those have power domain checks in place already.

I also postponed adding power domain checks for the PLL HW readout/state
checking code, since the development of that part is still in a bit of a
flux. But atm, it's only relevant on PCH platforms where we don't need
to care about power wells. So I'd add the checks for this when things
have settled.

> Maybe we should
> rename the fn pointer field to include a __ in the front so the
> compiler will catch them all and we'll know they're not to be called
> directly.

Hm, that'd mean some extra churn. I agree with your argument about the
compile time check it's a very nice guarantee for reviewers. I don't
have a strong opinion about the second argument. Some existing handlers
are also not ok to call in some contexts, so to keep things unified we'd
also have to prefix those. For now I'd just punt on this ..

--Imre

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 12/19] drm/i915: sanitize PUNIT register macro definitions
  2014-02-20 19:46   ` Jesse Barnes
@ 2014-02-24 13:12     ` Imre Deak
  0 siblings, 0 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-24 13:12 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 3668 bytes --]

On Thu, 2014-02-20 at 11:46 -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:13 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > In the upcoming patches we'll need to access the rest of the fields in
> > the punit power gating register, so prepare for that.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_reg.h     | 29 +++++++++++++++++++++++------
> >  drivers/gpu/drm/i915/intel_uncore.c |  4 +++-
> >  2 files changed, 26 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 2f564ce..5a700e9 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -377,14 +377,31 @@
> >  #define   DSPFREQSTAT_MASK			(0x3 << DSPFREQSTAT_SHIFT)
> >  #define   DSPFREQGUAR_SHIFT			14
> >  #define   DSPFREQGUAR_MASK			(0x3 << DSPFREQGUAR_SHIFT)
> > +
> > +enum punit_power_well {
> > +	PUNIT_POWER_WELL_RENDER			= 0,
> > +	PUNIT_POWER_WELL_MEDIA			= 1,
> > +	PUNIT_POWER_WELL_DISP2D			= 3,
> > +	PUNIT_POWER_WELL_DPIO_CMN_BC		= 5,
> > +	PUNIT_POWER_WELL_DPIO_TX_B_LANES_01	= 6,
> > +	PUNIT_POWER_WELL_DPIO_TX_B_LANES_23	= 7,
> > +	PUNIT_POWER_WELL_DPIO_TX_C_LANES_01	= 8,
> > +	PUNIT_POWER_WELL_DPIO_TX_C_LANES_23	= 9,
> > +	PUNIT_POWER_WELL_DPIO_RX0		= 10,
> > +	PUNIT_POWER_WELL_DPIO_RX1		= 11,
> > +	PUNIT_POWER_WELL_DPIO_RX2		= 12,
> > +	PUNIT_POWER_WELL_DPIO_RX3		= 13,
> > +
> > +	PUNIT_POWER_WELL_NUM,
> > +};
> > +
> >  #define PUNIT_REG_PWRGT_CTRL			0x60
> >  #define PUNIT_REG_PWRGT_STATUS			0x61
> > -#define	  PUNIT_CLK_GATE			1
> > -#define	  PUNIT_PWR_RESET			2
> > -#define	  PUNIT_PWR_GATE			3
> > -#define	  RENDER_PWRGT				(PUNIT_PWR_GATE << 0)
> > -#define	  MEDIA_PWRGT				(PUNIT_PWR_GATE << 2)
> > -#define	  DISP2D_PWRGT				(PUNIT_PWR_GATE << 6)
> > +#define   PUNIT_PWRGT_MASK(power_well)		(3 << ((power_well) * 2))
> > +#define   PUNIT_PWRGT_PWR_ON(power_well)	(0 << ((power_well) * 2))
> > +#define   PUNIT_PWRGT_CLK_GATE(power_well)	(1 << ((power_well) * 2))
> > +#define   PUNIT_PWRGT_RESET(power_well)		(2 << ((power_well) * 2))
> > +#define   PUNIT_PWRGT_PWR_GATE(power_well)	(3 << ((power_well) * 2))
> >  
> >  #define PUNIT_REG_GPU_LFM			0xd3
> >  #define PUNIT_REG_GPU_FREQ_REQ			0xd4
> > diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
> > index c628414..4aab7c2 100644
> > --- a/drivers/gpu/drm/i915/intel_uncore.c
> > +++ b/drivers/gpu/drm/i915/intel_uncore.c
> > @@ -354,7 +354,9 @@ void intel_uncore_sanitize(struct drm_device *dev)
> >  		mutex_lock(&dev_priv->rps.hw_lock);
> >  		reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS);
> >  
> > -		if (reg_val & (RENDER_PWRGT | MEDIA_PWRGT | DISP2D_PWRGT))
> > +		if (reg_val & (PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_RENDER) |
> > +			       PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_MEDIA) |
> > +			       PUNIT_PWRGT_PWR_GATE(PUNIT_POWER_WELL_DISP2D)))
> >  			vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, 0x0);
> >  
> >  		mutex_unlock(&dev_priv->rps.hw_lock);
> 
> I'd like to see a doc reference here, as I never remember which one has
> these bits...

It's the PUNIT 0.8 HAS, will add a comment about it here.

>   Also, are you sure about the RX bits?  The
> PUNIT_HAS_0.8 doc says only subsystems 10-11 cover RX, maybe in a ganged
> config?

You're right, I overlooked this, there are only 2 RX lanes. We don't use
them atm, but we'll still need to disable those wells. I'll fix this up.

--Imre

> 
> Otherwise:
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 14/19] drm/i915: switch order of power domain init wrt. irq install
  2014-02-20 19:48   ` Jesse Barnes
@ 2014-02-24 13:23     ` Imre Deak
  2014-03-05 10:29       ` Daniel Vetter
  0 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-24 13:23 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 1946 bytes --]

On Thu, 2014-02-20 at 11:48 -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:15 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > On VLV at least the display IRQ register access and functionality
> > depends on its power well to be on, so move the power domain HW init
> > before we install the IRQs.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_dma.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > index 8177c17..f8f7a59 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -1321,12 +1321,12 @@ static int i915_load_modeset_init(struct drm_device *dev)
> >  	if (ret)
> >  		goto cleanup_vga_switcheroo;
> >  
> > +	intel_power_domains_init_hw(dev_priv);
> > +
> >  	ret = drm_irq_install(dev);
> >  	if (ret)
> >  		goto cleanup_gem_stolen;
> >  
> > -	intel_power_domains_init_hw(dev_priv);
> > -
> >  	/* Important: The output setup functions called by modeset_init need
> >  	 * working irqs for e.g. gmbus and dp aux transfers. */
> >  	intel_modeset_init(dev);
> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 
> That said, this was always one part of the PM code that confused me and
> caused some refcounts to get messed up last time I worked on it.
>
> I think it would be better to not treat init specially, and let the
> power wells get turned on and off through normal power well get/put
> calls during init and resume.

I agree this is the ideal way and we should move towards that. Atm, we
have intel_display_set_init_power() for init and resume which is not so
nice, but it should do the right thing.

> It's a bit noisy, power wise, but ultimately it might make for clearer
> code and one less special case.

Yep and also give some power saving.

--Imre

[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions
  2014-02-17 22:02 ` [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions Imre Deak
  2014-02-20 19:17   ` Jesse Barnes
@ 2014-02-24 13:23   ` Paulo Zanoni
  2014-02-24 14:07     ` Imre Deak
  1 sibling, 1 reply; 68+ messages in thread
From: Paulo Zanoni @ 2014-02-24 13:23 UTC (permalink / raw)
  To: Imre Deak; +Cc: Intel Graphics Development

2014-02-17 19:02 GMT-03:00 Imre Deak <imre.deak@intel.com>:
> These functions are used only by a single call site and are simple
> enough to just fold them in.
>
> No functional change.
>
> Signed-off-by: Imre Deak <imre.deak@intel.com>

IMHO, this makes the code harder to read. I would prefer to not have
this change.


> ---
>  drivers/gpu/drm/i915/intel_pm.c | 37 +++++++++++++------------------------
>  1 file changed, 13 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index aa9c2df..db48d55 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -5305,27 +5305,6 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
>         }
>  }
>
> -static void __intel_power_well_get(struct drm_i915_private *dev_priv,
> -                                  struct i915_power_well *power_well)
> -{
> -       if (!power_well->count++ && power_well->set) {
> -               hsw_disable_package_c8(dev_priv);
> -               power_well->set(dev_priv, power_well, true);
> -       }
> -}
> -
> -static void __intel_power_well_put(struct drm_i915_private *dev_priv,
> -                                  struct i915_power_well *power_well)
> -{
> -       WARN_ON(!power_well->count);
> -
> -       if (!--power_well->count && power_well->set &&
> -           i915.disable_power_well) {
> -               power_well->set(dev_priv, power_well, false);
> -               hsw_enable_package_c8(dev_priv);
> -       }
> -}
> -
>  void intel_display_power_get(struct drm_i915_private *dev_priv,
>                              enum intel_display_power_domain domain)
>  {
> @@ -5338,7 +5317,10 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
>         mutex_lock(&power_domains->lock);
>
>         for_each_power_well(i, power_well, BIT(domain), power_domains)
> -               __intel_power_well_get(dev_priv, power_well);
> +               if (!power_well->count++ && power_well->set) {
> +                       hsw_disable_package_c8(dev_priv);
> +                       power_well->set(dev_priv, power_well, true);
> +               }
>
>         power_domains->domain_use_count[domain]++;
>
> @@ -5359,8 +5341,15 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
>         WARN_ON(!power_domains->domain_use_count[domain]);
>         power_domains->domain_use_count[domain]--;
>
> -       for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
> -               __intel_power_well_put(dev_priv, power_well);
> +       for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> +               WARN_ON(!power_well->count);
> +
> +               if (!--power_well->count && power_well->set &&
> +                               i915.disable_power_well) {
> +                       power_well->set(dev_priv, power_well, false);
> +                       hsw_enable_package_c8(dev_priv);
> +               }
> +       }
>
>         mutex_unlock(&power_domains->lock);
>  }
> --
> 1.8.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 17/19] drm/i915: vlv: factor out valleyview_display_irq_install
  2014-02-20 19:56   ` Jesse Barnes
@ 2014-02-24 13:34     ` Imre Deak
  0 siblings, 0 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-24 13:34 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 8907 bytes --]

On Thu, 2014-02-20 at 11:56 -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:18 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > We'll need to disable/re-enable the display-side IRQs when turning
> > off/on the VLV display power well. Factor out the helper functions
> > for this. For now keep the display IRQs enabled by default, so the
> > functionality doesn't change. This will be changed to enable/disable
> > the IRQs on-demand when adding support for VLV power wells in an
> > upcoming patch.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_dma.c |   1 +
> >  drivers/gpu/drm/i915/i915_drv.h |   5 ++
> >  drivers/gpu/drm/i915/i915_irq.c | 122 ++++++++++++++++++++++++++++++++--------
> >  3 files changed, 103 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > index f8f7a59..dca4dc3 100644
> > --- a/drivers/gpu/drm/i915/i915_dma.c
> > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > @@ -1668,6 +1668,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> >  		goto out_mtrrfree;
> >  	}
> >  
> > +	dev_priv->display_irqs_enabled = true;
> >  	intel_irq_init(dev);
> >  	intel_uncore_sanitize(dev);
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 632f9d8..227c349 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -1454,6 +1454,8 @@ typedef struct drm_i915_private {
> >  	/* protects the irq masks */
> >  	spinlock_t irq_lock;
> >  
> > +	bool display_irqs_enabled;
> > +
> >  	/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */
> >  	struct pm_qos_request pm_qos;
> >  
> > @@ -2052,6 +2054,9 @@ void
> >  i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
> >  		      u32 status_mask);
> >  
> > +void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv);
> > +void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv);
> > +
> >  /* i915_gem.c */
> >  int i915_gem_init_ioctl(struct drm_device *dev, void *data,
> >  			struct drm_file *file_priv);
> > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> > index 75dd0a8..6078d06 100644
> > --- a/drivers/gpu/drm/i915/i915_irq.c
> > +++ b/drivers/gpu/drm/i915/i915_irq.c
> > @@ -3016,41 +3016,109 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
> >  	return 0;
> >  }
> >  
> > +static void valleyview_display_irqs_install(struct drm_i915_private *dev_priv)
> > +{
> > +	unsigned long irqflags;
> > +	u32 pipestat_mask;
> > +	u32 iir_mask;
> > +
> > +	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
> > +			PIPE_FIFO_UNDERRUN_STATUS;
> > +	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
> > +	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
> > +	POSTING_READ(PIPESTAT(PIPE_A));
> > +
> > +	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
> > +			PIPE_CRC_DONE_INTERRUPT_STATUS;
> > +
> > +	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
> > +	i915_enable_pipestat(dev_priv, PIPE_A, pipestat_mask |
> > +					       PIPE_GMBUS_INTERRUPT_STATUS);
> > +	i915_enable_pipestat(dev_priv, PIPE_B, pipestat_mask);
> > +	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
> > +
> > +	iir_mask = I915_DISPLAY_PORT_INTERRUPT |
> > +		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> > +		   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
> > +	dev_priv->irq_mask &= ~iir_mask;
> > +
> > +	I915_WRITE(VLV_IIR, iir_mask);
> > +	I915_WRITE(VLV_IIR, iir_mask);
> > +	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
> > +	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
> > +	POSTING_READ(VLV_IER);
> > +}
> > +
> > +static void valleyview_display_irqs_uninstall(struct drm_i915_private *dev_priv)
> > +{
> > +	unsigned long irqflags;
> > +	u32 pipestat_mask;
> > +	u32 iir_mask;
> > +
> > +	iir_mask = I915_DISPLAY_PORT_INTERRUPT |
> > +		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> > +		   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
> > +	dev_priv->irq_mask |= iir_mask;
> > +	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
> > +	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
> > +	I915_WRITE(VLV_IIR, iir_mask);
> > +	I915_WRITE(VLV_IIR, iir_mask);
> > +	POSTING_READ(VLV_IIR);
> > +
> > +	pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV |
> > +			PIPE_CRC_DONE_INTERRUPT_STATUS;
> > +
> > +	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
> > +	i915_disable_pipestat(dev_priv, PIPE_A, pipestat_mask |
> > +					        PIPE_GMBUS_INTERRUPT_STATUS);
> > +	i915_disable_pipestat(dev_priv, PIPE_B, pipestat_mask);
> > +	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
> > +
> > +	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
> > +			PIPE_FIFO_UNDERRUN_STATUS;
> > +	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
> > +	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);
> > +	POSTING_READ(PIPESTAT(PIPE_A));
> > +}
> > +
> > +void valleyview_enable_display_irqs(struct drm_i915_private *dev_priv)
> > +{
> > +	if (dev_priv->display_irqs_enabled)
> > +		return;
> > +
> > +	dev_priv->display_irqs_enabled = true;
> > +
> > +	if (dev_priv->dev->irq_enabled)
> > +		valleyview_display_irqs_install(dev_priv);
> > +}
> > +
> > +void valleyview_disable_display_irqs(struct drm_i915_private *dev_priv)
> > +{
> > +	if (!dev_priv->display_irqs_enabled)
> > +		return;
> > +
> > +	dev_priv->display_irqs_enabled = false;
> > +
> > +	if (dev_priv->dev->irq_enabled)
> > +		valleyview_display_irqs_uninstall(dev_priv);
> > +}
> > +
> >  static int valleyview_irq_postinstall(struct drm_device *dev)
> >  {
> >  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
> > -	u32 enable_mask;
> > -	u32 pipestat_enable = PLANE_FLIP_DONE_INT_STATUS_VLV |
> > -		PIPE_CRC_DONE_INTERRUPT_STATUS;
> > -	unsigned long irqflags;
> >  
> > -	enable_mask = I915_DISPLAY_PORT_INTERRUPT;
> > -	enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
> > -		I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
> > -
> > -	/*
> > -	 *Leave vblank interrupts masked initially.  enable/disable will
> > -	 * toggle them based on usage.
> > -	 */
> > -	dev_priv->irq_mask = ~enable_mask;
> > +	dev_priv->irq_mask = ~0;
> >  
> >  	I915_WRITE(PORT_HOTPLUG_EN, 0);
> >  	POSTING_READ(PORT_HOTPLUG_EN);
> >  
> >  	I915_WRITE(VLV_IMR, dev_priv->irq_mask);
> > -	I915_WRITE(VLV_IER, enable_mask);
> > +	I915_WRITE(VLV_IER, ~dev_priv->irq_mask);
> >  	I915_WRITE(VLV_IIR, 0xffffffff);
> > -	I915_WRITE(PIPESTAT(0), 0xffff);
> > -	I915_WRITE(PIPESTAT(1), 0xffff);
> >  	POSTING_READ(VLV_IER);
> >  
> > -	/* Interrupt setup is already guaranteed to be single-threaded, this is
> > -	 * just to make the assert_spin_locked check happy. */
> > -	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
> > -	i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable);
> > -	i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS);
> > -	i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable);
> > -	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
> > +	if (dev_priv->display_irqs_enabled)
> > +		valleyview_display_irqs_install(dev_priv);
> >  
> >  	I915_WRITE(VLV_IIR, 0xffffffff);
> >  	I915_WRITE(VLV_IIR, 0xffffffff);
> > @@ -3193,8 +3261,12 @@ static void valleyview_irq_uninstall(struct drm_device *dev)
> >  	I915_WRITE(HWSTAM, 0xffffffff);
> >  	I915_WRITE(PORT_HOTPLUG_EN, 0);
> >  	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
> > -	for_each_pipe(pipe)
> > -		I915_WRITE(PIPESTAT(pipe), 0xffff);
> > +
> > +	if (dev_priv->display_irqs_enabled)
> > +		valleyview_display_irqs_uninstall(dev_priv);
> > +
> > +	dev_priv->irq_mask = 0;
> > +
> >  	I915_WRITE(VLV_IIR, 0xffffffff);
> >  	I915_WRITE(VLV_IMR, 0xffffffff);
> >  	I915_WRITE(VLV_IER, 0x0);
> 
> IRQ enable state and reg state may be another good thing to cross
> check.

A good idea, I can add that check as a follow-up.

>   And on disable, it might be a good thing to just write all of
> the pipestat irq status bits to avoid stuck interrupts (I think the
> order is ok though).

I added

+	pipestat_mask = PIPESTAT_INT_STATUS_MASK |
+			PIPE_FIFO_UNDERRUN_STATUS;
+	I915_WRITE(PIPESTAT(PIPE_A), pipestat_mask);
+	I915_WRITE(PIPESTAT(PIPE_B), pipestat_mask);

which does that.

> But you've probably tested it already so I assume it works ok.

kms_flip passed except the modset_vs_hang subtests which have an open
bugzilla ticket and I think are unrelated to this change.

One more thing I noticed meanwhile, is that the locking in
valleyview_display_irqs_install/uninstall() should be around all
register accesses, since we can call these functions with interrupts
already enabled.

--Imre

> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 04/19] drm/i915: move power domain macros to intel_pm.c
  2014-02-20 19:21   ` Jesse Barnes
@ 2014-02-24 13:38     ` Paulo Zanoni
  2014-02-24 13:54       ` Imre Deak
  0 siblings, 1 reply; 68+ messages in thread
From: Paulo Zanoni @ 2014-02-24 13:38 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: Intel Graphics Development

2014-02-20 16:21 GMT-03:00 Jesse Barnes <jbarnes@virtuousgeek.org>:
> On Tue, 18 Feb 2014 00:02:05 +0200
> Imre Deak <imre.deak@intel.com> wrote:
>
>> These macros are used only locally, so move them to the .c file.
>>
>> Also since logically the init power domain should be part of all power
>> wells add it to the always-on power wells too for consistency. Since
>> always-on power wells have noop handlers, this doesn't change the
>> functionality.

This patch should be split in two: one moves to .c, the other changes
the init power domain.

But I'm a little confused. I always understood that the "power_on"
domains were things that were always enabled on the hardware, so you
couldn't really turn them "off", no matter how many domains you put.
But the init power domain is different: when you get the init domain,
a lot of stuff can get enabled, and when you put it, a lot of stuff
can be disabled. By this logic, your patch would not make sense. So I
guess we probably have two different definitions for what is a
always_on power domain. I think we probably need to add some comments
in the source code to clarify the definitions of things, to avoid
further confusion :)

>>
>> Signed-off-by: Imre Deak <imre.deak@intel.com>
>> ---
>>  drivers/gpu/drm/i915/i915_drv.h | 10 ----------
>>  drivers/gpu/drm/i915/intel_pm.c | 21 +++++++++++++++++++--
>>  2 files changed, 19 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> index 796f971..de0c0e0 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.h
>> +++ b/drivers/gpu/drm/i915/i915_drv.h
>> @@ -121,8 +121,6 @@ enum intel_display_power_domain {
>>       POWER_DOMAIN_NUM,
>>  };
>>
>> -#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
>> -
>>  #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
>>  #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
>>               ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
>> @@ -130,14 +128,6 @@ enum intel_display_power_domain {
>>       ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
>>        (tran) + POWER_DOMAIN_TRANSCODER_A)
>>
>> -#define HSW_ALWAYS_ON_POWER_DOMAINS (                \
>> -     BIT(POWER_DOMAIN_PIPE_A) |              \
>> -     BIT(POWER_DOMAIN_TRANSCODER_EDP))
>> -#define BDW_ALWAYS_ON_POWER_DOMAINS (                \
>> -     BIT(POWER_DOMAIN_PIPE_A) |              \
>> -     BIT(POWER_DOMAIN_TRANSCODER_EDP) |      \
>> -     BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
>> -
>>  enum hpd_pin {
>>       HPD_NONE = 0,
>>       HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
>> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
>> index db48d55..9a608f1 100644
>> --- a/drivers/gpu/drm/i915/intel_pm.c
>> +++ b/drivers/gpu/drm/i915/intel_pm.c
>> @@ -5384,6 +5384,23 @@ void i915_release_power_well(void)
>>  }
>>  EXPORT_SYMBOL_GPL(i915_release_power_well);
>>
>> +#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
>> +
>> +#define HSW_ALWAYS_ON_POWER_DOMAINS (                        \
>> +     BIT(POWER_DOMAIN_PIPE_A) |                      \
>> +     BIT(POWER_DOMAIN_TRANSCODER_EDP) |              \
>> +     BIT(POWER_DOMAIN_INIT))
>> +#define HSW_DISPLAY_POWER_DOMAINS (                          \
>> +     (POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |    \
>> +     BIT(POWER_DOMAIN_INIT))
>> +
>> +#define BDW_ALWAYS_ON_POWER_DOMAINS (                        \
>> +     HSW_ALWAYS_ON_POWER_DOMAINS |                   \
>> +     BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
>> +#define BDW_DISPLAY_POWER_DOMAINS (                          \
>> +     (POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |    \
>> +     BIT(POWER_DOMAIN_INIT))
>> +
>>  static struct i915_power_well i9xx_always_on_power_well[] = {
>>       {
>>               .name = "always-on",
>> @@ -5400,7 +5417,7 @@ static struct i915_power_well hsw_power_wells[] = {
>>       },
>>       {
>>               .name = "display",
>> -             .domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS,
>> +             .domains = HSW_DISPLAY_POWER_DOMAINS,
>>               .is_enabled = hsw_power_well_enabled,
>>               .set = hsw_set_power_well,
>>       },
>> @@ -5414,7 +5431,7 @@ static struct i915_power_well bdw_power_wells[] = {
>>       },
>>       {
>>               .name = "display",
>> -             .domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS,
>> +             .domains = BDW_DISPLAY_POWER_DOMAINS,
>>               .is_enabled = hsw_power_well_enabled,
>>               .set = hsw_set_power_well,
>>       },
>
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
>
> --
> Jesse Barnes, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 04/19] drm/i915: move power domain macros to intel_pm.c
  2014-02-24 13:38     ` Paulo Zanoni
@ 2014-02-24 13:54       ` Imre Deak
  0 siblings, 0 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-24 13:54 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development


[-- Attachment #1.1: Type: text/plain, Size: 5774 bytes --]

On Mon, 2014-02-24 at 10:38 -0300, Paulo Zanoni wrote:
> 2014-02-20 16:21 GMT-03:00 Jesse Barnes <jbarnes@virtuousgeek.org>:
> > On Tue, 18 Feb 2014 00:02:05 +0200
> > Imre Deak <imre.deak@intel.com> wrote:
> >
> >> These macros are used only locally, so move them to the .c file.
> >>
> >> Also since logically the init power domain should be part of all power
> >> wells add it to the always-on power wells too for consistency. Since
> >> always-on power wells have noop handlers, this doesn't change the
> >> functionality.
> 
> This patch should be split in two: one moves to .c, the other changes
> the init power domain.

Ok.

> But I'm a little confused. I always understood that the "power_on"
> domains were things that were always enabled on the hardware, so you
> couldn't really turn them "off", no matter how many domains you put.
> But the init power domain is different: when you get the init domain,
> a lot of stuff can get enabled, and when you put it, a lot of stuff
> can be disabled. By this logic, your patch would not make sense. So I
> guess we probably have two different definitions for what is a
> always_on power domain. I think we probably need to add some comments
> in the source code to clarify the definitions of things, to avoid
> further confusion :)

In general getting a power domain guarantees that you can access the
relevant registers, so if you get POWER_DOMAIN_INIT it should enable all
the HW resources necessary for this. For always-on power wells that
won't involve turning on a power well, but it may involve enabling other
resources. A good example is the HSW CRT port power domain, which is on
the always-on power well, so we don't need to enable any power well for
it, but we still need to disable runtime PM.

--Imre

> 
> >>
> >> Signed-off-by: Imre Deak <imre.deak@intel.com>
> >> ---
> >>  drivers/gpu/drm/i915/i915_drv.h | 10 ----------
> >>  drivers/gpu/drm/i915/intel_pm.c | 21 +++++++++++++++++++--
> >>  2 files changed, 19 insertions(+), 12 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> >> index 796f971..de0c0e0 100644
> >> --- a/drivers/gpu/drm/i915/i915_drv.h
> >> +++ b/drivers/gpu/drm/i915/i915_drv.h
> >> @@ -121,8 +121,6 @@ enum intel_display_power_domain {
> >>       POWER_DOMAIN_NUM,
> >>  };
> >>
> >> -#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
> >> -
> >>  #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
> >>  #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
> >>               ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
> >> @@ -130,14 +128,6 @@ enum intel_display_power_domain {
> >>       ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
> >>        (tran) + POWER_DOMAIN_TRANSCODER_A)
> >>
> >> -#define HSW_ALWAYS_ON_POWER_DOMAINS (                \
> >> -     BIT(POWER_DOMAIN_PIPE_A) |              \
> >> -     BIT(POWER_DOMAIN_TRANSCODER_EDP))
> >> -#define BDW_ALWAYS_ON_POWER_DOMAINS (                \
> >> -     BIT(POWER_DOMAIN_PIPE_A) |              \
> >> -     BIT(POWER_DOMAIN_TRANSCODER_EDP) |      \
> >> -     BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
> >> -
> >>  enum hpd_pin {
> >>       HPD_NONE = 0,
> >>       HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
> >> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> >> index db48d55..9a608f1 100644
> >> --- a/drivers/gpu/drm/i915/intel_pm.c
> >> +++ b/drivers/gpu/drm/i915/intel_pm.c
> >> @@ -5384,6 +5384,23 @@ void i915_release_power_well(void)
> >>  }
> >>  EXPORT_SYMBOL_GPL(i915_release_power_well);
> >>
> >> +#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
> >> +
> >> +#define HSW_ALWAYS_ON_POWER_DOMAINS (                        \
> >> +     BIT(POWER_DOMAIN_PIPE_A) |                      \
> >> +     BIT(POWER_DOMAIN_TRANSCODER_EDP) |              \
> >> +     BIT(POWER_DOMAIN_INIT))
> >> +#define HSW_DISPLAY_POWER_DOMAINS (                          \
> >> +     (POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS) |    \
> >> +     BIT(POWER_DOMAIN_INIT))
> >> +
> >> +#define BDW_ALWAYS_ON_POWER_DOMAINS (                        \
> >> +     HSW_ALWAYS_ON_POWER_DOMAINS |                   \
> >> +     BIT(POWER_DOMAIN_PIPE_A_PANEL_FITTER))
> >> +#define BDW_DISPLAY_POWER_DOMAINS (                          \
> >> +     (POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS) |    \
> >> +     BIT(POWER_DOMAIN_INIT))
> >> +
> >>  static struct i915_power_well i9xx_always_on_power_well[] = {
> >>       {
> >>               .name = "always-on",
> >> @@ -5400,7 +5417,7 @@ static struct i915_power_well hsw_power_wells[] = {
> >>       },
> >>       {
> >>               .name = "display",
> >> -             .domains = POWER_DOMAIN_MASK & ~HSW_ALWAYS_ON_POWER_DOMAINS,
> >> +             .domains = HSW_DISPLAY_POWER_DOMAINS,
> >>               .is_enabled = hsw_power_well_enabled,
> >>               .set = hsw_set_power_well,
> >>       },
> >> @@ -5414,7 +5431,7 @@ static struct i915_power_well bdw_power_wells[] = {
> >>       },
> >>       {
> >>               .name = "display",
> >> -             .domains = POWER_DOMAIN_MASK & ~BDW_ALWAYS_ON_POWER_DOMAINS,
> >> +             .domains = BDW_DISPLAY_POWER_DOMAINS,
> >>               .is_enabled = hsw_power_well_enabled,
> >>               .set = hsw_set_power_well,
> >>       },
> >
> > Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> >
> > --
> > Jesse Barnes, Intel Open Source Technology Center
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions
  2014-02-24 13:23   ` Paulo Zanoni
@ 2014-02-24 14:07     ` Imre Deak
  0 siblings, 0 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-24 14:07 UTC (permalink / raw)
  To: Paulo Zanoni; +Cc: Intel Graphics Development


[-- Attachment #1.1: Type: text/plain, Size: 3814 bytes --]

On Mon, 2014-02-24 at 10:23 -0300, Paulo Zanoni wrote:
> 2014-02-17 19:02 GMT-03:00 Imre Deak <imre.deak@intel.com>:
> > These functions are used only by a single call site and are simple
> > enough to just fold them in.
> >
> > No functional change.
> >
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> 
> IMHO, this makes the code harder to read. I would prefer to not have
> this change.

I find intel_display_power_put() after patch 19/19 simple enough to not
have the separate functions. I'd say that in this case readability is
actually better with the inlined version, as you don't have to jump
between two functions when reading the code.

--Imre

> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 37 +++++++++++++------------------------
> >  1 file changed, 13 insertions(+), 24 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index aa9c2df..db48d55 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -5305,27 +5305,6 @@ static void hsw_set_power_well(struct drm_i915_private *dev_priv,
> >         }
> >  }
> >
> > -static void __intel_power_well_get(struct drm_i915_private *dev_priv,
> > -                                  struct i915_power_well *power_well)
> > -{
> > -       if (!power_well->count++ && power_well->set) {
> > -               hsw_disable_package_c8(dev_priv);
> > -               power_well->set(dev_priv, power_well, true);
> > -       }
> > -}
> > -
> > -static void __intel_power_well_put(struct drm_i915_private *dev_priv,
> > -                                  struct i915_power_well *power_well)
> > -{
> > -       WARN_ON(!power_well->count);
> > -
> > -       if (!--power_well->count && power_well->set &&
> > -           i915.disable_power_well) {
> > -               power_well->set(dev_priv, power_well, false);
> > -               hsw_enable_package_c8(dev_priv);
> > -       }
> > -}
> > -
> >  void intel_display_power_get(struct drm_i915_private *dev_priv,
> >                              enum intel_display_power_domain domain)
> >  {
> > @@ -5338,7 +5317,10 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
> >         mutex_lock(&power_domains->lock);
> >
> >         for_each_power_well(i, power_well, BIT(domain), power_domains)
> > -               __intel_power_well_get(dev_priv, power_well);
> > +               if (!power_well->count++ && power_well->set) {
> > +                       hsw_disable_package_c8(dev_priv);
> > +                       power_well->set(dev_priv, power_well, true);
> > +               }
> >
> >         power_domains->domain_use_count[domain]++;
> >
> > @@ -5359,8 +5341,15 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
> >         WARN_ON(!power_domains->domain_use_count[domain]);
> >         power_domains->domain_use_count[domain]--;
> >
> > -       for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
> > -               __intel_power_well_put(dev_priv, power_well);
> > +       for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
> > +               WARN_ON(!power_well->count);
> > +
> > +               if (!--power_well->count && power_well->set &&
> > +                               i915.disable_power_well) {
> > +                       power_well->set(dev_priv, power_well, false);
> > +                       hsw_enable_package_c8(dev_priv);
> > +               }
> > +       }
> >
> >         mutex_unlock(&power_domains->lock);
> >  }
> > --
> > 1.8.4
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> 
> 


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 19/19] drm/i915: power domains: add vlv power wells
  2014-02-20 19:58     ` Jesse Barnes
@ 2014-02-26 18:02       ` Imre Deak
  2014-02-26 19:52         ` Jesse Barnes
  0 siblings, 1 reply; 68+ messages in thread
From: Imre Deak @ 2014-02-26 18:02 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 5333 bytes --]

On Thu, 2014-02-20 at 11:58 -0800, Jesse Barnes wrote:
> On Wed, 19 Feb 2014 14:29:44 +0200
> Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> 
> > On Tue, Feb 18, 2014 at 12:02:20AM +0200, Imre Deak wrote:
> > > Based on an early draft from Jesse.
> > > 
> > > Add support for powering on/off the dynamic power wells on VLV by
> > > registering its display and dpio dynamic power wells with the power
> > > domain framework.
> > > 
> > > For now power on all PHY TX lanes regardless of the actual lane
> > > configuration. Later this can be optimized when the PHY side setup
> > > enables only the required lanes. Atm, it enables all lanes in all
> > > cases.
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_dma.c      |   1 -
> > >  drivers/gpu/drm/i915/i915_drv.h      |   2 +-
> > >  drivers/gpu/drm/i915/intel_display.c |   1 +
> > >  drivers/gpu/drm/i915/intel_pm.c      | 228 +++++++++++++++++++++++++++++++++++
> > >  4 files changed, 230 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > > index dca4dc3..f8f7a59 100644
> > > --- a/drivers/gpu/drm/i915/i915_dma.c
> > > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > > @@ -1668,7 +1668,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> > >  		goto out_mtrrfree;
> > >  	}
> > >  
> > > -	dev_priv->display_irqs_enabled = true;
> > >  	intel_irq_init(dev);
> > >  	intel_uncore_sanitize(dev);
> > >  
> > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > > index 227c349..804334e 100644
> > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > @@ -1053,7 +1053,7 @@ struct i915_power_well {
> > >  	/* power well enable/disable usage count */
> > >  	int count;
> > >  	unsigned long domains;
> > > -	void *data;
> > > +	unsigned long data;
> > >  	const struct i915_power_well_ops *ops;
> > >  };
> > >  
> > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > index ea00878..d6661c4 100644
> > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > @@ -4224,6 +4224,7 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
> > >  
> > >  	if (req_cdclk != cur_cdclk)
> > >  		valleyview_set_cdclk(dev, req_cdclk);
> > > +	modeset_update_power_wells(dev);
> > >  }
> > >  
> > >  static void valleyview_crtc_enable(struct drm_crtc *crtc)
> > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > index 68f58e5..e4416a7 100644
> > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > @@ -5344,6 +5344,133 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> > >  	hsw_enable_package_c8(dev_priv);
> > >  }
> > >  
> > > +static void vlv_set_power_well(struct drm_i915_private *dev_priv,
> > > +			       struct i915_power_well *power_well, bool enable)
> > > +{
> > > +	enum punit_power_well power_well_id = power_well->data;
> > > +	u32 mask;
> > > +	u32 state;
> > > +	u32 ctrl;
> > > +
> > > +	mask = PUNIT_PWRGT_MASK(power_well_id);
> > > +	state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
> > > +			 PUNIT_PWRGT_PWR_GATE(power_well_id);
> > > +
> > > +	mutex_lock(&dev_priv->rps.hw_lock);
> > > +
> > > +#define COND \
> > > +	((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
> > > +
> > > +	if (COND)
> > > +		goto out;
> > > +
> > > +	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
> > > +	ctrl &= ~mask;
> > > +	ctrl |= state;
> > > +	vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
> > > +
> > > +	if (wait_for(COND, 100))
> > > +		DRM_ERROR("timout setting power well state %08x (%08x)\n",
> > > +			  state,
> > > +			  vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
> > 
> > #undef COND somewhere to avoid suprises further down in the code?
> > 
> > > +
> > > +out:
> > > +	mutex_unlock(&dev_priv->rps.hw_lock);
> > > +}
> > > +
> > <snip>
> > 
> 
> I'd like to see the code for re-enabling the display state land
> eventually too, so we can get savings when userspace uses DPMS instead
> of NULL mode sets for things.  But to do that nicely requires some more
> work in the mode set code to pull out more PLL bits (also needed for
> atomic mode setting).

I guess you meant here the drm connector->funcs->dpms() callback, that's
called when setting the connector's dpms property. But I'm not sure what
you meant by re-enabling the display state.

I was thinking that we need to get/put the power domains around setting
DPMS off/on via the above property, but we actually don't need that.
Internally the dpms callback just calls the
display.disable_crtc/enable_crtc() which will disable/enable the pipes
but won't do anything with the power domains (which is only updated
during a normal modeset through display.modeset_global_resources().

This isn't optimal power-wise, but it's a separate issue. I think Daniel
had the idea of converting the dpms callback to be a proper NULL
modeset. In that case too the power domains will be get/put correctly.

--Imre


[-- Attachment #1.2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 19/19] drm/i915: power domains: add vlv power wells
  2014-02-26 18:02       ` Imre Deak
@ 2014-02-26 19:52         ` Jesse Barnes
  2014-02-27 10:03           ` Imre Deak
  2014-03-05 10:38           ` Daniel Vetter
  0 siblings, 2 replies; 68+ messages in thread
From: Jesse Barnes @ 2014-02-26 19:52 UTC (permalink / raw)
  To: imre.deak; +Cc: intel-gfx

On Wed, 26 Feb 2014 20:02:19 +0200
Imre Deak <imre.deak@intel.com> wrote:

> On Thu, 2014-02-20 at 11:58 -0800, Jesse Barnes wrote:
> > On Wed, 19 Feb 2014 14:29:44 +0200
> > Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > 
> > > On Tue, Feb 18, 2014 at 12:02:20AM +0200, Imre Deak wrote:
> > > > Based on an early draft from Jesse.
> > > > 
> > > > Add support for powering on/off the dynamic power wells on VLV by
> > > > registering its display and dpio dynamic power wells with the power
> > > > domain framework.
> > > > 
> > > > For now power on all PHY TX lanes regardless of the actual lane
> > > > configuration. Later this can be optimized when the PHY side setup
> > > > enables only the required lanes. Atm, it enables all lanes in all
> > > > cases.
> > > > 
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/i915_dma.c      |   1 -
> > > >  drivers/gpu/drm/i915/i915_drv.h      |   2 +-
> > > >  drivers/gpu/drm/i915/intel_display.c |   1 +
> > > >  drivers/gpu/drm/i915/intel_pm.c      | 228 +++++++++++++++++++++++++++++++++++
> > > >  4 files changed, 230 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > > > index dca4dc3..f8f7a59 100644
> > > > --- a/drivers/gpu/drm/i915/i915_dma.c
> > > > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > > > @@ -1668,7 +1668,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> > > >  		goto out_mtrrfree;
> > > >  	}
> > > >  
> > > > -	dev_priv->display_irqs_enabled = true;
> > > >  	intel_irq_init(dev);
> > > >  	intel_uncore_sanitize(dev);
> > > >  
> > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > > > index 227c349..804334e 100644
> > > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > > @@ -1053,7 +1053,7 @@ struct i915_power_well {
> > > >  	/* power well enable/disable usage count */
> > > >  	int count;
> > > >  	unsigned long domains;
> > > > -	void *data;
> > > > +	unsigned long data;
> > > >  	const struct i915_power_well_ops *ops;
> > > >  };
> > > >  
> > > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > > index ea00878..d6661c4 100644
> > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > @@ -4224,6 +4224,7 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
> > > >  
> > > >  	if (req_cdclk != cur_cdclk)
> > > >  		valleyview_set_cdclk(dev, req_cdclk);
> > > > +	modeset_update_power_wells(dev);
> > > >  }
> > > >  
> > > >  static void valleyview_crtc_enable(struct drm_crtc *crtc)
> > > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > > index 68f58e5..e4416a7 100644
> > > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > > @@ -5344,6 +5344,133 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> > > >  	hsw_enable_package_c8(dev_priv);
> > > >  }
> > > >  
> > > > +static void vlv_set_power_well(struct drm_i915_private *dev_priv,
> > > > +			       struct i915_power_well *power_well, bool enable)
> > > > +{
> > > > +	enum punit_power_well power_well_id = power_well->data;
> > > > +	u32 mask;
> > > > +	u32 state;
> > > > +	u32 ctrl;
> > > > +
> > > > +	mask = PUNIT_PWRGT_MASK(power_well_id);
> > > > +	state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
> > > > +			 PUNIT_PWRGT_PWR_GATE(power_well_id);
> > > > +
> > > > +	mutex_lock(&dev_priv->rps.hw_lock);
> > > > +
> > > > +#define COND \
> > > > +	((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
> > > > +
> > > > +	if (COND)
> > > > +		goto out;
> > > > +
> > > > +	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
> > > > +	ctrl &= ~mask;
> > > > +	ctrl |= state;
> > > > +	vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
> > > > +
> > > > +	if (wait_for(COND, 100))
> > > > +		DRM_ERROR("timout setting power well state %08x (%08x)\n",
> > > > +			  state,
> > > > +			  vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
> > > 
> > > #undef COND somewhere to avoid suprises further down in the code?
> > > 
> > > > +
> > > > +out:
> > > > +	mutex_unlock(&dev_priv->rps.hw_lock);
> > > > +}
> > > > +
> > > <snip>
> > > 
> > 
> > I'd like to see the code for re-enabling the display state land
> > eventually too, so we can get savings when userspace uses DPMS instead
> > of NULL mode sets for things.  But to do that nicely requires some more
> > work in the mode set code to pull out more PLL bits (also needed for
> > atomic mode setting).
> 
> I guess you meant here the drm connector->funcs->dpms() callback, that's
> called when setting the connector's dpms property. But I'm not sure what
> you meant by re-enabling the display state.
> 
> I was thinking that we need to get/put the power domains around setting
> DPMS off/on via the above property, but we actually don't need that.
> Internally the dpms callback just calls the
> display.disable_crtc/enable_crtc() which will disable/enable the pipes
> but won't do anything with the power domains (which is only updated
> during a normal modeset through display.modeset_global_resources().
> 
> This isn't optimal power-wise, but it's a separate issue. I think Daniel
> had the idea of converting the dpms callback to be a proper NULL
> modeset. In that case too the power domains will be get/put correctly.

Right, that's what I'm getting at.  Today when someone uses the DPMS
prop, we won't go through the mode set path and thus won't do any power
well toggles.  I think that's a bug we should fix.  Either by making
DPMS into a NULL mode set, or pulling out more bits from our mode set
sequence into our crtc enable/disable paths.

My earlier code did this somewhat differently, but it did cover DPMS.

-- 
Jesse Barnes, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 19/19] drm/i915: power domains: add vlv power wells
  2014-02-26 19:52         ` Jesse Barnes
@ 2014-02-27 10:03           ` Imre Deak
  2014-03-05 10:38           ` Daniel Vetter
  1 sibling, 0 replies; 68+ messages in thread
From: Imre Deak @ 2014-02-27 10:03 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Wed, 2014-02-26 at 11:52 -0800, Jesse Barnes wrote:
> On Wed, 26 Feb 2014 20:02:19 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > On Thu, 2014-02-20 at 11:58 -0800, Jesse Barnes wrote:
> > > On Wed, 19 Feb 2014 14:29:44 +0200
> > > Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > > 
> > > > On Tue, Feb 18, 2014 at 12:02:20AM +0200, Imre Deak wrote:
> > > > > Based on an early draft from Jesse.
> > > > > 
> > > > > Add support for powering on/off the dynamic power wells on VLV by
> > > > > registering its display and dpio dynamic power wells with the power
> > > > > domain framework.
> > > > > 
> > > > > For now power on all PHY TX lanes regardless of the actual lane
> > > > > configuration. Later this can be optimized when the PHY side setup
> > > > > enables only the required lanes. Atm, it enables all lanes in all
> > > > > cases.
> > > > > 
> > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/i915_dma.c      |   1 -
> > > > >  drivers/gpu/drm/i915/i915_drv.h      |   2 +-
> > > > >  drivers/gpu/drm/i915/intel_display.c |   1 +
> > > > >  drivers/gpu/drm/i915/intel_pm.c      | 228 +++++++++++++++++++++++++++++++++++
> > > > >  4 files changed, 230 insertions(+), 2 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > > > > index dca4dc3..f8f7a59 100644
> > > > > --- a/drivers/gpu/drm/i915/i915_dma.c
> > > > > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > > > > @@ -1668,7 +1668,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
> > > > >  		goto out_mtrrfree;
> > > > >  	}
> > > > >  
> > > > > -	dev_priv->display_irqs_enabled = true;
> > > > >  	intel_irq_init(dev);
> > > > >  	intel_uncore_sanitize(dev);
> > > > >  
> > > > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > > > > index 227c349..804334e 100644
> > > > > --- a/drivers/gpu/drm/i915/i915_drv.h
> > > > > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > > > > @@ -1053,7 +1053,7 @@ struct i915_power_well {
> > > > >  	/* power well enable/disable usage count */
> > > > >  	int count;
> > > > >  	unsigned long domains;
> > > > > -	void *data;
> > > > > +	unsigned long data;
> > > > >  	const struct i915_power_well_ops *ops;
> > > > >  };
> > > > >  
> > > > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > > > > index ea00878..d6661c4 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_display.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_display.c
> > > > > @@ -4224,6 +4224,7 @@ static void valleyview_modeset_global_resources(struct drm_device *dev)
> > > > >  
> > > > >  	if (req_cdclk != cur_cdclk)
> > > > >  		valleyview_set_cdclk(dev, req_cdclk);
> > > > > +	modeset_update_power_wells(dev);
> > > > >  }
> > > > >  
> > > > >  static void valleyview_crtc_enable(struct drm_crtc *crtc)
> > > > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > > > index 68f58e5..e4416a7 100644
> > > > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > > > @@ -5344,6 +5344,133 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> > > > >  	hsw_enable_package_c8(dev_priv);
> > > > >  }
> > > > >  
> > > > > +static void vlv_set_power_well(struct drm_i915_private *dev_priv,
> > > > > +			       struct i915_power_well *power_well, bool enable)
> > > > > +{
> > > > > +	enum punit_power_well power_well_id = power_well->data;
> > > > > +	u32 mask;
> > > > > +	u32 state;
> > > > > +	u32 ctrl;
> > > > > +
> > > > > +	mask = PUNIT_PWRGT_MASK(power_well_id);
> > > > > +	state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) :
> > > > > +			 PUNIT_PWRGT_PWR_GATE(power_well_id);
> > > > > +
> > > > > +	mutex_lock(&dev_priv->rps.hw_lock);
> > > > > +
> > > > > +#define COND \
> > > > > +	((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state)
> > > > > +
> > > > > +	if (COND)
> > > > > +		goto out;
> > > > > +
> > > > > +	ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL);
> > > > > +	ctrl &= ~mask;
> > > > > +	ctrl |= state;
> > > > > +	vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, ctrl);
> > > > > +
> > > > > +	if (wait_for(COND, 100))
> > > > > +		DRM_ERROR("timout setting power well state %08x (%08x)\n",
> > > > > +			  state,
> > > > > +			  vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL));
> > > > 
> > > > #undef COND somewhere to avoid suprises further down in the code?
> > > > 
> > > > > +
> > > > > +out:
> > > > > +	mutex_unlock(&dev_priv->rps.hw_lock);
> > > > > +}
> > > > > +
> > > > <snip>
> > > > 
> > > 
> > > I'd like to see the code for re-enabling the display state land
> > > eventually too, so we can get savings when userspace uses DPMS instead
> > > of NULL mode sets for things.  But to do that nicely requires some more
> > > work in the mode set code to pull out more PLL bits (also needed for
> > > atomic mode setting).
> > 
> > I guess you meant here the drm connector->funcs->dpms() callback, that's
> > called when setting the connector's dpms property. But I'm not sure what
> > you meant by re-enabling the display state.
> > 
> > I was thinking that we need to get/put the power domains around setting
> > DPMS off/on via the above property, but we actually don't need that.
> > Internally the dpms callback just calls the
> > display.disable_crtc/enable_crtc() which will disable/enable the pipes
> > but won't do anything with the power domains (which is only updated
> > during a normal modeset through display.modeset_global_resources().
> > 
> > This isn't optimal power-wise, but it's a separate issue. I think Daniel
> > had the idea of converting the dpms callback to be a proper NULL
> > modeset. In that case too the power domains will be get/put correctly.
> 
> Right, that's what I'm getting at.  Today when someone uses the DPMS
> prop, we won't go through the mode set path and thus won't do any power
> well toggles.  I think that's a bug we should fix.  Either by making
> DPMS into a NULL mode set, or pulling out more bits from our mode set
> sequence into our crtc enable/disable paths.

Ok, I agree the DPMS prop handling should be fixed. Making it a NULL
modeset makes sense to me, X is already using that anyway for blanking
and by that we would have a single code path for both modeset and
blanking.

> My earlier code did this somewhat differently, but it did cover DPMS.

Right, checking again [1], you toggled the power around DPMS on/off. I'd
suggest that we fix this later by fixing DPMS prop as above, since it:

- keeps things simple, no need to save/restore the display HW state
during power domain off/on
- X is using a NULL modeset for blanking, so the DPMS prop handling is
less important IMO

I guess this is what you also suggested.

[1]
http://lists.freedesktop.org/archives/intel-gfx/2013-October/034584.html

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 07/19] drm/i915: add port power domains
  2014-02-17 22:02 ` [PATCH 07/19] drm/i915: add port power domains Imre Deak
  2014-02-20 19:31   ` Jesse Barnes
@ 2014-03-05 10:11   ` Daniel Vetter
  1 sibling, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:11 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 12:02:08AM +0200, Imre Deak wrote:
> Parts that poke port specific HW blocks like the encoder HW state
> readout or connector hotplug detect code need a way to check whether
> required power domains are on or enable/disable these. For this purpose
> add a set of power domains that refer to the port HW blocks. Get the
> proper port power domains during modeset.
> 
> For now when requesting the power domain for a DDI port get it for a 4
> lane configuration. This can be optimized later to request only the 2
> lane power domain, when proper support is added on the VLV PHY side for
> this. Atm, the PHY setup code assumes a 4 lane config in all cases.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>

[snip]

> +enum intel_display_power_domain
> +intel_display_port_power_domain(struct intel_encoder *intel_encoder)
>  {
> +	struct drm_device *dev = intel_encoder->base.dev;
> +	struct intel_digital_port *intel_dig_port;
> +
> +	switch (intel_encoder->type) {
> +	case INTEL_OUTPUT_UNKNOWN:
> +		/* Only DDI platforms should ever use this output type */
> +		WARN_ON_ONCE(!HAS_DDI(dev));
> +	case INTEL_OUTPUT_DISPLAYPORT:
> +	case INTEL_OUTPUT_HDMI:
> +	case INTEL_OUTPUT_EDP:
> +		intel_dig_port = enc_to_dig_port(&intel_encoder->base);
> +		switch (intel_dig_port->port) {
> +		case PORT_A:
> +			return POWER_DOMAIN_PORT_DDI_A_4_LANES;
> +		case PORT_B:
> +			return POWER_DOMAIN_PORT_DDI_B_4_LANES;
> +		case PORT_C:
> +			return POWER_DOMAIN_PORT_DDI_C_4_LANES;
> +		case PORT_D:
> +			return POWER_DOMAIN_PORT_DDI_D_4_LANES;
> +		default:
> +			WARN_ON_ONCE(1);
> +			return POWER_DOMAIN_PORT_OTHER;
> +		}
> +	case INTEL_OUTPUT_ANALOG:
> +		return POWER_DOMAIN_PORT_CRT;
> +	case INTEL_OUTPUT_DSI:
> +		return POWER_DOMAIN_PORT_DSI;
> +	default:
> +		return POWER_DOMAIN_PORT_OTHER;
> +	}
> +}

This creeps me out a bit tbh ... I guess eventually this will grow out of
bounds and we should just track all the required power domains for an
output configuration in the pipe config structure. Then crtc, encoders and
everything else can or in bits as they see fit.

Also, we need to fix the ddi code to finally keep track of it's own state
and rid us of all that OUTPUT_UNKNOWN nonsense. Iirc Damien is on the hook
for that.

All stuff for follow-ups though.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 08/19] drm/i915: get port power domain in connector detect
  2014-02-24 11:56         ` Imre Deak
@ 2014-03-05 10:15           ` Daniel Vetter
  0 siblings, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:15 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Feb 24, 2014 at 01:56:20PM +0200, Imre Deak wrote:
> On Thu, 2014-02-20 at 11:33 -0800, Jesse Barnes wrote:
> > On Wed, 19 Feb 2014 14:39:58 +0200
> > Imre Deak <imre.deak@intel.com> wrote:
> > 
> > > On Wed, 2014-02-19 at 14:35 +0200, Ville Syrjälä wrote:
> > > > On Tue, Feb 18, 2014 at 12:02:09AM +0200, Imre Deak wrote:
> > > > > The connector detect and get_mode handlers need to access the port
> > > > > specific HW blocks to read the EDID etc. Get/put the port power domains
> > > > > around these handlers.
> > > > > 
> > > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/i915/intel_crt.c | 42 ++++++++++++++++++++++++++++++++--------
> > > > >  drivers/gpu/drm/i915/intel_dp.c  | 16 ++++++++++++---
> > > > >  drivers/gpu/drm/i915/intel_dsi.c | 13 ++++++++++++-
> > > > 
> > > > And what about HDMI?
> > > 
> > > Good catch, I missed that one.
> > 
> > I wonder if we can catch bits like that using our display reg base
> > bits.  We could have a platform specific power check for each block to
> > do some basic sanity checking on whether the appropriate well was
> > enabled and squak if not.
> > 
> > I just know we'll miss this more than once, and I'm not sure if the
> > unclaimed reg stuff will save us on all platforms.
> 
> Yea, good idea. The register->power well mapping could be part of the
> platform specific power well struct and we could assert on the SW state
> of the well being 'enabled'.

We could add a (start, length) register range (or an array of such ranges)
to the power well struct and use that in our reg I/O functions for the
display range. If we don't do this for any of the registers in the
forcewake range the impact should be fairly minimal I hope ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state
  2014-02-17 22:02 ` [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state Imre Deak
  2014-02-20 19:36   ` Jesse Barnes
@ 2014-03-05 10:21   ` Daniel Vetter
  1 sibling, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:21 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 12:02:10AM +0200, Imre Deak wrote:
> Since the encoder is tied to its port, we need to make sure the power
> domain for that port is on before reading out the encoder HW state.
> 
> Signed-off-by: Imre Deak <imre.deak@intel.com>
> +bool intel_encoder_get_hw_state(struct intel_encoder *intel_encoder,
> +				enum pipe *pipe)
> +{
> +	enum intel_display_power_domain power_domain;
> +	struct drm_i915_private *dev_priv = intel_encoder->base.dev->dev_private;
> +
> +	power_domain = intel_display_port_power_domain(intel_encoder);
> +	if (!intel_display_power_enabled(dev_priv, power_domain))
> +		return false;
> +
> +	return intel_encoder->get_hw_state(intel_encoder, pipe);
> +}

Nope, these kinds of checks should be pushed down into the
encoder/platform specific callbacks imo. Like I've said in my previous
reply I'm not a fan of the port_power_domain function, knowledge about
this should be pushed out from generic code into encoder callbacks. hw
engineers are create enough imo that this will hurt us in the end if we
don't have full flexibility in the encoder specific code.

Same goes with any other relevant power well checks, imo they should be as
close to the actual hw readout code as possible (e.g. pfit, pll, ...). For
example see the platform specific power well check in
haswell_get_pipe_config.

So please replaced this patch with one which sprinkles the relevant checks
all over the place.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 10/19] drm/i915: check pipe power domain when reading its hw state
  2014-02-20 19:37   ` Jesse Barnes
@ 2014-03-05 10:24     ` Daniel Vetter
  0 siblings, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:24 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Thu, Feb 20, 2014 at 11:37:25AM -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:11 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > We can read out the pipe HW state only if the required power domain is
> > on. If not we consider the pipe to be off.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 19 +++++++++++++++----
> >  1 file changed, 15 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index ce1c00a..e3824f8 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -9535,6 +9535,18 @@ check_encoder_state(struct drm_device *dev)
> >  	}
> >  }
> >  
> > +static bool intel_display_get_pipe_config(struct intel_crtc *crtc,
> > +					  struct intel_crtc_config *pipe_config)
> > +{
> > +	struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
> > +
> > +	if (!intel_display_power_enabled(dev_priv,
> > +					 POWER_DOMAIN_PIPE(crtc->pipe)))
> > +		return false;
> > +
> > +	return dev_priv->display.get_pipe_config(crtc, pipe_config);
> > +}
> > +
> >  static void
> >  check_crtc_state(struct drm_device *dev)
> >  {
> > @@ -9572,8 +9584,7 @@ check_crtc_state(struct drm_device *dev)
> >  		     "crtc's computed enabled state doesn't match tracked enabled state "
> >  		     "(expected %i, found %i)\n", enabled, crtc->base.enabled);
> >  
> > -		active = dev_priv->display.get_pipe_config(crtc,
> > -							   &pipe_config);
> > +		active = intel_display_get_pipe_config(crtc, &pipe_config);
> >  
> >  		/* hw state is inconsistent with the pipe A quirk */
> >  		if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)
> > @@ -11328,8 +11339,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
> >  			    base.head) {
> >  		memset(&crtc->config, 0, sizeof(crtc->config));
> >  
> > -		crtc->active = dev_priv->display.get_pipe_config(crtc,
> > -								 &crtc->config);
> > +		crtc->active = intel_display_get_pipe_config(crtc,
> > +							     &crtc->config);
> >  
> >  		crtc->base.enabled = crtc->active;
> >  		crtc->primary_enabled = crtc->active;
> 
> Same comment about renaming .get_pipe_config applies here too, but I
> think you got them all in this case, so that could be done on top.
> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Same comment here - imo this should be pushed down into callbacks, since
they are the only ones precisely aware of which power domains are needed.
And by pushing it down we can group the power domain checks closely
together with the register readback code, e.g. for fine-grained stuff like
pfit or special plls.

And we already have some of these checks in the hsw get_pipe_config
function.

So nack on this approach.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 14/19] drm/i915: switch order of power domain init wrt. irq install
  2014-02-24 13:23     ` Imre Deak
@ 2014-03-05 10:29       ` Daniel Vetter
  0 siblings, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:29 UTC (permalink / raw)
  To: Imre Deak; +Cc: intel-gfx

On Mon, Feb 24, 2014 at 03:23:23PM +0200, Imre Deak wrote:
> On Thu, 2014-02-20 at 11:48 -0800, Jesse Barnes wrote:
> > On Tue, 18 Feb 2014 00:02:15 +0200
> > Imre Deak <imre.deak@intel.com> wrote:
> > 
> > > On VLV at least the display IRQ register access and functionality
> > > depends on its power well to be on, so move the power domain HW init
> > > before we install the IRQs.
> > > 
> > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/i915_dma.c | 4 ++--
> > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> > > index 8177c17..f8f7a59 100644
> > > --- a/drivers/gpu/drm/i915/i915_dma.c
> > > +++ b/drivers/gpu/drm/i915/i915_dma.c
> > > @@ -1321,12 +1321,12 @@ static int i915_load_modeset_init(struct drm_device *dev)
> > >  	if (ret)
> > >  		goto cleanup_vga_switcheroo;
> > >  
> > > +	intel_power_domains_init_hw(dev_priv);
> > > +
> > >  	ret = drm_irq_install(dev);
> > >  	if (ret)
> > >  		goto cleanup_gem_stolen;
> > >  
> > > -	intel_power_domains_init_hw(dev_priv);
> > > -
> > >  	/* Important: The output setup functions called by modeset_init need
> > >  	 * working irqs for e.g. gmbus and dp aux transfers. */
> > >  	intel_modeset_init(dev);
> > 
> > Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
> > 
> > That said, this was always one part of the PM code that confused me and
> > caused some refcounts to get messed up last time I worked on it.
> >
> > I think it would be better to not treat init specially, and let the
> > power wells get turned on and off through normal power well get/put
> > calls during init and resume.
> 
> I agree this is the ideal way and we should move towards that. Atm, we
> have intel_display_set_init_power() for init and resume which is not so
> nice, but it should do the right thing.
> 
> > It's a bit noisy, power wise, but ultimately it might make for clearer
> > code and one less special case.
> 
> Yep and also give some power saving.

I think we should have some more robust debug infrastructure before we
endeavour on this journey. E.g. some basic checks to compare register
ranges with power wells and their state like Jesse suggested earlier. Init
code is hilarious complicated and I'm pretty sure we'll miss something in
the transition to more explicitly managed power wells for init and
suspend/resume and all that code otherwise.

Merged this patch here to give the init reordering a bit of time to
settle. This stuff just blows up too often ...
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 15/19] drm/i915: use power domain api to check vga power state
  2014-02-20 19:51   ` Jesse Barnes
@ 2014-03-05 10:31     ` Daniel Vetter
  0 siblings, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:31 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Thu, Feb 20, 2014 at 11:51:33AM -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:16 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > This way we can reuse the check on other platforms too. Also factor out
> > a version of the function that doesn't check if the power is on, we'll
> > need to call this from within the power domain framework.
> > 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_drv.h      |  1 +
> >  drivers/gpu/drm/i915/intel_display.c | 20 +++++++++++++-------
> >  2 files changed, 14 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 76bd03a..632f9d8 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -2591,6 +2591,7 @@ extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
> >  extern void intel_modeset_setup_hw_state(struct drm_device *dev,
> >  					 bool force_restore);
> >  extern void i915_redisable_vga(struct drm_device *dev);
> > +extern void i915_redisable_vga_power_on(struct drm_device *dev);
> >  extern bool intel_fbc_enabled(struct drm_device *dev);
> >  extern void intel_disable_fbc(struct drm_device *dev);
> >  extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index e3824f8..ea00878 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -11304,10 +11304,20 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
> >  	 * the crtc fixup. */
> >  }
> >  
> > +void i915_redisable_vga_power_on(struct drm_device *dev)
> > +{
> > +	struct drm_i915_private *dev_priv = dev->dev_private;
> > +	u32 vga_reg = i915_vgacntrl_reg(dev);
> > +
> > +	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
> > +		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
> > +		i915_disable_vga(dev);
> > +	}
> > +}
> > +
> >  void i915_redisable_vga(struct drm_device *dev)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> > -	u32 vga_reg = i915_vgacntrl_reg(dev);
> >  
> >  	/* This function can be called both from intel_modeset_setup_hw_state or
> >  	 * at a very early point in our resume sequence, where the power well
> > @@ -11316,14 +11326,10 @@ void i915_redisable_vga(struct drm_device *dev)
> >  	 * level, just check if the power well is enabled instead of trying to
> >  	 * follow the "don't touch the power well if we don't need it" policy
> >  	 * the rest of the driver uses. */
> > -	if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) &&
> > -	    (I915_READ(HSW_PWR_WELL_DRIVER) & HSW_PWR_WELL_STATE_ENABLED) == 0)
> > +	if (!intel_display_power_enabled(dev_priv, POWER_DOMAIN_VGA))
> >  		return;
> >  
> > -	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
> > -		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
> > -		i915_disable_vga(dev);
> > -	}
> > +	i915_redisable_vga_power_on(dev);
> >  }
> >  
> >  static void intel_modeset_readout_hw_state(struct drm_device *dev)
> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Queued for -next, thanks for the patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 16/19] drm/i915: sanity check power well sw state against hw state
  2014-02-18 17:59       ` Ville Syrjälä
@ 2014-03-05 10:32         ` Daniel Vetter
  0 siblings, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:32 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, Feb 18, 2014 at 07:59:05PM +0200, Ville Syrjälä wrote:
> On Tue, Feb 18, 2014 at 07:37:01PM +0200, Imre Deak wrote:
> > On Tue, 2014-02-18 at 18:55 +0200, Ville Syrjälä wrote:
> > > On Tue, Feb 18, 2014 at 12:02:17AM +0200, Imre Deak wrote:
> > > > Suggested by Daniel.
> > > > 
> > > > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/i915/intel_pm.c | 33 ++++++++++++++++++++++++++++++---
> > > >  1 file changed, 30 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > > > index e81e7de..21ccf89 100644
> > > > --- a/drivers/gpu/drm/i915/intel_pm.c
> > > > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > > > @@ -5338,6 +5338,24 @@ static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
> > > >  	hsw_enable_package_c8(dev_priv);
> > > >  }
> > > >  
> > > > +static void check_power_well_state(struct drm_i915_private *dev_priv,
> > > > +				   struct i915_power_well *power_well)
> > > > +{
> > > > +	bool enabled;
> > > > +
> > > > +	if (!power_well->ops->is_enabled)
> > > > +		return;
> > > > +
> > > > +	enabled = power_well->ops->is_enabled(dev_priv, power_well);
> > > > +
> > > > +	if (enabled != (power_well->count > 0 || !i915.disable_power_well)) {
> > > 
> > > Doesn't i915.disable_power_well==true mean "leave power wells always
> > > enabled"? So I think the '!' needs to be removed.
> > 
> > No, i915.disable_power_well==true means disable power wells when the
> > refcount goes to 0. Perhaps not the best name/semantics for this kind of
> > option, the default for it should be 0 and mean normal operation, which
> > is to disable power wells when possible.
> 
> Oh I had the impression it was the other way around, but you're right.
> Seems I keep getting confused by this thing. It has happened before and
> I'm guessing it will happen again after I've forgotten the details
> again.

I concur that a module option rename pass is in order. Maybe once this has
all settled a bit ;-)
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 18/19] drm/i915: move hsw power domain comment to its right place
  2014-02-20 19:53   ` Jesse Barnes
@ 2014-03-05 10:34     ` Daniel Vetter
  0 siblings, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:34 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Thu, Feb 20, 2014 at 11:53:07AM -0800, Jesse Barnes wrote:
> On Tue, 18 Feb 2014 00:02:19 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > Signed-off-by: Imre Deak <imre.deak@intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c | 12 ++++++------
> >  1 file changed, 6 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index 21ccf89..68f58e5 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -5213,6 +5213,12 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
> >  	return is_enabled;
> >  }
> >  
> > +/*
> > + * 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
> > + * to be enabled, and it will only be disabled if none of the registers is
> > + * requesting it to be enabled.
> > + */
> >  static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv)
> >  {
> >  	struct drm_device *dev = dev_priv->dev;
> > @@ -5556,12 +5562,6 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
> >  	mutex_unlock(&power_domains->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
> > - * to be enabled, and it will only be disabled if none of the registers is
> > - * requesting it to be enabled.
> > - */
> >  void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
> >  {
> >  	/* For now, we need the power well to be always enabled. */
> 
> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Queued for -next, thanks for the patch.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

* Re: [PATCH 19/19] drm/i915: power domains: add vlv power wells
  2014-02-26 19:52         ` Jesse Barnes
  2014-02-27 10:03           ` Imre Deak
@ 2014-03-05 10:38           ` Daniel Vetter
  1 sibling, 0 replies; 68+ messages in thread
From: Daniel Vetter @ 2014-03-05 10:38 UTC (permalink / raw)
  To: Jesse Barnes; +Cc: intel-gfx

On Wed, Feb 26, 2014 at 11:52:25AM -0800, Jesse Barnes wrote:
> On Wed, 26 Feb 2014 20:02:19 +0200
> Imre Deak <imre.deak@intel.com> wrote:
> 
> > On Thu, 2014-02-20 at 11:58 -0800, Jesse Barnes wrote:
> > > I'd like to see the code for re-enabling the display state land
> > > eventually too, so we can get savings when userspace uses DPMS instead
> > > of NULL mode sets for things.  But to do that nicely requires some more
> > > work in the mode set code to pull out more PLL bits (also needed for
> > > atomic mode setting).
> > 
> > I guess you meant here the drm connector->funcs->dpms() callback, that's
> > called when setting the connector's dpms property. But I'm not sure what
> > you meant by re-enabling the display state.
> > 
> > I was thinking that we need to get/put the power domains around setting
> > DPMS off/on via the above property, but we actually don't need that.
> > Internally the dpms callback just calls the
> > display.disable_crtc/enable_crtc() which will disable/enable the pipes
> > but won't do anything with the power domains (which is only updated
> > during a normal modeset through display.modeset_global_resources().
> > 
> > This isn't optimal power-wise, but it's a separate issue. I think Daniel
> > had the idea of converting the dpms callback to be a proper NULL
> > modeset. In that case too the power domains will be get/put correctly.
> 
> Right, that's what I'm getting at.  Today when someone uses the DPMS
> prop, we won't go through the mode set path and thus won't do any power
> well toggles.  I think that's a bug we should fix.  Either by making
> DPMS into a NULL mode set, or pulling out more bits from our mode set
> sequence into our crtc enable/disable paths.

Yeah, I think in the end we should be able to get rid of the ->mode_set
callbacks completely and move all the remaining hw frobbing into ->enable
and all the remaining state computation (plls mostly) into
->compute_config. That way ->enable will always restore the full hw state
and so won't get screwed over when a power well switched cleared all the
registers.

With that done we can add the display power well stuff from the modeset
path to the dpms path and update so that it follows crtc->active and not
crtc->enabled.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 68+ messages in thread

end of thread, other threads:[~2014-03-05 10:38 UTC | newest]

Thread overview: 68+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-17 22:02 [PATCH 00/19] drm/i915: vlv power domains support Imre Deak
2014-02-17 22:02 ` [PATCH 01/19] drm/i915: use drm_i915_private everywhere in the power domain api Imre Deak
2014-02-20 19:16   ` Jesse Barnes
2014-02-17 22:02 ` [PATCH 02/19] drm/i915: fold in __intel_power_well_get/put functions Imre Deak
2014-02-20 19:17   ` Jesse Barnes
2014-02-20 19:44     ` Chris Wilson
2014-02-24 13:23   ` Paulo Zanoni
2014-02-24 14:07     ` Imre Deak
2014-02-17 22:02 ` [PATCH 03/19] drm/i915: move modeset_update_power_wells earlier Imre Deak
2014-02-20 19:18   ` Jesse Barnes
2014-02-17 22:02 ` [PATCH 04/19] drm/i915: move power domain macros to intel_pm.c Imre Deak
2014-02-20 19:21   ` Jesse Barnes
2014-02-24 13:38     ` Paulo Zanoni
2014-02-24 13:54       ` Imre Deak
2014-02-17 22:02 ` [PATCH 05/19] drm/i915: power domains: add power well ops Imre Deak
2014-02-20 19:26   ` Jesse Barnes
2014-02-24 11:42     ` Imre Deak
2014-02-17 22:02 ` [PATCH 06/19] drm/i915: remove power_well->always_on flag Imre Deak
2014-02-20 19:27   ` Jesse Barnes
2014-02-17 22:02 ` [PATCH 07/19] drm/i915: add port power domains Imre Deak
2014-02-20 19:31   ` Jesse Barnes
2014-02-24 11:52     ` Imre Deak
2014-03-05 10:11   ` Daniel Vetter
2014-02-17 22:02 ` [PATCH 08/19] drm/i915: get port power domain in connector detect Imre Deak
2014-02-19 12:35   ` Ville Syrjälä
2014-02-19 12:39     ` Imre Deak
2014-02-20 19:33       ` Jesse Barnes
2014-02-24 11:56         ` Imre Deak
2014-03-05 10:15           ` Daniel Vetter
2014-02-17 22:02 ` [PATCH 09/19] drm/i915: check port power domain when reading the encoder hw state Imre Deak
2014-02-20 19:36   ` Jesse Barnes
2014-02-24 12:53     ` Imre Deak
2014-03-05 10:21   ` Daniel Vetter
2014-02-17 22:02 ` [PATCH 10/19] drm/i915: check pipe power domain when reading its " Imre Deak
2014-02-20 19:37   ` Jesse Barnes
2014-03-05 10:24     ` Daniel Vetter
2014-02-17 22:02 ` [PATCH 11/19] drm/i915: vlv: keep first level vblank IRQs masked Imre Deak
2014-02-18 16:54   ` Ville Syrjälä
2014-02-17 22:02 ` [PATCH 12/19] drm/i915: sanitize PUNIT register macro definitions Imre Deak
2014-02-20 19:46   ` Jesse Barnes
2014-02-24 13:12     ` Imre Deak
2014-02-17 22:02 ` [PATCH 13/19] drm/i915: factor out reset_vblank_counter Imre Deak
2014-02-18 16:55   ` Ville Syrjälä
2014-02-17 22:02 ` [PATCH 14/19] drm/i915: switch order of power domain init wrt. irq install Imre Deak
2014-02-20 19:48   ` Jesse Barnes
2014-02-24 13:23     ` Imre Deak
2014-03-05 10:29       ` Daniel Vetter
2014-02-17 22:02 ` [PATCH 15/19] drm/i915: use power domain api to check vga power state Imre Deak
2014-02-20 19:51   ` Jesse Barnes
2014-03-05 10:31     ` Daniel Vetter
2014-02-17 22:02 ` [PATCH 16/19] drm/i915: sanity check power well sw state against hw state Imre Deak
2014-02-18 16:55   ` Ville Syrjälä
2014-02-18 17:37     ` Imre Deak
2014-02-18 17:59       ` Ville Syrjälä
2014-03-05 10:32         ` Daniel Vetter
2014-02-17 22:02 ` [PATCH 17/19] drm/i915: vlv: factor out valleyview_display_irq_install Imre Deak
2014-02-20 19:56   ` Jesse Barnes
2014-02-24 13:34     ` Imre Deak
2014-02-17 22:02 ` [PATCH 18/19] drm/i915: move hsw power domain comment to its right place Imre Deak
2014-02-20 19:53   ` Jesse Barnes
2014-03-05 10:34     ` Daniel Vetter
2014-02-17 22:02 ` [PATCH 19/19] drm/i915: power domains: add vlv power wells Imre Deak
2014-02-19 12:29   ` Ville Syrjälä
2014-02-20 19:58     ` Jesse Barnes
2014-02-26 18:02       ` Imre Deak
2014-02-26 19:52         ` Jesse Barnes
2014-02-27 10:03           ` Imre Deak
2014-03-05 10:38           ` Daniel Vetter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.