All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] drm/i915: CHV DPIO power gating, take two
@ 2015-07-08 20:45 ville.syrjala
  2015-07-08 20:45 ` [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV ville.syrjala
                   ` (15 more replies)
  0 siblings, 16 replies; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Here's the new version of the CHV DPIO powergating feature. In short,
it allows us to power off unused lanes in the display PHY. So should
save some power when stuff is either disabled, or when running DP links
with less than four lanes.

My previous attempt [1] failed to actually enable the dynamic powerdown
bits in the PHY, which meant it basically did nothing. Actually setting
those bits has a pretty big effect on the hardware as CMN/TX/PCS
registers stop working in powered down lanes. So dealing with that fact,
and several nasty corner cases makes things a bit tricky in places.

The series depends on my earlier DP pipe config cleanup [2] since we now
depend on knowing which lanes are actually powered on when
enabling/disabling DP ports.

The entire thing is availabe from my github repo [3] where it's
sitting on a few other patches, including my earlier DPLL cleanup
series [4]. However there should be no real dependency on this other
stuff apart from the already mentioned DP pipe config patches (which are
also included in the branch).

Deepak, perchance you would be willing to review this since you already
reviwed my first attempt (and shot it full of holes)?

Oh, and the first two patches aren't really about DPIO powergating. But
I wanted to get them out and one of them does touch the same code so
I figured I'd sneak them in.

[1] http://lists.freedesktop.org/archives/intel-gfx/2015-April/064403.html
[2] http://lists.freedesktop.org/archives/intel-gfx/2015-July/070780.html
[3] git://github.com/vsyrjala/linux.git chv_dpio_powergating_4
[4] http://lists.freedesktop.org/archives/intel-gfx/2015-June/070036.html

Ville Syrjälä (15):
  drm/i915: Always program m2 fractional value on CHV
  drm/i915: Always program unique transition scale for CHV
  drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock
    buffer disables there
  drm/i915: Move DPIO port init earlier
  drm/i915: Add locking around chv_phy_control_init()
  drm/i915: Move VLV/CHV prepare_pll later
  drm/i915: Add vlv_dport_to_phy()
  drm/i915: Implement PHY lane power gating for CHV
  drm/i915: Trick CL2 into life on CHV when using pipe B with port B
  drm/i915: Force common lane on for the PPS kick on CHV
  drm/i915: Enable DPIO SUS clock gating on CHV
  drm/i915: Force CL2 off in CHV x1 PHY
  drm/i915: Clean up CHV lane soft reset programming
  drm/i915: Add some CHV DPIO lane power state asserts
  drm/i915: Add CHV PHY LDO power sanity checks

 drivers/gpu/drm/i915/i915_dma.c         |  20 ++
 drivers/gpu/drm/i915/i915_reg.h         |  23 +++
 drivers/gpu/drm/i915/intel_display.c    |  54 +----
 drivers/gpu/drm/i915/intel_dp.c         | 315 +++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_drv.h        |  26 ++-
 drivers/gpu/drm/i915/intel_hdmi.c       | 171 +++++++++++-----
 drivers/gpu/drm/i915/intel_runtime_pm.c | 344 +++++++++++++++++++++++++++++---
 7 files changed, 721 insertions(+), 232 deletions(-)

-- 
2.3.6

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

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

* [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-17  2:19   ` Deepak
  2015-07-08 20:45 ` [PATCH 02/15] drm/i915: Always program unique transition scale for CHV ville.syrjala
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

When fractional m2 divider isn't used on CHV the fractional part
is ignore by the hardware. Despite that, program the fractional
value (0 in this case) to the hardware register just to keep
things a bit more consistent. Might at least make register dumps
a bit less confusing when there isn't some stale fractional part
hanging around.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0b2ad76..3df9cb2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7393,8 +7393,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
 			1 << DPIO_CHV_N_DIV_SHIFT);
 
 	/* M2 fraction division */
-	if (bestm2_frac)
-		vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
+	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
 
 	/* M2 fraction division enable */
 	dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
-- 
2.3.6

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

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

* [PATCH 02/15] drm/i915: Always program unique transition scale for CHV
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
  2015-07-08 20:45 ` [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-17  2:31   ` Deepak
  2015-07-08 20:45 ` [PATCH 03/15] drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there ville.syrjala
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

The docs give you the impression that the unique transition scale
value shouldn't matter when unique transition scale is enabled. But
as Imre found on BXT (and I verfied also on BSW) the value does
matter. So from now on just program the same value 0x9a always.

Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   | 53 +++++++++++++++++++--------------------
 drivers/gpu/drm/i915/intel_hdmi.c | 30 +++++++++++-----------
 2 files changed, 42 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f424833..32d7e43 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3142,6 +3142,12 @@ static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)
 	return 0;
 }
 
+static bool chv_need_uniq_trans_scale(uint8_t train_set)
+{
+	return (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) == DP_TRAIN_PRE_EMPH_LEVEL_0 &&
+		(train_set & DP_TRAIN_VOLTAGE_SWING_MASK) == DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
+}
+
 static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -3260,41 +3266,34 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
 	/* Program swing margin */
 	for (i = 0; i < 4; i++) {
 		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
+
 		val &= ~DPIO_SWING_MARGIN000_MASK;
 		val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT;
+
+		/*
+		 * Supposedly this value shouldn't matter when unique transition
+		 * scale is disabled, but in fact it does matter. Let's just
+		 * always program the same value and hope it's OK.
+		 */
+		val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
+		val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT;
+
 		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
 	}
 
-	/* Disable unique transition scale */
+	/*
+	 * The document said it needs to set bit 27 for ch0 and bit 26
+	 * for ch1. Might be a typo in the doc.
+	 * For now, for this unique transition scale selection, set bit
+	 * 27 for ch0 and ch1.
+	 */
 	for (i = 0; i < 4; i++) {
 		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
-		val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
-		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
-	}
-
-	if (((train_set & DP_TRAIN_PRE_EMPHASIS_MASK)
-			== DP_TRAIN_PRE_EMPH_LEVEL_0) &&
-		((train_set & DP_TRAIN_VOLTAGE_SWING_MASK)
-			== DP_TRAIN_VOLTAGE_SWING_LEVEL_3)) {
-
-		/*
-		 * The document said it needs to set bit 27 for ch0 and bit 26
-		 * for ch1. Might be a typo in the doc.
-		 * For now, for this unique transition scale selection, set bit
-		 * 27 for ch0 and ch1.
-		 */
-		for (i = 0; i < 4; i++) {
-			val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
+		if (chv_need_uniq_trans_scale(train_set))
 			val |= DPIO_TX_UNIQ_TRANS_SCALE_EN;
-			vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
-		}
-
-		for (i = 0; i < 4; i++) {
-			val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
-			val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
-			val |= (0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT);
-			vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
-		}
+		else
+			val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
+		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
 	}
 
 	/* Start swing calculation */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index ba845f7..9f79afb 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1846,31 +1846,33 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
 
 	for (i = 0; i < 4; i++) {
 		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
+
 		val &= ~DPIO_SWING_MARGIN000_MASK;
 		val |= 102 << DPIO_SWING_MARGIN000_SHIFT;
+
+		/*
+		 * Supposedly this value shouldn't matter when unique transition
+		 * scale is disabled, but in fact it does matter. Let's just
+		 * always program the same value and hope it's OK.
+		 */
+		val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
+		val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT;
+
 		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
 	}
 
-	/* Disable unique transition scale */
+	/*
+	 * The document said it needs to set bit 27 for ch0 and bit 26
+	 * for ch1. Might be a typo in the doc.
+	 * For now, for this unique transition scale selection, set bit
+	 * 27 for ch0 and ch1.
+	 */
 	for (i = 0; i < 4; i++) {
 		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
 		val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
 		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
 	}
 
-	/* Additional steps for 1200mV-0dB */
-#if 0
-	val = vlv_dpio_read(dev_priv, pipe, VLV_TX_DW3(ch));
-	if (ch)
-		val |= DPIO_TX_UNIQ_TRANS_SCALE_CH1;
-	else
-		val |= DPIO_TX_UNIQ_TRANS_SCALE_CH0;
-	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(ch), val);
-
-	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(ch),
-			vlv_dpio_read(dev_priv, pipe, VLV_TX_DW2(ch)) |
-				(0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT));
-#endif
 	/* Start swing calculation */
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
 	val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
-- 
2.3.6

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

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

* [PATCH 03/15] drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
  2015-07-08 20:45 ` [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV ville.syrjala
  2015-07-08 20:45 ` [PATCH 02/15] drm/i915: Always program unique transition scale for CHV ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-17  4:16   ` Deepak
  2015-07-08 20:45 ` [PATCH 04/15] drm/i915: Move DPIO port init earlier ville.syrjala
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move the CHV clock buffer disable from chv_disable_pll() to the new
encoder .post_pll_disable() hook. This is more symmetric since the
clock buffer enable happens from the .pre_pll_enable() hook.

We'll have more use for the new hook soon.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 15 ++++-----------
 drivers/gpu/drm/i915/intel_dp.c      | 23 +++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |  1 +
 drivers/gpu/drm/i915/intel_hdmi.c    | 23 +++++++++++++++++++++++
 4 files changed, 51 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3df9cb2..db518a7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1851,17 +1851,6 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
 	val &= ~DPIO_DCLKP_EN;
 	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
 
-	/* disable left/right clock distribution */
-	if (pipe != PIPE_B) {
-		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
-		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
-		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
-	} else {
-		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
-		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
-		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
-	}
-
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
@@ -6171,6 +6160,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 			i9xx_disable_pll(intel_crtc);
 	}
 
+	for_each_encoder_on_crtc(dev, crtc, encoder)
+		if (encoder->post_pll_disable)
+			encoder->post_pll_disable(encoder);
+
 	if (!IS_GEN2(dev))
 		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
 }
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 32d7e43..40b8430 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2906,6 +2906,28 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
+static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
+	u32 val;
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	/* disable left/right clock distribution */
+	if (pipe != PIPE_B) {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+	} else {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+	}
+
+	mutex_unlock(&dev_priv->sb_lock);
+}
+
 /*
  * Native read with retry for link status and receiver capability reads for
  * cases where the sink may still be asleep.
@@ -5931,6 +5953,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 		intel_encoder->pre_enable = chv_pre_enable_dp;
 		intel_encoder->enable = vlv_enable_dp;
 		intel_encoder->post_disable = chv_post_disable_dp;
+		intel_encoder->post_pll_disable = chv_dp_post_pll_disable;
 	} else if (IS_VALLEYVIEW(dev)) {
 		intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
 		intel_encoder->pre_enable = vlv_pre_enable_dp;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 4f3b708..42fa135 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -148,6 +148,7 @@ struct intel_encoder {
 	void (*mode_set)(struct intel_encoder *intel_encoder);
 	void (*disable)(struct intel_encoder *);
 	void (*post_disable)(struct intel_encoder *);
+	void (*post_pll_disable)(struct intel_encoder *);
 	/* Read out the current hw state of this connector, returning true if
 	 * the encoder is active. If the encoder is enabled it also set the pipe
 	 * it is connected to in the pipe parameter. */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 9f79afb..86b1a2c 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1678,6 +1678,28 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
+static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
+	u32 val;
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	/* disable left/right clock distribution */
+	if (pipe != PIPE_B) {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
+		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
+	} else {
+		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
+		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
+	}
+
+	mutex_unlock(&dev_priv->sb_lock);
+}
+
 static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
 {
 	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
@@ -2073,6 +2095,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
 		intel_encoder->pre_enable = chv_hdmi_pre_enable;
 		intel_encoder->enable = vlv_enable_hdmi;
 		intel_encoder->post_disable = chv_hdmi_post_disable;
+		intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable;
 	} else if (IS_VALLEYVIEW(dev)) {
 		intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
 		intel_encoder->pre_enable = vlv_hdmi_pre_enable;
-- 
2.3.6

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

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

* [PATCH 04/15] drm/i915: Move DPIO port init earlier
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (2 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 03/15] drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-17  4:18   ` Deepak
  2015-07-08 20:45 ` [PATCH 05/15] drm/i915: Add locking around chv_phy_control_init() ville.syrjala
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

To implement DPIO lane power gating on CHV we're going to need to access
DPIO registers from the cmn power well enable hook. That gets called
rather early, so we need to move the DPIO port IOSF sideband port
assignment earlier as well.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_dma.c      | 20 ++++++++++++++++++++
 drivers/gpu/drm/i915/intel_display.c | 22 ----------------------
 2 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 5e63076..3e9e98a 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -783,6 +783,24 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
 			 info->has_eu_pg ? "y" : "n");
 }
 
+static void intel_init_dpio(struct drm_i915_private *dev_priv)
+{
+	if (!IS_VALLEYVIEW(dev_priv))
+		return;
+
+	/*
+	 * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
+	 * CHV x1 PHY (DP/HDMI D)
+	 * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
+	 */
+	if (IS_CHERRYVIEW(dev_priv)) {
+		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
+		DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
+	} else {
+		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
+	}
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -983,6 +1001,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	intel_device_info_runtime_init(dev);
 
+	intel_init_dpio(dev_priv);
+
 	if (INTEL_INFO(dev)->num_pipes) {
 		ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
 		if (ret)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index db518a7..0473b38 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1590,26 +1590,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
 	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID);
 }
 
-static void intel_init_dpio(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (!IS_VALLEYVIEW(dev))
-		return;
-
-	/*
-	 * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
-	 * CHV x1 PHY (DP/HDMI D)
-	 * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
-	 */
-	if (IS_CHERRYVIEW(dev)) {
-		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
-		DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
-	} else {
-		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
-	}
-}
-
 static void vlv_enable_pll(struct intel_crtc *crtc,
 			   const struct intel_crtc_state *pipe_config)
 {
@@ -15049,8 +15029,6 @@ void intel_modeset_init(struct drm_device *dev)
 		}
 	}
 
-	intel_init_dpio(dev);
-
 	intel_shared_dpll_init(dev);
 
 	/* Just disable it once at startup */
-- 
2.3.6

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

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

* [PATCH 05/15] drm/i915: Add locking around chv_phy_control_init()
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (3 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 04/15] drm/i915: Move DPIO port init earlier ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-17  4:23   ` Deepak
  2015-07-08 20:45 ` [PATCH 06/15] drm/i915: Move VLV/CHV prepare_pll later ville.syrjala
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

dev_priv->chv_phy_control is protected by the power_domains->lock
elsewhere, so also grab it when initializing chv_phy_control.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_runtime_pm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 2142ae6..dab1da9 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -1678,7 +1678,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
 	power_domains->initializing = true;
 
 	if (IS_CHERRYVIEW(dev)) {
+		mutex_lock(&power_domains->lock);
 		chv_phy_control_init(dev_priv);
+		mutex_unlock(&power_domains->lock);
 	} else if (IS_VALLEYVIEW(dev)) {
 		mutex_lock(&power_domains->lock);
 		vlv_cmnlane_wa(dev_priv);
-- 
2.3.6

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

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

* [PATCH 06/15] drm/i915: Move VLV/CHV prepare_pll later
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (4 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 05/15] drm/i915: Add locking around chv_phy_control_init() ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-17  4:36   ` Deepak
  2015-08-17  4:39   ` Deepak
  2015-07-08 20:45 ` [PATCH 07/15] drm/i915: Add vlv_dport_to_phy() ville.syrjala
                   ` (9 subsequent siblings)
  15 siblings, 2 replies; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

With DPIO powergating active on CHV, we can't even access the DPIO PLL
registers until the lane power state overrides have been enabled. That
will happen from the encoder .pre_pll_enable() hook, so move
chv_prepare_pll() to happen after that point, which puts it just before
chv_enable_pll() actually.

Do the same for VLV to avoid accumulating weird differences between the
platforms. Both platforms seem happy with the new arrangement.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_display.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0473b38..666a236 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5979,13 +5979,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 
 	is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
 
-	if (!is_dsi) {
-		if (IS_CHERRYVIEW(dev))
-			chv_prepare_pll(intel_crtc, intel_crtc->config);
-		else
-			vlv_prepare_pll(intel_crtc, intel_crtc->config);
-	}
-
 	if (intel_crtc->config->has_dp_encoder)
 		intel_dp_set_m_n(intel_crtc, M1_N1);
 
@@ -6009,10 +6002,13 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
 			encoder->pre_pll_enable(encoder);
 
 	if (!is_dsi) {
-		if (IS_CHERRYVIEW(dev))
+		if (IS_CHERRYVIEW(dev)) {
+			chv_prepare_pll(intel_crtc, intel_crtc->config);
 			chv_enable_pll(intel_crtc, intel_crtc->config);
-		else
+		} else {
+			vlv_prepare_pll(intel_crtc, intel_crtc->config);
 			vlv_enable_pll(intel_crtc, intel_crtc->config);
+		}
 	}
 
 	for_each_encoder_on_crtc(dev, crtc, encoder)
-- 
2.3.6

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

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

* [PATCH 07/15] drm/i915: Add vlv_dport_to_phy()
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (5 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 06/15] drm/i915: Move VLV/CHV prepare_pll later ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-17  4:56   ` Deepak
  2015-08-26  8:24   ` Daniel Vetter
  2015-07-08 20:45 ` [PATCH 08/15] drm/i915: Implement PHY lane power gating for CHV ville.syrjala
                   ` (8 subsequent siblings)
  15 siblings, 2 replies; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add vlv_dport_to_phy() and fix up the return values of
vlv_dport_to_channel() and vlv_pipe_to_channel() to use
the appropriate enums.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_drv.h | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 42fa135..23d5e46 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -791,7 +791,7 @@ struct intel_dp_mst_encoder {
 	void *port; /* store this opaque as its illegal to dereference it */
 };
 
-static inline int
+static inline enum dpio_channel
 vlv_dport_to_channel(struct intel_digital_port *dport)
 {
 	switch (dport->port) {
@@ -805,7 +805,21 @@ vlv_dport_to_channel(struct intel_digital_port *dport)
 	}
 }
 
-static inline int
+static inline enum dpio_phy
+vlv_dport_to_phy(struct intel_digital_port *dport)
+{
+	switch (dport->port) {
+	case PORT_B:
+	case PORT_C:
+		return DPIO_PHY0;
+	case PORT_D:
+		return DPIO_PHY1;
+	default:
+		BUG();
+	}
+}
+
+static inline enum dpio_channel
 vlv_pipe_to_channel(enum pipe pipe)
 {
 	switch (pipe) {
-- 
2.3.6

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

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

* [PATCH 08/15] drm/i915: Implement PHY lane power gating for CHV
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (6 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 07/15] drm/i915: Add vlv_dport_to_phy() ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-19  1:48   ` Deepak
  2015-08-26  8:27   ` Daniel Vetter
  2015-07-08 20:45 ` [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B ville.syrjala
                   ` (7 subsequent siblings)
  15 siblings, 2 replies; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Powergate the PHY lanes when they're not needed. For HDMI all four lanes
are needed always, but for DP we can enable only the needed lanes. To
power down the unused lanes we use some power down override bits in the
DISPLAY_PHY_CONTROL register. Without the overrides it appears that the
hardware always powers on all the lanes. When the port is disabled the
power down override is not needed and the lanes will shut off on their
own. That also means the override is critical to actually be able to
access the DPIO registers before the port is actually enabled.

Additionally the common lanes will power down when not needed. CL1
remains on as long as anything else is on, CL2 will shut down when
all the lanes in the same channel will shut down. There is one exception
for CL2 that will be dealt in a separate patch for clarity.

With potentially some lanes powered down, the DP code now has to check
the number of active lanes before accessing PCS/TX registers. All
registers in powered down blocks will reads as 0xffffffff, and soe we
would drown in warnings from vlv_dpio_read() if we allowed the code
to access all those registers.

Another important detail in the DP code is the "TX latency optimal"
setting. Normally the second TX lane acts as some kind of reset master,
with the other lanes as slaves. But when only a single lane is enabled,
that single lane obviously has to be the master.

A bit of extra care is needed to reconstruct the initial state of the
DISPLAY_PHY_CONTROL register since it can't be read safely. So instead
read the actual lane status from the DPLL/PHY_STATUS registers and
use that to determine which lanes ought to be powergated initially.

We also need to switch the PHY power modes to "deep PSR" to avoid
a hard system hang when powering down the single channel PHY.

Also sprinkle a few debug prints around so that we can monitor the
DISPLAY_PHY_STATUS changes without having to read it and risk
corrupting it.

v2: Add locking to chv_powergate_phy_lanes()
v3: Actually enable dynamic powerdown in the PHY and deal with the
    fallout

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h         |   8 ++
 drivers/gpu/drm/i915/intel_dp.c         | 141 +++++++++++++++++++++-----------
 drivers/gpu/drm/i915/intel_drv.h        |   4 +
 drivers/gpu/drm/i915/intel_hdmi.c       |   4 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 123 ++++++++++++++++++++++++++--
 5 files changed, 221 insertions(+), 59 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 17cb7e5..bcfcbb62 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1125,9 +1125,15 @@ enum skl_disp_power_wells {
 
 #define _CHV_CMN_DW19_CH0		0x814c
 #define _CHV_CMN_DW6_CH1		0x8098
+#define   DPIO_DYNPWRDOWNEN_CH1		(1 << 28) /* CL2 DW6 only */
 #define   CHV_CMN_USEDCLKCHANNEL	(1 << 13)
+
 #define CHV_CMN_DW19(ch) _PIPE(ch, _CHV_CMN_DW19_CH0, _CHV_CMN_DW6_CH1)
 
+#define CHV_CMN_DW28			0x8170
+#define   DPIO_CL1POWERDOWNEN		(1 << 23)
+#define   DPIO_DYNPWRDOWNEN_CH0		(1 << 22)
+
 #define CHV_CMN_DW30			0x8178
 #define   DPIO_LRC_BYPASS		(1 << 3)
 
@@ -2175,10 +2181,12 @@ enum skl_disp_power_wells {
 #define DPIO_PHY_STATUS			(VLV_DISPLAY_BASE + 0x6240)
 #define   DPLL_PORTD_READY_MASK		(0xf)
 #define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100)
+#define   PHY_CH_POWER_DOWN_OVRD_EN(phy, ch)	(1 << (2*(phy)+(ch)+27))
 #define   PHY_LDO_DELAY_0NS			0x0
 #define   PHY_LDO_DELAY_200NS			0x1
 #define   PHY_LDO_DELAY_600NS			0x2
 #define   PHY_LDO_SEQ_DELAY(delay, phy)		((delay) << (2*(phy)+23))
+#define   PHY_CH_POWER_DOWN_OVRD(mask, phy, ch)	((mask) << (8*(phy)+4*(ch)+11))
 #define   PHY_CH_SU_PSR				0x1
 #define   PHY_CH_DEEP_PSR			0x7
 #define   PHY_CH_POWER_MODE(mode, phy, ch)	((mode) << (6*(phy)+3*(ch)+2))
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 40b8430..6058129 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -133,6 +133,11 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp);
 static void vlv_steal_power_sequencer(struct drm_device *dev,
 				      enum pipe pipe);
 
+static unsigned int intel_dp_unused_lane_mask(int lane_count)
+{
+	return ~((1 << lane_count) - 1) & 0xf;
+}
+
 static int
 intel_dp_max_link_bw(struct intel_dp  *intel_dp)
 {
@@ -2395,17 +2400,21 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)
 	val |= CHV_PCS_REQ_SOFTRESET_EN;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
+		val |= CHV_PCS_REQ_SOFTRESET_EN;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+	}
 
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
 	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	}
 
 	mutex_unlock(&dev_priv->sb_lock);
 }
@@ -2525,7 +2534,6 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
 	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
-	unsigned int lane_mask = 0x0;
 
 	if (WARN_ON(dp_reg & DP_PORT_EN))
 		return;
@@ -2543,9 +2551,15 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 
 	pps_unlock(intel_dp);
 
-	if (IS_VALLEYVIEW(dev))
+	if (IS_VALLEYVIEW(dev)) {
+		unsigned int lane_mask = 0x0;
+
+		if (IS_CHERRYVIEW(dev))
+			lane_mask = intel_dp_unused_lane_mask(crtc->config->lane_count);
+
 		vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp),
 				    lane_mask);
+	}
 
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_start_link_train(intel_dp);
@@ -2772,31 +2786,40 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
-	val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
+		val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+	}
 
 	/* Deassert soft data lane reset*/
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
 	val |= CHV_PCS_REQ_SOFTRESET_EN;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
+		val |= CHV_PCS_REQ_SOFTRESET_EN;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+	}
 
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
 	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+		val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	}
 
 	/* Program Tx lane latency optimal setting*/
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < intel_crtc->config->lane_count; i++) {
 		/* Set the upar bit */
-		data = (i == 1) ? 0x0 : 0x1;
+		if (intel_crtc->config->lane_count == 1)
+			data = 0x0;
+		else
+			data = (i == 1) ? 0x0 : 0x1;
 		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW14(ch, i),
 				data << DPIO_UPAR_SHIFT);
 	}
@@ -2817,9 +2840,11 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	val |= DPIO_TX2_STAGGER_MASK(0x1f);
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
-	val |= DPIO_TX2_STAGGER_MASK(0x1f);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
+		val |= DPIO_TX2_STAGGER_MASK(0x1f);
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
+	}
 
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch),
 		       DPIO_LANESTAGGER_STRAP(stagger) |
@@ -2828,12 +2853,14 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 		       DPIO_TX1_STAGGER_MULT(6) |
 		       DPIO_TX2_STAGGER_MULT(0));
 
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch),
-		       DPIO_LANESTAGGER_STRAP(stagger) |
-		       DPIO_LANESTAGGER_STRAP_OVRD |
-		       DPIO_TX1_STAGGER_MASK(0x1f) |
-		       DPIO_TX1_STAGGER_MULT(7) |
-		       DPIO_TX2_STAGGER_MULT(5));
+	if (intel_crtc->config->lane_count > 2) {
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch),
+			       DPIO_LANESTAGGER_STRAP(stagger) |
+			       DPIO_LANESTAGGER_STRAP_OVRD |
+			       DPIO_TX1_STAGGER_MASK(0x1f) |
+			       DPIO_TX1_STAGGER_MULT(7) |
+			       DPIO_TX2_STAGGER_MULT(5));
+	}
 
 	mutex_unlock(&dev_priv->sb_lock);
 
@@ -2849,10 +2876,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
 		to_intel_crtc(encoder->base.crtc);
 	enum dpio_channel ch = vlv_dport_to_channel(dport);
 	enum pipe pipe = intel_crtc->pipe;
+	unsigned int lane_mask =
+		intel_dp_unused_lane_mask(intel_crtc->config->lane_count);
 	u32 val;
 
 	intel_dp_prepare(encoder);
 
+	chv_phy_powergate_lanes(encoder, true, lane_mask);
+
 	mutex_lock(&dev_priv->sb_lock);
 
 	/* program left/right clock distribution */
@@ -2883,13 +2914,15 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
 		val |= CHV_PCS_USEDCLKCHANNEL;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
-	val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
-	if (pipe != PIPE_B)
-		val &= ~CHV_PCS_USEDCLKCHANNEL;
-	else
-		val |= CHV_PCS_USEDCLKCHANNEL;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
+		val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
+		if (pipe != PIPE_B)
+			val &= ~CHV_PCS_USEDCLKCHANNEL;
+		else
+			val |= CHV_PCS_USEDCLKCHANNEL;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
+	}
 
 	/*
 	 * This a a bit weird since generally CL
@@ -2926,6 +2959,8 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
 	}
 
 	mutex_unlock(&dev_priv->sb_lock);
+
+	chv_phy_powergate_lanes(encoder, false, 0x0);
 }
 
 /*
@@ -3261,24 +3296,28 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
 	val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
-	val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
-	val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
-	val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
+		val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
+		val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
+		val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
+	}
 
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch));
 	val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
 	val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch));
-	val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
-	val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch));
+		val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
+		val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val);
+	}
 
 	/* Program swing deemph */
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < intel_crtc->config->lane_count; i++) {
 		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW4(ch, i));
 		val &= ~DPIO_SWING_DEEMPH9P5_MASK;
 		val |= deemph_reg_value << DPIO_SWING_DEEMPH9P5_SHIFT;
@@ -3286,7 +3325,7 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
 	}
 
 	/* Program swing margin */
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < intel_crtc->config->lane_count; i++) {
 		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
 
 		val &= ~DPIO_SWING_MARGIN000_MASK;
@@ -3309,7 +3348,7 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
 	 * For now, for this unique transition scale selection, set bit
 	 * 27 for ch0 and ch1.
 	 */
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < intel_crtc->config->lane_count; i++) {
 		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
 		if (chv_need_uniq_trans_scale(train_set))
 			val |= DPIO_TX_UNIQ_TRANS_SCALE_EN;
@@ -3323,9 +3362,11 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
 	val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val);
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
-	val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
+	if (intel_crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
+		val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
+	}
 
 	/* LRC Bypass */
 	val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 23d5e46..f8a16dc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1370,6 +1370,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
 
 void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
 
+void chv_phy_powergate_lanes(struct intel_encoder *encoder,
+			     bool override, unsigned int mask);
+
+
 /* intel_pm.c */
 void intel_init_clock_gating(struct drm_device *dev);
 void intel_suspend_hw(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 86b1a2c..b3f6c9f 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1625,6 +1625,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 
 	intel_hdmi_prepare(encoder);
 
+	chv_phy_powergate_lanes(encoder, true, 0x0);
+
 	mutex_lock(&dev_priv->sb_lock);
 
 	/* program left/right clock distribution */
@@ -1698,6 +1700,8 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
 	}
 
 	mutex_unlock(&dev_priv->sb_lock);
+
+	chv_phy_powergate_lanes(encoder, false, 0x0);
 }
 
 static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index dab1da9..506a8cc 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -946,14 +946,19 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 					   struct i915_power_well *power_well)
 {
 	enum dpio_phy phy;
+	enum pipe pipe;
+	uint32_t tmp;
 
 	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
 		     power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
 
-	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC)
+	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+		pipe = PIPE_A;
 		phy = DPIO_PHY0;
-	else
+	} else {
+		pipe = PIPE_C;
 		phy = DPIO_PHY1;
+	}
 
 	/* since ref/cri clock was enabled */
 	udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
@@ -963,8 +968,26 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 	if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
 		DRM_ERROR("Display PHY %d is not power up\n", phy);
 
+	mutex_lock(&dev_priv->sb_lock);
+
+	/* Enable dynamic power down */
+	tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28);
+	tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN;
+	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
+
+	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
+		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
+		tmp |= DPIO_DYNPWRDOWNEN_CH1;
+		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
+	}
+
+	mutex_unlock(&dev_priv->sb_lock);
+
 	dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
 	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
+
+	DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
+		      phy, dev_priv->chv_phy_control);
 }
 
 static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
@@ -988,6 +1011,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
 	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
 
 	vlv_set_power_well(dev_priv, power_well, false);
+
+	DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
+		      phy, dev_priv->chv_phy_control);
+}
+
+void chv_phy_powergate_lanes(struct intel_encoder *encoder,
+			     bool override, unsigned int mask)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	enum dpio_phy phy = vlv_dport_to_phy(enc_to_dig_port(&encoder->base));
+	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+
+	mutex_lock(&power_domains->lock);
+
+	dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD(0xf, phy, ch);
+	dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD(mask, phy, ch);
+
+	if (override)
+		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+	else
+		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+
+	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
+
+	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
+		      phy, ch, mask, dev_priv->chv_phy_control);
+
+	mutex_unlock(&power_domains->lock);
 }
 
 static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
@@ -1620,19 +1672,72 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
 	 * DISPLAY_PHY_CONTROL can get corrupted if read. As a
 	 * workaround never ever read DISPLAY_PHY_CONTROL, and
 	 * instead maintain a shadow copy ourselves. Use the actual
-	 * power well state to reconstruct the expected initial
-	 * value.
+	 * power well state and lane status to reconstruct the
+	 * expected initial value.
 	 */
 	dev_priv->chv_phy_control =
 		PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY0) |
 		PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY1) |
-		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH0) |
-		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH1) |
-		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY1, DPIO_CH0);
-	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc))
+		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH0) |
+		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH1) |
+		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY1, DPIO_CH0);
+
+	/*
+	 * If all lanes are disabled we leave the override disabled
+	 * with all power down bits cleared to match the state we
+	 * would use after disabling the port. Otherwise enable the
+	 * override and set the lane powerdown bits accding to the
+	 * current lane status.
+	 */
+	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
+		uint32_t status = I915_READ(DPLL(PIPE_A));
+		unsigned int mask;
+
+		mask = status & DPLL_PORTB_READY_MASK;
+		if (mask == 0xf)
+			mask = 0x0;
+		else
+			dev_priv->chv_phy_control |=
+				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0);
+
+		dev_priv->chv_phy_control |=
+			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH0);
+
+		mask = (status & DPLL_PORTC_READY_MASK) >> 4;
+		if (mask == 0xf)
+			mask = 0x0;
+		else
+			dev_priv->chv_phy_control |=
+				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1);
+
+		dev_priv->chv_phy_control |=
+			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1);
+
 		dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0);
-	if (cmn_d->ops->is_enabled(dev_priv, cmn_d))
+	}
+
+	if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
+		uint32_t status = I915_READ(DPIO_PHY_STATUS);
+		unsigned int mask;
+
+		mask = status & DPLL_PORTD_READY_MASK;
+
+		if (mask == 0xf)
+			mask = 0x0;
+		else
+			dev_priv->chv_phy_control |=
+				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0);
+
+		dev_priv->chv_phy_control |=
+			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0);
+
 		dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1);
+	}
+
+	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
+
+	DRM_DEBUG_KMS("Initial PHY_CONTROL=0x%08x\n",
+		      dev_priv->chv_phy_control);
 }
 
 static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
-- 
2.3.6

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

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

* [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (7 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 08/15] drm/i915: Implement PHY lane power gating for CHV ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-19  2:17   ` Deepak
  2015-07-08 20:45 ` [PATCH 10/15] drm/i915: Force common lane on for the PPS kick on CHV ville.syrjala
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Normmally the common lane in a PHY channel gets powered up when some
of the data lanes get powered up. But when we're driving port B with
pipe B we don't want to enabled any of the data lanes, and just want
the DPLL in the common lane to be active.

To make that happens we have to temporarily enable some data lanes
after which we can access the DPLL registers in the common lane. Once
the pipe is up and running we can drop the power override on the data
lanes allowing them to shut down. From this point forward the common
lane will in fact stay powered on until the data lanes in the other
channel get powered down.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c         | 23 +++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h        |  3 +++
 drivers/gpu/drm/i915/intel_hdmi.c       | 23 +++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++++++++++++
 4 files changed, 78 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6058129..8d088f3 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2865,6 +2865,12 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->sb_lock);
 
 	intel_enable_dp(encoder);
+
+	/* Second common lane will stay alive on its own now */
+	if (dport->release_cl2_override) {
+		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
+		dport->release_cl2_override = false;
+	}
 }
 
 static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
@@ -2882,6 +2888,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
 
 	intel_dp_prepare(encoder);
 
+	/*
+	 * Must trick the second common lane into life.
+	 * Otherwise we can't even access the PLL.
+	 */
+	if (ch == DPIO_CH0 && pipe == PIPE_B)
+		dport->release_cl2_override =
+			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
+
 	chv_phy_powergate_lanes(encoder, true, lane_mask);
 
 	mutex_lock(&dev_priv->sb_lock);
@@ -2960,6 +2974,15 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
 
 	mutex_unlock(&dev_priv->sb_lock);
 
+	/*
+	 * Leave the power down bit cleared for at least one
+	 * lane so that chv_powergate_phy_ch() will power
+	 * on something when the channel is otherwise unused.
+	 * When the port is off and the override is removed
+	 * the lanes power down anyway, so otherwise it doesn't
+	 * really matter what the state of power down bits is
+	 * after this.
+	 */
 	chv_phy_powergate_lanes(encoder, false, 0x0);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f8a16dc..6133a98 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -782,6 +782,7 @@ struct intel_digital_port {
 	struct intel_dp dp;
 	struct intel_hdmi hdmi;
 	enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
+	bool release_cl2_override;
 };
 
 struct intel_dp_mst_encoder {
@@ -1372,6 +1373,8 @@ void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
 
 void chv_phy_powergate_lanes(struct intel_encoder *encoder,
 			     bool override, unsigned int mask);
+bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+			  enum dpio_channel ch, bool override);
 
 
 /* intel_pm.c */
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index b3f6c9f..4b604ee 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1625,6 +1625,14 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 
 	intel_hdmi_prepare(encoder);
 
+	/*
+	 * Must trick the second common lane into life.
+	 * Otherwise we can't even access the PLL.
+	 */
+	if (ch == DPIO_CH0 && pipe == PIPE_B)
+		dport->release_cl2_override =
+			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
+
 	chv_phy_powergate_lanes(encoder, true, 0x0);
 
 	mutex_lock(&dev_priv->sb_lock);
@@ -1701,6 +1709,15 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
 
 	mutex_unlock(&dev_priv->sb_lock);
 
+	/*
+	 * Leave the power down bit cleared for at least one
+	 * lane so that chv_powergate_phy_ch() will power
+	 * on something when the channel is otherwise unused.
+	 * When the port is off and the override is removed
+	 * the lanes power down anyway, so otherwise it doesn't
+	 * really matter what the state of power down bits is
+	 * after this.
+	 */
 	chv_phy_powergate_lanes(encoder, false, 0x0);
 }
 
@@ -1922,6 +1939,12 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
 	g4x_enable_hdmi(encoder);
 
 	vlv_wait_port_ready(dev_priv, dport, 0x0);
+
+	/* Second common lane will stay alive on its own now */
+	if (dport->release_cl2_override) {
+		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
+		dport->release_cl2_override = false;
+	}
 }
 
 static void intel_hdmi_destroy(struct drm_connector *connector)
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 506a8cc..551cf08 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -1016,6 +1016,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
 		      phy, dev_priv->chv_phy_control);
 }
 
+bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+			  enum dpio_channel ch, bool override)
+{
+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	bool was_override;
+
+	mutex_lock(&power_domains->lock);
+
+	was_override = dev_priv->chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+
+	if (override == was_override)
+		goto out;
+
+	if (override)
+		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+	else
+		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
+
+	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
+
+	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
+		      phy, ch, dev_priv->chv_phy_control);
+
+out:
+	mutex_unlock(&power_domains->lock);
+
+	return was_override;
+}
+
 void chv_phy_powergate_lanes(struct intel_encoder *encoder,
 			     bool override, unsigned int mask)
 {
-- 
2.3.6

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

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

* [PATCH 10/15] drm/i915: Force common lane on for the PPS kick on CHV
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (8 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-07-10  7:56   ` [PATCH v2 " ville.syrjala
  2015-08-19  2:21   ` [PATCH " Deepak
  2015-07-08 20:45 ` [PATCH 11/15] drm/i915: Enable DPIO SUS clock gating " ville.syrjala
                   ` (5 subsequent siblings)
  15 siblings, 2 replies; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

With DPIO powergating active the DPLL can't be accessed unless
something else is keeping the common lane in the channel on.
That means the PPS kick procedure could fail to enable the PLL.

Power up some data lanes to force the common lane to power up
so that the PLL can be enabled temporarily.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8d088f3..817df87 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -341,7 +341,9 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum pipe pipe = intel_dp->pps_pipe;
-	bool pll_enabled;
+	bool pll_enabled, release_cl_override;
+	enum dpio_phy phy = DPIO_PHY(pipe);
+	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
 	uint32_t DP;
 
 	if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,
@@ -371,9 +373,13 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 	 * The DPLL for the pipe must be enabled for this to work.
 	 * So enable temporarily it if it's not already enabled.
 	 */
-	if (!pll_enabled)
+	if (!pll_enabled) {
+		release_cl_override = IS_CHERRYVIEW(dev) &&
+			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
+
 		vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
 				 &chv_dpll[0].dpll : &vlv_dpll[0].dpll);
+	}
 
 	/*
 	 * Similar magic as in intel_dp_enable_port().
@@ -390,8 +396,12 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
 	POSTING_READ(intel_dp->output_reg);
 
-	if (!pll_enabled)
+	if (!pll_enabled) {
 		vlv_force_pll_off(dev, pipe);
+
+		if (release_cl_override)
+			chv_phy_powergate_ch(dev_priv, phy, ch, false);
+	}
 }
 
 static enum pipe
-- 
2.3.6

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

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

* [PATCH 11/15] drm/i915: Enable DPIO SUS clock gating on CHV
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (9 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 10/15] drm/i915: Force common lane on for the PPS kick on CHV ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-19 13:09   ` Deepak
  2015-07-08 20:45 ` [PATCH 12/15] drm/i915: Force CL2 off in CHV x1 PHY ville.syrjala
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

CHV has supports some form of automagic clock gating for the
DPIO SUS clock. We can simply enable the magic bits and the
hardware should take care of the rest.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h         | 4 ++++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 3 ++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index bcfcbb62..8010200 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1133,6 +1133,10 @@ enum skl_disp_power_wells {
 #define CHV_CMN_DW28			0x8170
 #define   DPIO_CL1POWERDOWNEN		(1 << 23)
 #define   DPIO_DYNPWRDOWNEN_CH0		(1 << 22)
+#define   DPIO_SUS_CLK_CONFIG_ON		(0 << 0)
+#define   DPIO_SUS_CLK_CONFIG_CLKREQ		(1 << 0)
+#define   DPIO_SUS_CLK_CONFIG_GATE		(2 << 0)
+#define   DPIO_SUS_CLK_CONFIG_GATE_CLKREQ	(3 << 0)
 
 #define CHV_CMN_DW30			0x8178
 #define   DPIO_LRC_BYPASS		(1 << 3)
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 551cf08..37e4375 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -972,7 +972,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 
 	/* Enable dynamic power down */
 	tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28);
-	tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN;
+	tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN |
+		DPIO_SUS_CLK_CONFIG_GATE_CLKREQ;
 	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
 
 	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
-- 
2.3.6

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

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

* [PATCH 12/15] drm/i915: Force CL2 off in CHV x1 PHY
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (10 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 11/15] drm/i915: Enable DPIO SUS clock gating " ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-08-19 13:22   ` Deepak
  2015-07-08 20:45 ` [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming ville.syrjala
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We can choose to leave the display PHY CL2 powerdown up to some hardware
signals, or we can force it. The BXT code forces the nonexistent CL2 in
the x1 PHY to power down. Follow suit on CHV. Maybe it can still save
some extra power by disabling some extra logic in CL1, or something.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h         | 1 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 9 +++++++++
 2 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8010200..395f556 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1139,6 +1139,7 @@ enum skl_disp_power_wells {
 #define   DPIO_SUS_CLK_CONFIG_GATE_CLKREQ	(3 << 0)
 
 #define CHV_CMN_DW30			0x8178
+#define   DPIO_CL2_LDOFUSE_PWRENB	(1 << 6)
 #define   DPIO_LRC_BYPASS		(1 << 3)
 
 #define _TXLANE(ch, lane, offset) ((ch ? 0x2400 : 0) + \
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 37e4375..002b78f 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -980,6 +980,15 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
 		tmp |= DPIO_DYNPWRDOWNEN_CH1;
 		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
+	} else {
+		/*
+		 * Force the non-existing CL2 off. BXT does this
+		 * too, so maybe it saves some power even though
+		 * CL2 doesn't exist?
+		 */
+		tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
+		tmp |= DPIO_CL2_LDOFUSE_PWRENB;
+		vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, tmp);
 	}
 
 	mutex_unlock(&dev_priv->sb_lock);
-- 
2.3.6

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

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

* [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (11 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 12/15] drm/i915: Force CL2 off in CHV x1 PHY ville.syrjala
@ 2015-07-08 20:45 ` ville.syrjala
  2015-07-09 16:27   ` Daniel Vetter
                     ` (2 more replies)
  2015-07-08 20:46 ` [PATCH 14/15] drm/i915: Add some CHV DPIO lane power state asserts ville.syrjala
                   ` (2 subsequent siblings)
  15 siblings, 3 replies; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:45 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently we relesar the lane soft reset before lane stagger settings
have been programmed. I believe that means we don't actually do lane
staggering. So move the soft reset deassert to happen after lane
staggering has been programmed.

The one confusing thing in this is that when we remove the power down
override from the lanes, they power up with defaul register values,
which do not have the soft reset overrides enabled. And according to
some docs by default the data lane resets are tied to cmnreset. So that
would mean that lanes would come out of reset without staggering as
soon as the power down overrides are removed. But sine we can't access
either the lane stagger register nor the soft reset override registers
until the lanes are powered on, we can really do anything about it.
So let's just set the soft reset overrides as soon as the lane is
powered on and hope for the best.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   | 91 +++++++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_hdmi.c | 91 ++++++++++++++++++++++-----------------
 2 files changed, 100 insertions(+), 82 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 817df87..297bd14 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2389,42 +2389,62 @@ static void vlv_post_disable_dp(struct intel_encoder *encoder)
 	intel_dp_link_down(intel_dp);
 }
 
-static void chv_post_disable_dp(struct intel_encoder *encoder)
+static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+				     bool reset)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
-	struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = encoder->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc =
-		to_intel_crtc(encoder->base.crtc);
-	enum dpio_channel ch = vlv_dport_to_channel(dport);
-	enum pipe pipe = intel_crtc->pipe;
-	u32 val;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	enum pipe pipe = crtc->pipe;
+	uint32_t val;
 
-	intel_dp_link_down(intel_dp);
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
+	if (reset)
+		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+	else
+		val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
 
-	mutex_lock(&dev_priv->sb_lock);
+	if (crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+		if (reset)
+			val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+		else
+			val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	}
 
-	/* Propagate soft reset to data lane reset */
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
 	val |= CHV_PCS_REQ_SOFTRESET_EN;
+	if (reset)
+		val &= ~DPIO_PCS_CLK_SOFT_RESET;
+	else
+		val |= DPIO_PCS_CLK_SOFT_RESET;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
 
-	if (intel_crtc->config->lane_count > 2) {
+	if (crtc->config->lane_count > 2) {
 		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
 		val |= CHV_PCS_REQ_SOFTRESET_EN;
+		if (reset)
+			val &= ~DPIO_PCS_CLK_SOFT_RESET;
+		else
+			val |= DPIO_PCS_CLK_SOFT_RESET;
 		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
 	}
+}
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
+static void chv_post_disable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (intel_crtc->config->lane_count > 2) {
-		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-	}
+	intel_dp_link_down(intel_dp);
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	/* Assert data lane reset */
+	chv_data_lane_soft_reset(encoder, true);
 
 	mutex_unlock(&dev_priv->sb_lock);
 }
@@ -2802,27 +2822,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
 	}
 
-	/* Deassert soft data lane reset*/
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-	if (intel_crtc->config->lane_count > 2) {
-		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-		val |= CHV_PCS_REQ_SOFTRESET_EN;
-		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-	}
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-	if (intel_crtc->config->lane_count > 2) {
-		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-		val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-	}
-
 	/* Program Tx lane latency optimal setting*/
 	for (i = 0; i < intel_crtc->config->lane_count; i++) {
 		/* Set the upar bit */
@@ -2872,6 +2871,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 			       DPIO_TX2_STAGGER_MULT(5));
 	}
 
+	/* Deassert data lane reset */
+	chv_data_lane_soft_reset(encoder, false);
+
 	mutex_unlock(&dev_priv->sb_lock);
 
 	intel_enable_dp(encoder);
@@ -2910,6 +2912,9 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
 
 	mutex_lock(&dev_priv->sb_lock);
 
+	/* Assert data lane reset */
+	chv_data_lane_soft_reset(encoder, true);
+
 	/* program left/right clock distribution */
 	if (pipe != PIPE_B) {
 		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 4b604ee..176d681 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1612,6 +1612,50 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
+static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+				     bool reset)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	enum pipe pipe = crtc->pipe;
+	uint32_t val;
+
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
+	if (reset)
+		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+	else
+		val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
+
+	if (crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+		if (reset)
+			val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+		else
+			val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	}
+
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
+	val |= CHV_PCS_REQ_SOFTRESET_EN;
+	if (reset)
+		val &= ~DPIO_PCS_CLK_SOFT_RESET;
+	else
+		val |= DPIO_PCS_CLK_SOFT_RESET;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
+
+	if (crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
+		val |= CHV_PCS_REQ_SOFTRESET_EN;
+		if (reset)
+			val &= ~DPIO_PCS_CLK_SOFT_RESET;
+		else
+			val |= DPIO_PCS_CLK_SOFT_RESET;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+	}
+}
+
 static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 {
 	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
@@ -1637,6 +1681,9 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 
 	mutex_lock(&dev_priv->sb_lock);
 
+	/* Assert data lane reset */
+	chv_data_lane_soft_reset(encoder, true);
+
 	/* program left/right clock distribution */
 	if (pipe != PIPE_B) {
 		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
@@ -1739,33 +1786,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
 
 static void chv_hdmi_post_disable(struct intel_encoder *encoder)
 {
-	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc =
-		to_intel_crtc(encoder->base.crtc);
-	enum dpio_channel ch = vlv_dport_to_channel(dport);
-	enum pipe pipe = intel_crtc->pipe;
-	u32 val;
 
 	mutex_lock(&dev_priv->sb_lock);
 
-	/* Propagate soft reset to data lane reset */
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	/* Assert data lane reset */
+	chv_data_lane_soft_reset(encoder, true);
 
 	mutex_unlock(&dev_priv->sb_lock);
 }
@@ -1796,23 +1823,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
 	val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
 
-	/* Deassert soft data lane reset*/
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-
 	/* Program Tx latency optimal setting */
 	for (i = 0; i < 4; i++) {
 		/* Set the upar bit */
@@ -1855,6 +1865,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
 		       DPIO_TX1_STAGGER_MULT(7) |
 		       DPIO_TX2_STAGGER_MULT(5));
 
+	/* Deassert data lane reset */
+	chv_data_lane_soft_reset(encoder, false);
+
 	/* Clear calc init */
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
 	val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
-- 
2.3.6

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

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

* [PATCH 14/15] drm/i915: Add some CHV DPIO lane power state asserts
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (12 preceding siblings ...)
  2015-07-08 20:45 ` [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming ville.syrjala
@ 2015-07-08 20:46 ` ville.syrjala
  2015-08-27  4:36   ` Deepak
  2015-07-08 20:46 ` [PATCH 15/15] drm/i915: Add CHV PHY LDO power sanity checks ville.syrjala
  2015-07-09 13:24 ` [PATCH 00/15] drm/i915: CHV DPIO power gating, take two Deepak
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:46 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Add some checks that the state of the DPIO lanes is more or less what we
expect based on the overrides.

The hardware only provides two bits per channel indicating whether all
or some of the lanes are powered down, so we can't do an exact check.

Additionally, CL2 powering down before we can check it adds another
twist. To work around this we simply check for the 0 value of the
CL2 register (which is what we get when it's powered down) and
adjust our expectations.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h         |  8 +++++
 drivers/gpu/drm/i915/intel_runtime_pm.c | 54 +++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 395f556..586a0f7 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1089,6 +1089,12 @@ enum skl_disp_power_wells {
 #define  DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE	1 /* 1: coarse & 0 : fine  */
 #define CHV_PLL_DW9(ch) _PIPE(ch, _CHV_PLL_DW9_CH0, _CHV_PLL_DW9_CH1)
 
+#define _CHV_CMN_DW0_CH0               0x8100
+#define   DPIO_ALLDL_POWERDOWN_SHIFT_CH0	19
+#define   DPIO_ANYDL_POWERDOWN_SHIFT_CH0	18
+#define   DPIO_ALLDL_POWERDOWN			(1 << 1)
+#define   DPIO_ANYDL_POWERDOWN			(1 << 0)
+
 #define _CHV_CMN_DW5_CH0               0x8114
 #define   CHV_BUFRIGHTENA1_DISABLE	(0 << 20)
 #define   CHV_BUFRIGHTENA1_NORMAL	(1 << 20)
@@ -1125,6 +1131,8 @@ enum skl_disp_power_wells {
 
 #define _CHV_CMN_DW19_CH0		0x814c
 #define _CHV_CMN_DW6_CH1		0x8098
+#define   DPIO_ALLDL_POWERDOWN_SHIFT_CH1	30 /* CL2 DW6 only */
+#define   DPIO_ANYDL_POWERDOWN_SHIFT_CH1	29 /* CL2 DW6 only */
 #define   DPIO_DYNPWRDOWNEN_CH1		(1 << 28) /* CL2 DW6 only */
 #define   CHV_CMN_USEDCLKCHANNEL	(1 << 13)
 
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 002b78f..a1d9676 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -1026,6 +1026,58 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
 		      phy, dev_priv->chv_phy_control);
 }
 
+static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
+				     enum dpio_channel ch, bool override, unsigned int mask)
+{
+	enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C;
+	u32 reg, val, expected, actual;
+
+	if (ch == DPIO_CH0)
+		reg = _CHV_CMN_DW0_CH0;
+	else
+		reg = _CHV_CMN_DW6_CH1;
+
+	mutex_lock(&dev_priv->sb_lock);
+	val = vlv_dpio_read(dev_priv, pipe, reg);
+	mutex_unlock(&dev_priv->sb_lock);
+
+	/*
+	 * This assumes !override is only used when the port is disabled.
+	 * All lanes should power down even without the override when
+	 * the port is disabled.
+	 */
+	if (!override || mask == 0xf) {
+		expected = DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
+		/*
+		 * If CH1 common lane is not active anymore
+		 * (eg. for pipe B DPLL) the entire channel will
+		 * shut down, which causes the common lane registers
+		 * to read as 0. That means we can't actually check
+		 * the lane power down status bits, but as the entire
+		 * register reads as 0 it's a good indication that the
+		 * channel is indeed entirely powered down.
+		 */
+		if (ch == DPIO_CH1 && val == 0)
+			expected = 0;
+	} else if (mask != 0x0) {
+		expected = DPIO_ANYDL_POWERDOWN;
+	} else {
+		expected = 0;
+	}
+
+	if (ch == DPIO_CH0)
+		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH0;
+	else
+		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH1;
+	actual &= DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
+
+	WARN(actual != expected,
+	     "Unexpected DPIO lane power down: all %d, any %d. Expected: all %d, any %d. (0x%x = 0x%08x)\n",
+	     !!(actual & DPIO_ALLDL_POWERDOWN), !!(actual & DPIO_ANYDL_POWERDOWN),
+	     !!(expected & DPIO_ALLDL_POWERDOWN), !!(expected & DPIO_ANYDL_POWERDOWN),
+	     reg, val);
+}
+
 bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
 			  enum dpio_channel ch, bool override)
 {
@@ -1078,6 +1130,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
 	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
 		      phy, ch, mask, dev_priv->chv_phy_control);
 
+	assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
+
 	mutex_unlock(&power_domains->lock);
 }
 
-- 
2.3.6

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

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

* [PATCH 15/15] drm/i915: Add CHV PHY LDO power sanity checks
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (13 preceding siblings ...)
  2015-07-08 20:46 ` [PATCH 14/15] drm/i915: Add some CHV DPIO lane power state asserts ville.syrjala
@ 2015-07-08 20:46 ` ville.syrjala
  2015-08-27  4:39   ` Deepak
  2015-07-09 13:24 ` [PATCH 00/15] drm/i915: CHV DPIO power gating, take two Deepak
  15 siblings, 1 reply; 50+ messages in thread
From: ville.syrjala @ 2015-07-08 20:46 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S, deepak.s

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

At various points when changing the DPIO lane/phy power states,
construct an expected value of the DISPLAY_PHY_STATUS register
and compare it with the real thing.

To construct the expected value we look at our shadow PHY_CONTROL
register value (which should match what we've just written to the
hardware), and we also need to look at the actual state of the cmn
power wells as a disabled power well causes the relevant LDO status
to be reported as 'on' in DISPLAY_PHY_STATUS.

When initially powering up the PHY it performs various internal
calibrations for which it fully powers up. That means that if we check
for the expetected power state immediately upon releasing cmnreset we
would get the occasional false positive. But we can of course
poll until the expected value appears. It shouldn't be too long so
this shouldn't make modesets substantially longer.

One extra complication is introduced when we cross the streams, ie.
drive port B with pipe B. In this case we trick CL2 (where the DPLL lives)
into life by temporaily powering up the lanes in the second channel,
and once the pipe is up and runnign we release the lane power override.
At that point the power state of CL2 has somehow gotten entangled with
the power state of the first channel. That means that constructing the
expected DISPLAY_PHY_STATUS value is a bit tricky since based on the
lane power states in the second channel, CL2 should also be powered
down. But we can use the DPLL enable bit to determine when CL2 should
be alive even if the lanes are powered down. However the power state
of CL2 isn't actually tied in with the DPLL state, but to the state
of the lanes in first channel, so we have to avoid checking the
expected state between shutting down the DPLL and powering down
the lanes in the first channel. So no calling assert_chv_phy_status()
before the DISPLAY_PHY_CONTROL write in chv_phy_powergate_lanes(),
but after the write is a safe time to check.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h         |   2 +
 drivers/gpu/drm/i915/intel_runtime_pm.c | 126 +++++++++++++++++++++++++++-----
 2 files changed, 111 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 586a0f7..429105e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2206,6 +2206,8 @@ enum skl_disp_power_wells {
 #define   PHY_COM_LANE_RESET_DEASSERT(phy)	(1 << (phy))
 #define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104)
 #define   PHY_POWERGOOD(phy)	(((phy) == DPIO_PHY0) ? (1<<31) : (1<<30))
+#define   PHY_STATUS_CMN_LDO(phy, ch)                   (1 << (6-(6*(phy)+3*(ch))))
+#define   PHY_STATUS_SPLINE_LDO(phy, ch, spline)        (1 << (8-(6*(phy)+3*(ch)+(spline))))
 
 /*
  * The i830 generation, in LVDS mode, defines P1 as the bit number set within
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index a1d9676..e6f1b4ee 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -942,6 +942,107 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
 	vlv_set_power_well(dev_priv, power_well, false);
 }
 
+#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
+
+static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
+						 int power_well_id)
+{
+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
+	struct i915_power_well *power_well;
+	int i;
+
+	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
+		if (power_well->data == power_well_id)
+			return power_well;
+	}
+
+	return NULL;
+}
+
+#define BITS_SET(val, bits) (((val) & (bits)) == (bits))
+
+static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
+{
+	struct i915_power_well *cmn_bc =
+		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
+	struct i915_power_well *cmn_d =
+		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
+	u32 phy_control = dev_priv->chv_phy_control;
+	u32 phy_status = 0;
+	u32 tmp;
+
+	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
+		phy_status |= PHY_POWERGOOD(DPIO_PHY0);
+
+		/* this assumes override is only used to enable lanes */
+		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0)) == 0)
+			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0);
+
+		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1)) == 0)
+			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1);
+
+		/* CL1 is on whenever anything is on in either channel */
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0) |
+			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)))
+			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0);
+
+		/*
+		 * The DPLLB check accounts for the pipe B + port A usage
+		 * with CL2 powered up but all the lanes in the second channel
+		 * powered down.
+		 */
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)) &&
+		    (I915_READ(DPLL(PIPE_B)) & DPLL_VCO_ENABLE) == 0)
+			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1);
+
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH0)))
+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0);
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH0)))
+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1);
+
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH1)))
+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0);
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH1)))
+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1);
+	}
+
+	if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
+		phy_status |= PHY_POWERGOOD(DPIO_PHY1);
+
+		/* this assumes override is only used to enable lanes */
+		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0)) == 0)
+			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0);
+
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0)))
+			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0);
+
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY1, DPIO_CH0)))
+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0);
+		if (BITS_SET(phy_control,
+			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY1, DPIO_CH0)))
+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1);
+	}
+
+	/*
+	 * The PHY may be busy with some initial calibration and whatnot,
+	 * so the power state can take a while to actually change.
+	 */
+	if (wait_for((tmp = I915_READ(DISPLAY_PHY_STATUS)) == phy_status, 10))
+		WARN(phy_status != tmp,
+		     "Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n",
+		     tmp, phy_status, dev_priv->chv_phy_control);
+}
+
+#undef BITS_SET
+
 static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 					   struct i915_power_well *power_well)
 {
@@ -998,6 +1099,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
 
 	DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
 		      phy, dev_priv->chv_phy_control);
+
+	assert_chv_phy_status(dev_priv);
 }
 
 static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
@@ -1024,6 +1127,8 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
 
 	DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
 		      phy, dev_priv->chv_phy_control);
+
+	assert_chv_phy_status(dev_priv);
 }
 
 static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
@@ -1101,6 +1206,8 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
 	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
 		      phy, ch, dev_priv->chv_phy_control);
 
+	assert_chv_phy_status(dev_priv);
+
 out:
 	mutex_unlock(&power_domains->lock);
 
@@ -1130,6 +1237,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
 	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
 		      phy, ch, mask, dev_priv->chv_phy_control);
 
+	assert_chv_phy_status(dev_priv);
+
 	assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
 
 	mutex_unlock(&power_domains->lock);
@@ -1302,8 +1411,6 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
 	intel_runtime_pm_put(dev_priv);
 }
 
-#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) |		\
@@ -1565,21 +1672,6 @@ static struct i915_power_well chv_power_wells[] = {
 	},
 };
 
-static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
-						 int power_well_id)
-{
-	struct i915_power_domains *power_domains = &dev_priv->power_domains;
-	struct i915_power_well *power_well;
-	int i;
-
-	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
-		if (power_well->data == power_well_id)
-			return power_well;
-	}
-
-	return NULL;
-}
-
 bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
 				    int power_well_id)
 {
-- 
2.3.6

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

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

* Re: [PATCH 00/15] drm/i915: CHV DPIO power gating, take two
  2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
                   ` (14 preceding siblings ...)
  2015-07-08 20:46 ` [PATCH 15/15] drm/i915: Add CHV PHY LDO power sanity checks ville.syrjala
@ 2015-07-09 13:24 ` Deepak
  15 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-07-09 13:24 UTC (permalink / raw)
  To: intel-gfx



On Thursday 09 July 2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Here's the new version of the CHV DPIO powergating feature. In short,
> it allows us to power off unused lanes in the display PHY. So should
> save some power when stuff is either disabled, or when running DP links
> with less than four lanes.
>
> My previous attempt [1] failed to actually enable the dynamic powerdown
> bits in the PHY, which meant it basically did nothing. Actually setting
> those bits has a pretty big effect on the hardware as CMN/TX/PCS
> registers stop working in powered down lanes. So dealing with that fact,
> and several nasty corner cases makes things a bit tricky in places.
>
> The series depends on my earlier DP pipe config cleanup [2] since we now
> depend on knowing which lanes are actually powered on when
> enabling/disabling DP ports.
>
> The entire thing is availabe from my github repo [3] where it's
> sitting on a few other patches, including my earlier DPLL cleanup
> series [4]. However there should be no real dependency on this other
> stuff apart from the already mentioned DP pipe config patches (which are
> also included in the branch).
>
> Deepak, perchance you would be willing to review this since you already
> reviwed my first attempt (and shot it full of holes)?

Sure. I will review the patches :)

> Oh, and the first two patches aren't really about DPIO powergating. But
> I wanted to get them out and one of them does touch the same code so
> I figured I'd sneak them in.
>
> [1] http://lists.freedesktop.org/archives/intel-gfx/2015-April/064403.html
> [2] http://lists.freedesktop.org/archives/intel-gfx/2015-July/070780.html
> [3] git://github.com/vsyrjala/linux.git chv_dpio_powergating_4
> [4] http://lists.freedesktop.org/archives/intel-gfx/2015-June/070036.html
>
> Ville Syrjälä (15):
>    drm/i915: Always program m2 fractional value on CHV
>    drm/i915: Always program unique transition scale for CHV
>    drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock
>      buffer disables there
>    drm/i915: Move DPIO port init earlier
>    drm/i915: Add locking around chv_phy_control_init()
>    drm/i915: Move VLV/CHV prepare_pll later
>    drm/i915: Add vlv_dport_to_phy()
>    drm/i915: Implement PHY lane power gating for CHV
>    drm/i915: Trick CL2 into life on CHV when using pipe B with port B
>    drm/i915: Force common lane on for the PPS kick on CHV
>    drm/i915: Enable DPIO SUS clock gating on CHV
>    drm/i915: Force CL2 off in CHV x1 PHY
>    drm/i915: Clean up CHV lane soft reset programming
>    drm/i915: Add some CHV DPIO lane power state asserts
>    drm/i915: Add CHV PHY LDO power sanity checks
>
>   drivers/gpu/drm/i915/i915_dma.c         |  20 ++
>   drivers/gpu/drm/i915/i915_reg.h         |  23 +++
>   drivers/gpu/drm/i915/intel_display.c    |  54 +----
>   drivers/gpu/drm/i915/intel_dp.c         | 315 +++++++++++++++++++----------
>   drivers/gpu/drm/i915/intel_drv.h        |  26 ++-
>   drivers/gpu/drm/i915/intel_hdmi.c       | 171 +++++++++++-----
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 344 +++++++++++++++++++++++++++++---
>   7 files changed, 721 insertions(+), 232 deletions(-)
>

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

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

* Re: [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming
  2015-07-08 20:45 ` [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming ville.syrjala
@ 2015-07-09 16:27   ` Daniel Vetter
  2015-07-09 17:14   ` [PATCH v2 " ville.syrjala
  2015-08-27  4:25   ` [PATCH " Deepak
  2 siblings, 0 replies; 50+ messages in thread
From: Daniel Vetter @ 2015-07-09 16:27 UTC (permalink / raw)
  To: ville.syrjala; +Cc: DeepakS, deepak.s, intel-gfx

On Wed, Jul 08, 2015 at 11:45:59PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Currently we relesar the lane soft reset before lane stagger settings
               release

> have been programmed. I believe that means we don't actually do lane
> staggering. So move the soft reset deassert to happen after lane
> staggering has been programmed.
> 
> The one confusing thing in this is that when we remove the power down
> override from the lanes, they power up with defaul register values,
> which do not have the soft reset overrides enabled. And according to
> some docs by default the data lane resets are tied to cmnreset. So that
> would mean that lanes would come out of reset without staggering as
> soon as the power down overrides are removed. But sine we can't access
> either the lane stagger register nor the soft reset override registers
> until the lanes are powered on, we can really do anything about it.
                                     can't?

> So let's just set the soft reset overrides as soon as the lane is
> powered on and hope for the best.

Fun story in these patches ...
-Daniel

> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c   | 91 +++++++++++++++++++++------------------
>  drivers/gpu/drm/i915/intel_hdmi.c | 91 ++++++++++++++++++++++-----------------
>  2 files changed, 100 insertions(+), 82 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 817df87..297bd14 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2389,42 +2389,62 @@ static void vlv_post_disable_dp(struct intel_encoder *encoder)
>  	intel_dp_link_down(intel_dp);
>  }
>  
> -static void chv_post_disable_dp(struct intel_encoder *encoder)
> +static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
> +				     bool reset)
>  {
> -	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> -	struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
> -	struct drm_device *dev = encoder->base.dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_crtc *intel_crtc =
> -		to_intel_crtc(encoder->base.crtc);
> -	enum dpio_channel ch = vlv_dport_to_channel(dport);
> -	enum pipe pipe = intel_crtc->pipe;
> -	u32 val;
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
> +	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
> +	enum pipe pipe = crtc->pipe;
> +	uint32_t val;
>  
> -	intel_dp_link_down(intel_dp);
> +	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> +	if (reset)
> +		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +	else
> +		val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
> +	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
>  
> -	mutex_lock(&dev_priv->sb_lock);
> +	if (crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> +		if (reset)
> +			val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +		else
> +			val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	}
>  
> -	/* Propagate soft reset to data lane reset */
>  	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
>  	val |= CHV_PCS_REQ_SOFTRESET_EN;
> +	if (reset)
> +		val &= ~DPIO_PCS_CLK_SOFT_RESET;
> +	else
> +		val |= DPIO_PCS_CLK_SOFT_RESET;
>  	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
>  
> -	if (intel_crtc->config->lane_count > 2) {
> +	if (crtc->config->lane_count > 2) {
>  		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
>  		val |= CHV_PCS_REQ_SOFTRESET_EN;
> +		if (reset)
> +			val &= ~DPIO_PCS_CLK_SOFT_RESET;
> +		else
> +			val |= DPIO_PCS_CLK_SOFT_RESET;
>  		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
>  	}
> +}
>  
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> -	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> +static void chv_post_disable_dp(struct intel_encoder *encoder)
> +{
> +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	if (intel_crtc->config->lane_count > 2) {
> -		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> -	}
> +	intel_dp_link_down(intel_dp);
> +
> +	mutex_lock(&dev_priv->sb_lock);
> +
> +	/* Assert data lane reset */
> +	chv_data_lane_soft_reset(encoder, true);
>  
>  	mutex_unlock(&dev_priv->sb_lock);
>  }
> @@ -2802,27 +2822,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>  		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
>  	}
>  
> -	/* Deassert soft data lane reset*/
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
> -
> -	if (intel_crtc->config->lane_count > 2) {
> -		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> -		val |= CHV_PCS_REQ_SOFTRESET_EN;
> -		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> -	}
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> -	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> -
> -	if (intel_crtc->config->lane_count > 2) {
> -		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -		val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> -	}
> -
>  	/* Program Tx lane latency optimal setting*/
>  	for (i = 0; i < intel_crtc->config->lane_count; i++) {
>  		/* Set the upar bit */
> @@ -2872,6 +2871,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>  			       DPIO_TX2_STAGGER_MULT(5));
>  	}
>  
> +	/* Deassert data lane reset */
> +	chv_data_lane_soft_reset(encoder, false);
> +
>  	mutex_unlock(&dev_priv->sb_lock);
>  
>  	intel_enable_dp(encoder);
> @@ -2910,6 +2912,9 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
>  
>  	mutex_lock(&dev_priv->sb_lock);
>  
> +	/* Assert data lane reset */
> +	chv_data_lane_soft_reset(encoder, true);
> +
>  	/* program left/right clock distribution */
>  	if (pipe != PIPE_B) {
>  		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 4b604ee..176d681 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1612,6 +1612,50 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>  	mutex_unlock(&dev_priv->sb_lock);
>  }
>  
> +static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
> +				     bool reset)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
> +	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
> +	enum pipe pipe = crtc->pipe;
> +	uint32_t val;
> +
> +	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> +	if (reset)
> +		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +	else
> +		val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
> +	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> +
> +	if (crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> +		if (reset)
> +			val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +		else
> +			val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	}
> +
> +	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
> +	val |= CHV_PCS_REQ_SOFTRESET_EN;
> +	if (reset)
> +		val &= ~DPIO_PCS_CLK_SOFT_RESET;
> +	else
> +		val |= DPIO_PCS_CLK_SOFT_RESET;
> +	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
> +
> +	if (crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> +		val |= CHV_PCS_REQ_SOFTRESET_EN;
> +		if (reset)
> +			val &= ~DPIO_PCS_CLK_SOFT_RESET;
> +		else
> +			val |= DPIO_PCS_CLK_SOFT_RESET;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> +	}
> +}
> +
>  static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>  {
>  	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
> @@ -1637,6 +1681,9 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>  
>  	mutex_lock(&dev_priv->sb_lock);
>  
> +	/* Assert data lane reset */
> +	chv_data_lane_soft_reset(encoder, true);
> +
>  	/* program left/right clock distribution */
>  	if (pipe != PIPE_B) {
>  		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> @@ -1739,33 +1786,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
>  
>  static void chv_hdmi_post_disable(struct intel_encoder *encoder)
>  {
> -	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
>  	struct drm_device *dev = encoder->base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_crtc *intel_crtc =
> -		to_intel_crtc(encoder->base.crtc);
> -	enum dpio_channel ch = vlv_dport_to_channel(dport);
> -	enum pipe pipe = intel_crtc->pipe;
> -	u32 val;
>  
>  	mutex_lock(&dev_priv->sb_lock);
>  
> -	/* Propagate soft reset to data lane reset */
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> -	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	/* Assert data lane reset */
> +	chv_data_lane_soft_reset(encoder, true);
>  
>  	mutex_unlock(&dev_priv->sb_lock);
>  }
> @@ -1796,23 +1823,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
>  	val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
>  	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
>  
> -	/* Deassert soft data lane reset*/
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> -	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> -
>  	/* Program Tx latency optimal setting */
>  	for (i = 0; i < 4; i++) {
>  		/* Set the upar bit */
> @@ -1855,6 +1865,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
>  		       DPIO_TX1_STAGGER_MULT(7) |
>  		       DPIO_TX2_STAGGER_MULT(5));
>  
> +	/* Deassert data lane reset */
> +	chv_data_lane_soft_reset(encoder, false);
> +
>  	/* Clear calc init */
>  	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
>  	val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
> -- 
> 2.3.6
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* [PATCH v2 13/15] drm/i915: Clean up CHV lane soft reset programming
  2015-07-08 20:45 ` [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming ville.syrjala
  2015-07-09 16:27   ` Daniel Vetter
@ 2015-07-09 17:14   ` ville.syrjala
  2015-08-27  4:25   ` [PATCH " Deepak
  2 siblings, 0 replies; 50+ messages in thread
From: ville.syrjala @ 2015-07-09 17:14 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently we release the lane soft reset before lane stagger settings
have been programmed. I believe that means we don't actually do lane
staggering. So move the soft reset deassert to happen after lane
staggering has been programmed.

The one confusing thing in this is that when we remove the power down
override from the lanes, they power up with defaul register values,
which do not have the soft reset overrides enabled. And according to
some docs by default the data lane resets are tied to cmnreset. So that
would mean that lanes would come out of reset without staggering as
soon as the power down overrides are removed. But since we can't access
either the lane stagger register nor the soft reset override registers
until the lanes are powered on, we can't really do anything about it.
So let's just set the soft reset overrides as soon as the lane is
powered on and hope for the best.

v2: Fix typos in commit message (Daniel)

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c   | 91 +++++++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_hdmi.c | 91 ++++++++++++++++++++++-----------------
 2 files changed, 100 insertions(+), 82 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 817df87..297bd14 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2389,42 +2389,62 @@ static void vlv_post_disable_dp(struct intel_encoder *encoder)
 	intel_dp_link_down(intel_dp);
 }
 
-static void chv_post_disable_dp(struct intel_encoder *encoder)
+static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+				     bool reset)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
-	struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
-	struct drm_device *dev = encoder->base.dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc =
-		to_intel_crtc(encoder->base.crtc);
-	enum dpio_channel ch = vlv_dport_to_channel(dport);
-	enum pipe pipe = intel_crtc->pipe;
-	u32 val;
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	enum pipe pipe = crtc->pipe;
+	uint32_t val;
 
-	intel_dp_link_down(intel_dp);
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
+	if (reset)
+		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+	else
+		val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
 
-	mutex_lock(&dev_priv->sb_lock);
+	if (crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+		if (reset)
+			val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+		else
+			val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	}
 
-	/* Propagate soft reset to data lane reset */
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
 	val |= CHV_PCS_REQ_SOFTRESET_EN;
+	if (reset)
+		val &= ~DPIO_PCS_CLK_SOFT_RESET;
+	else
+		val |= DPIO_PCS_CLK_SOFT_RESET;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
 
-	if (intel_crtc->config->lane_count > 2) {
+	if (crtc->config->lane_count > 2) {
 		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
 		val |= CHV_PCS_REQ_SOFTRESET_EN;
+		if (reset)
+			val &= ~DPIO_PCS_CLK_SOFT_RESET;
+		else
+			val |= DPIO_PCS_CLK_SOFT_RESET;
 		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
 	}
+}
 
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
+static void chv_post_disable_dp(struct intel_encoder *encoder)
+{
+	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
-	if (intel_crtc->config->lane_count > 2) {
-		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-	}
+	intel_dp_link_down(intel_dp);
+
+	mutex_lock(&dev_priv->sb_lock);
+
+	/* Assert data lane reset */
+	chv_data_lane_soft_reset(encoder, true);
 
 	mutex_unlock(&dev_priv->sb_lock);
 }
@@ -2802,27 +2822,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
 	}
 
-	/* Deassert soft data lane reset*/
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-	if (intel_crtc->config->lane_count > 2) {
-		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-		val |= CHV_PCS_REQ_SOFTRESET_EN;
-		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-	}
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-	if (intel_crtc->config->lane_count > 2) {
-		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-		val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-	}
-
 	/* Program Tx lane latency optimal setting*/
 	for (i = 0; i < intel_crtc->config->lane_count; i++) {
 		/* Set the upar bit */
@@ -2872,6 +2871,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 			       DPIO_TX2_STAGGER_MULT(5));
 	}
 
+	/* Deassert data lane reset */
+	chv_data_lane_soft_reset(encoder, false);
+
 	mutex_unlock(&dev_priv->sb_lock);
 
 	intel_enable_dp(encoder);
@@ -2910,6 +2912,9 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
 
 	mutex_lock(&dev_priv->sb_lock);
 
+	/* Assert data lane reset */
+	chv_data_lane_soft_reset(encoder, true);
+
 	/* program left/right clock distribution */
 	if (pipe != PIPE_B) {
 		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 4b604ee..176d681 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1612,6 +1612,50 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->sb_lock);
 }
 
+static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
+				     bool reset)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	enum pipe pipe = crtc->pipe;
+	uint32_t val;
+
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
+	if (reset)
+		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+	else
+		val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
+
+	if (crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
+		if (reset)
+			val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
+		else
+			val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	}
+
+	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
+	val |= CHV_PCS_REQ_SOFTRESET_EN;
+	if (reset)
+		val &= ~DPIO_PCS_CLK_SOFT_RESET;
+	else
+		val |= DPIO_PCS_CLK_SOFT_RESET;
+	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
+
+	if (crtc->config->lane_count > 2) {
+		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
+		val |= CHV_PCS_REQ_SOFTRESET_EN;
+		if (reset)
+			val &= ~DPIO_PCS_CLK_SOFT_RESET;
+		else
+			val |= DPIO_PCS_CLK_SOFT_RESET;
+		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
+	}
+}
+
 static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 {
 	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
@@ -1637,6 +1681,9 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
 
 	mutex_lock(&dev_priv->sb_lock);
 
+	/* Assert data lane reset */
+	chv_data_lane_soft_reset(encoder, true);
+
 	/* program left/right clock distribution */
 	if (pipe != PIPE_B) {
 		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
@@ -1739,33 +1786,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
 
 static void chv_hdmi_post_disable(struct intel_encoder *encoder)
 {
-	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
 	struct drm_device *dev = encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_crtc *intel_crtc =
-		to_intel_crtc(encoder->base.crtc);
-	enum dpio_channel ch = vlv_dport_to_channel(dport);
-	enum pipe pipe = intel_crtc->pipe;
-	u32 val;
 
 	mutex_lock(&dev_priv->sb_lock);
 
-	/* Propagate soft reset to data lane reset */
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
+	/* Assert data lane reset */
+	chv_data_lane_soft_reset(encoder, true);
 
 	mutex_unlock(&dev_priv->sb_lock);
 }
@@ -1796,23 +1823,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
 	val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
 	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
 
-	/* Deassert soft data lane reset*/
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
-	val |= CHV_PCS_REQ_SOFTRESET_EN;
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
-	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
-
-	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
-	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
-	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
-
 	/* Program Tx latency optimal setting */
 	for (i = 0; i < 4; i++) {
 		/* Set the upar bit */
@@ -1855,6 +1865,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
 		       DPIO_TX1_STAGGER_MULT(7) |
 		       DPIO_TX2_STAGGER_MULT(5));
 
+	/* Deassert data lane reset */
+	chv_data_lane_soft_reset(encoder, false);
+
 	/* Clear calc init */
 	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
 	val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
-- 
2.3.6

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

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

* [PATCH v2 10/15] drm/i915: Force common lane on for the PPS kick on CHV
  2015-07-08 20:45 ` [PATCH 10/15] drm/i915: Force common lane on for the PPS kick on CHV ville.syrjala
@ 2015-07-10  7:56   ` ville.syrjala
  2015-08-19  2:21   ` [PATCH " Deepak
  1 sibling, 0 replies; 50+ messages in thread
From: ville.syrjala @ 2015-07-10  7:56 UTC (permalink / raw)
  To: intel-gfx; +Cc: Deepak S

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

With DPIO powergating active the DPLL can't be accessed unless
something else is keeping the common lane in the channel on.
That means the PPS kick procedure could fail to enable the PLL.

Power up some data lanes to force the common lane to power up
so that the PLL can be enabled temporarily.

v2: Avoid gcc uninitilized variable warning

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8d088f3..2459374 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -341,7 +341,9 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	enum pipe pipe = intel_dp->pps_pipe;
-	bool pll_enabled;
+	bool pll_enabled, release_cl_override = false;
+	enum dpio_phy phy = DPIO_PHY(pipe);
+	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
 	uint32_t DP;
 
 	if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,
@@ -371,9 +373,13 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 	 * The DPLL for the pipe must be enabled for this to work.
 	 * So enable temporarily it if it's not already enabled.
 	 */
-	if (!pll_enabled)
+	if (!pll_enabled) {
+		release_cl_override = IS_CHERRYVIEW(dev) &&
+			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
+
 		vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
 				 &chv_dpll[0].dpll : &vlv_dpll[0].dpll);
+	}
 
 	/*
 	 * Similar magic as in intel_dp_enable_port().
@@ -390,8 +396,12 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
 	POSTING_READ(intel_dp->output_reg);
 
-	if (!pll_enabled)
+	if (!pll_enabled) {
 		vlv_force_pll_off(dev, pipe);
+
+		if (release_cl_override)
+			chv_phy_powergate_ch(dev_priv, phy, ch, false);
+	}
 }
 
 static enum pipe
-- 
2.3.6

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

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

* Re: [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV
  2015-07-08 20:45 ` [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV ville.syrjala
@ 2015-08-17  2:19   ` Deepak
  2015-08-17 11:45     ` Ville Syrjälä
  0 siblings, 1 reply; 50+ messages in thread
From: Deepak @ 2015-08-17  2:19 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> When fractional m2 divider isn't used on CHV the fractional part
> is ignore by the hardware. Despite that, program the fractional
> value (0 in this case) to the hardware register just to keep
> things a bit more consistent. Might at least make register dumps
> a bit less confusing when there isn't some stale fractional part
> hanging around.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_display.c | 3 +--
>   1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0b2ad76..3df9cb2 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -7393,8 +7393,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
>   			1 << DPIO_CHV_N_DIV_SHIFT);
>   
>   	/* M2 fraction division */
> -	if (bestm2_frac)
> -		vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
> +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
>   
>   	/* M2 fraction division enable */
>   	dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
Since we do not use fractional m2 driver in chv, can we remove other 
bestm2_frac used in chv pll function?
like
if (bestm2_frac)
     dpio_val |= DPIO_CHV_FRAC_DIV_EN;

&
if (!bestm2_frac)
     dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;

Do we need this?





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

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

* Re: [PATCH 02/15] drm/i915: Always program unique transition scale for CHV
  2015-07-08 20:45 ` [PATCH 02/15] drm/i915: Always program unique transition scale for CHV ville.syrjala
@ 2015-08-17  2:31   ` Deepak
  0 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-17  2:31 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> The docs give you the impression that the unique transition scale
> value shouldn't matter when unique transition scale is enabled. But
> as Imre found on BXT (and I verfied also on BSW) the value does
> matter. So from now on just program the same value 0x9a always.
>
> Cc: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_dp.c   | 53 +++++++++++++++++++--------------------
>   drivers/gpu/drm/i915/intel_hdmi.c | 30 +++++++++++-----------
>   2 files changed, 42 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index f424833..32d7e43 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3142,6 +3142,12 @@ static uint32_t vlv_signal_levels(struct intel_dp *intel_dp)
>   	return 0;
>   }
>   
> +static bool chv_need_uniq_trans_scale(uint8_t train_set)
> +{
> +	return (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) == DP_TRAIN_PRE_EMPH_LEVEL_0 &&
> +		(train_set & DP_TRAIN_VOLTAGE_SWING_MASK) == DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
> +}
> +
>   static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
>   {
>   	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -3260,41 +3266,34 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
>   	/* Program swing margin */
>   	for (i = 0; i < 4; i++) {
>   		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
> +
>   		val &= ~DPIO_SWING_MARGIN000_MASK;
>   		val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT;
> +
> +		/*
> +		 * Supposedly this value shouldn't matter when unique transition
> +		 * scale is disabled, but in fact it does matter. Let's just
> +		 * always program the same value and hope it's OK.
> +		 */
> +		val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
> +		val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT;
> +
>   		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
>   	}
>   
> -	/* Disable unique transition scale */
> +	/*
> +	 * The document said it needs to set bit 27 for ch0 and bit 26
> +	 * for ch1. Might be a typo in the doc.
> +	 * For now, for this unique transition scale selection, set bit
> +	 * 27 for ch0 and ch1.
> +	 */
>   	for (i = 0; i < 4; i++) {
>   		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
> -		val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
> -		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
> -	}
> -
> -	if (((train_set & DP_TRAIN_PRE_EMPHASIS_MASK)
> -			== DP_TRAIN_PRE_EMPH_LEVEL_0) &&
> -		((train_set & DP_TRAIN_VOLTAGE_SWING_MASK)
> -			== DP_TRAIN_VOLTAGE_SWING_LEVEL_3)) {
> -
> -		/*
> -		 * The document said it needs to set bit 27 for ch0 and bit 26
> -		 * for ch1. Might be a typo in the doc.
> -		 * For now, for this unique transition scale selection, set bit
> -		 * 27 for ch0 and ch1.
> -		 */
> -		for (i = 0; i < 4; i++) {
> -			val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
> +		if (chv_need_uniq_trans_scale(train_set))
>   			val |= DPIO_TX_UNIQ_TRANS_SCALE_EN;
> -			vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
> -		}
> -
> -		for (i = 0; i < 4; i++) {
> -			val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
> -			val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
> -			val |= (0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT);
> -			vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
> -		}
> +		else
> +			val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
> +		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
>   	}
>   
>   	/* Start swing calculation */
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index ba845f7..9f79afb 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1846,31 +1846,33 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
>   
>   	for (i = 0; i < 4; i++) {
>   		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
> +
>   		val &= ~DPIO_SWING_MARGIN000_MASK;
>   		val |= 102 << DPIO_SWING_MARGIN000_SHIFT;
> +
> +		/*
> +		 * Supposedly this value shouldn't matter when unique transition
> +		 * scale is disabled, but in fact it does matter. Let's just
> +		 * always program the same value and hope it's OK.
> +		 */
> +		val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT);
> +		val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT;
> +
>   		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val);
>   	}
>   
> -	/* Disable unique transition scale */
> +	/*
> +	 * The document said it needs to set bit 27 for ch0 and bit 26
> +	 * for ch1. Might be a typo in the doc.
> +	 * For now, for this unique transition scale selection, set bit
> +	 * 27 for ch0 and ch1.
> +	 */
>   	for (i = 0; i < 4; i++) {
>   		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
>   		val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN;
>   		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val);
>   	}
>   
> -	/* Additional steps for 1200mV-0dB */
> -#if 0
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_TX_DW3(ch));
> -	if (ch)
> -		val |= DPIO_TX_UNIQ_TRANS_SCALE_CH1;
> -	else
> -		val |= DPIO_TX_UNIQ_TRANS_SCALE_CH0;
> -	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(ch), val);
> -
> -	vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(ch),
> -			vlv_dpio_read(dev_priv, pipe, VLV_TX_DW2(ch)) |
> -				(0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT));
> -#endif
>   	/* Start swing calculation */
>   	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
>   	val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
Looks fine to me
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 03/15] drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there
  2015-07-08 20:45 ` [PATCH 03/15] drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there ville.syrjala
@ 2015-08-17  4:16   ` Deepak
  2015-08-17 11:53     ` Ville Syrjälä
  0 siblings, 1 reply; 50+ messages in thread
From: Deepak @ 2015-08-17  4:16 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Move the CHV clock buffer disable from chv_disable_pll() to the new
> encoder .post_pll_disable() hook. This is more symmetric since the
> clock buffer enable happens from the .pre_pll_enable() hook.
>
> We'll have more use for the new hook soon.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_display.c | 15 ++++-----------
>   drivers/gpu/drm/i915/intel_dp.c      | 23 +++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_drv.h     |  1 +
>   drivers/gpu/drm/i915/intel_hdmi.c    | 23 +++++++++++++++++++++++
>   4 files changed, 51 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 3df9cb2..db518a7 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1851,17 +1851,6 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
>   	val &= ~DPIO_DCLKP_EN;
>   	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
>   
> -	/* disable left/right clock distribution */
> -	if (pipe != PIPE_B) {
> -		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> -		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
> -		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
> -	} else {
> -		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
> -		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
> -		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
> -	}
> -
>   	mutex_unlock(&dev_priv->sb_lock);
>   }
>   
> @@ -6171,6 +6160,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
>   			i9xx_disable_pll(intel_crtc);
>   	}
>   
> +	for_each_encoder_on_crtc(dev, crtc, encoder)
> +		if (encoder->post_pll_disable)
> +			encoder->post_pll_disable(encoder);
> +
We call "vlv_force_pll_off" in vlv_power_sequencer_kick which call 
chv_disablepll.
Should we add the "post_pll_disable"in force pll off?
>   	if (!IS_GEN2(dev))
>   		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
>   }
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 32d7e43..40b8430 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2906,6 +2906,28 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
>   	mutex_unlock(&dev_priv->sb_lock);
>   }
>   
> +static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
> +	u32 val;
> +
> +	mutex_lock(&dev_priv->sb_lock);
> +
> +	/* disable left/right clock distribution */
> +	if (pipe != PIPE_B) {
> +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> +		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
> +	} else {
> +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
> +		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
> +	}
> +
> +	mutex_unlock(&dev_priv->sb_lock);
> +}
> +
>   /*
>    * Native read with retry for link status and receiver capability reads for
>    * cases where the sink may still be asleep.
> @@ -5931,6 +5953,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
>   		intel_encoder->pre_enable = chv_pre_enable_dp;
>   		intel_encoder->enable = vlv_enable_dp;
>   		intel_encoder->post_disable = chv_post_disable_dp;
> +		intel_encoder->post_pll_disable = chv_dp_post_pll_disable;
>   	} else if (IS_VALLEYVIEW(dev)) {
>   		intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
>   		intel_encoder->pre_enable = vlv_pre_enable_dp;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 4f3b708..42fa135 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -148,6 +148,7 @@ struct intel_encoder {
>   	void (*mode_set)(struct intel_encoder *intel_encoder);
>   	void (*disable)(struct intel_encoder *);
>   	void (*post_disable)(struct intel_encoder *);
> +	void (*post_pll_disable)(struct intel_encoder *);
>   	/* Read out the current hw state of this connector, returning true if
>   	 * the encoder is active. If the encoder is enabled it also set the pipe
>   	 * it is connected to in the pipe parameter. */
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 9f79afb..86b1a2c 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1678,6 +1678,28 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>   	mutex_unlock(&dev_priv->sb_lock);
>   }
>   
> +static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
> +	u32 val;
> +
> +	mutex_lock(&dev_priv->sb_lock);
> +
> +	/* disable left/right clock distribution */
> +	if (pipe != PIPE_B) {
> +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> +		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
> +	} else {
> +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
> +		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
> +	}
> +
> +	mutex_unlock(&dev_priv->sb_lock);
> +}
> +
>   static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
>   {
>   	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
> @@ -2073,6 +2095,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
>   		intel_encoder->pre_enable = chv_hdmi_pre_enable;
>   		intel_encoder->enable = vlv_enable_hdmi;
>   		intel_encoder->post_disable = chv_hdmi_post_disable;
> +		intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable;
>   	} else if (IS_VALLEYVIEW(dev)) {
>   		intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
>   		intel_encoder->pre_enable = vlv_hdmi_pre_enable;

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

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

* Re: [PATCH 04/15] drm/i915: Move DPIO port init earlier
  2015-07-08 20:45 ` [PATCH 04/15] drm/i915: Move DPIO port init earlier ville.syrjala
@ 2015-08-17  4:18   ` Deepak
  0 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-17  4:18 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> To implement DPIO lane power gating on CHV we're going to need to access
> DPIO registers from the cmn power well enable hook. That gets called
> rather early, so we need to move the DPIO port IOSF sideband port
> assignment earlier as well.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_dma.c      | 20 ++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_display.c | 22 ----------------------
>   2 files changed, 20 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 5e63076..3e9e98a 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -783,6 +783,24 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
>   			 info->has_eu_pg ? "y" : "n");
>   }
>   
> +static void intel_init_dpio(struct drm_i915_private *dev_priv)
> +{
> +	if (!IS_VALLEYVIEW(dev_priv))
> +		return;
> +
> +	/*
> +	 * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
> +	 * CHV x1 PHY (DP/HDMI D)
> +	 * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
> +	 */
> +	if (IS_CHERRYVIEW(dev_priv)) {
> +		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
> +		DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
> +	} else {
> +		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
> +	}
> +}
> +
>   /**
>    * i915_driver_load - setup chip and create an initial config
>    * @dev: DRM device
> @@ -983,6 +1001,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
>   
>   	intel_device_info_runtime_init(dev);
>   
> +	intel_init_dpio(dev_priv);
> +
>   	if (INTEL_INFO(dev)->num_pipes) {
>   		ret = drm_vblank_init(dev, INTEL_INFO(dev)->num_pipes);
>   		if (ret)
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index db518a7..0473b38 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -1590,26 +1590,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
>   	assert_pch_hdmi_disabled(dev_priv, pipe, PCH_HDMID);
>   }
>   
> -static void intel_init_dpio(struct drm_device *dev)
> -{
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -
> -	if (!IS_VALLEYVIEW(dev))
> -		return;
> -
> -	/*
> -	 * IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
> -	 * CHV x1 PHY (DP/HDMI D)
> -	 * IOSF_PORT_DPIO_2 is used for CHV x2 PHY (DP/HDMI B and C)
> -	 */
> -	if (IS_CHERRYVIEW(dev)) {
> -		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
> -		DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
> -	} else {
> -		DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
> -	}
> -}
> -
>   static void vlv_enable_pll(struct intel_crtc *crtc,
>   			   const struct intel_crtc_state *pipe_config)
>   {
> @@ -15049,8 +15029,6 @@ void intel_modeset_init(struct drm_device *dev)
>   		}
>   	}
>   
> -	intel_init_dpio(dev);
> -
>   	intel_shared_dpll_init(dev);
>   
>   	/* Just disable it once at startup */
Looks fine to me
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 05/15] drm/i915: Add locking around chv_phy_control_init()
  2015-07-08 20:45 ` [PATCH 05/15] drm/i915: Add locking around chv_phy_control_init() ville.syrjala
@ 2015-08-17  4:23   ` Deepak
  0 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-17  4:23 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> dev_priv->chv_phy_control is protected by the power_domains->lock
> elsewhere, so also grab it when initializing chv_phy_control.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 2 ++
>   1 file changed, 2 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 2142ae6..dab1da9 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -1678,7 +1678,9 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv)
>   	power_domains->initializing = true;
>   
>   	if (IS_CHERRYVIEW(dev)) {
> +		mutex_lock(&power_domains->lock);
>   		chv_phy_control_init(dev_priv);
> +		mutex_unlock(&power_domains->lock);
>   	} else if (IS_VALLEYVIEW(dev)) {
>   		mutex_lock(&power_domains->lock);
>   		vlv_cmnlane_wa(dev_priv);
Looks fine to me :)
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 06/15] drm/i915: Move VLV/CHV prepare_pll later
  2015-07-08 20:45 ` [PATCH 06/15] drm/i915: Move VLV/CHV prepare_pll later ville.syrjala
@ 2015-08-17  4:36   ` Deepak
  2015-08-17  4:39   ` Deepak
  1 sibling, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-17  4:36 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> With DPIO powergating active on CHV, we can't even access the DPIO PLL
> registers until the lane power state overrides have been enabled. That
> will happen from the encoder .pre_pll_enable() hook, so move
> chv_prepare_pll() to happen after that point, which puts it just before
> chv_enable_pll() actually.
>
> Do the same for VLV to avoid accumulating weird differences between the
> platforms. Both platforms seem happy with the new arrangement.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_display.c | 14 +++++---------
>   1 file changed, 5 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0473b38..666a236 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5979,13 +5979,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
>   
>   	is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
>   
> -	if (!is_dsi) {
> -		if (IS_CHERRYVIEW(dev))
> -			chv_prepare_pll(intel_crtc, intel_crtc->config);
> -		else
> -			vlv_prepare_pll(intel_crtc, intel_crtc->config);
> -	}
> -
>   	if (intel_crtc->config->has_dp_encoder)
>   		intel_dp_set_m_n(intel_crtc, M1_N1);
>   
> @@ -6009,10 +6002,13 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
>   			encoder->pre_pll_enable(encoder);
>   
>   	if (!is_dsi) {
> -		if (IS_CHERRYVIEW(dev))
> +		if (IS_CHERRYVIEW(dev)) {
> +			chv_prepare_pll(intel_crtc, intel_crtc->config);
>   			chv_enable_pll(intel_crtc, intel_crtc->config);
> -		else
> +		} else {
> +			vlv_prepare_pll(intel_crtc, intel_crtc->config);
>   			vlv_enable_pll(intel_crtc, intel_crtc->config);
> +		}
>   	}
>   
>   	for_each_encoder_on_crtc(dev, crtc, encoder)

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

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

* Re: [PATCH 06/15] drm/i915: Move VLV/CHV prepare_pll later
  2015-07-08 20:45 ` [PATCH 06/15] drm/i915: Move VLV/CHV prepare_pll later ville.syrjala
  2015-08-17  4:36   ` Deepak
@ 2015-08-17  4:39   ` Deepak
  1 sibling, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-17  4:39 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> With DPIO powergating active on CHV, we can't even access the DPIO PLL
> registers until the lane power state overrides have been enabled. That
> will happen from the encoder .pre_pll_enable() hook, so move
> chv_prepare_pll() to happen after that point, which puts it just before
> chv_enable_pll() actually.
>
> Do the same for VLV to avoid accumulating weird differences between the
> platforms. Both platforms seem happy with the new arrangement.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_display.c | 14 +++++---------
>   1 file changed, 5 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0473b38..666a236 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -5979,13 +5979,6 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
>   
>   	is_dsi = intel_pipe_has_type(intel_crtc, INTEL_OUTPUT_DSI);
>   
> -	if (!is_dsi) {
> -		if (IS_CHERRYVIEW(dev))
> -			chv_prepare_pll(intel_crtc, intel_crtc->config);
> -		else
> -			vlv_prepare_pll(intel_crtc, intel_crtc->config);
> -	}
> -
>   	if (intel_crtc->config->has_dp_encoder)
>   		intel_dp_set_m_n(intel_crtc, M1_N1);
>   
> @@ -6009,10 +6002,13 @@ static void valleyview_crtc_enable(struct drm_crtc *crtc)
>   			encoder->pre_pll_enable(encoder);
>   
>   	if (!is_dsi) {
> -		if (IS_CHERRYVIEW(dev))
> +		if (IS_CHERRYVIEW(dev)) {
> +			chv_prepare_pll(intel_crtc, intel_crtc->config);
>   			chv_enable_pll(intel_crtc, intel_crtc->config);
> -		else
> +		} else {
> +			vlv_prepare_pll(intel_crtc, intel_crtc->config);
>   			vlv_enable_pll(intel_crtc, intel_crtc->config);
> +		}
>   	}
>   
>   	for_each_encoder_on_crtc(dev, crtc, encoder)
Looks fine to me
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 07/15] drm/i915: Add vlv_dport_to_phy()
  2015-07-08 20:45 ` [PATCH 07/15] drm/i915: Add vlv_dport_to_phy() ville.syrjala
@ 2015-08-17  4:56   ` Deepak
  2015-08-26  8:24   ` Daniel Vetter
  1 sibling, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-17  4:56 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Add vlv_dport_to_phy() and fix up the return values of
> vlv_dport_to_channel() and vlv_pipe_to_channel() to use
> the appropriate enums.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_drv.h | 18 ++++++++++++++++--
>   1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 42fa135..23d5e46 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -791,7 +791,7 @@ struct intel_dp_mst_encoder {
>   	void *port; /* store this opaque as its illegal to dereference it */
>   };
>   
> -static inline int
> +static inline enum dpio_channel
>   vlv_dport_to_channel(struct intel_digital_port *dport)
>   {
>   	switch (dport->port) {
> @@ -805,7 +805,21 @@ vlv_dport_to_channel(struct intel_digital_port *dport)
>   	}
>   }
>   
> -static inline int
> +static inline enum dpio_phy
> +vlv_dport_to_phy(struct intel_digital_port *dport)
> +{
> +	switch (dport->port) {
> +	case PORT_B:
> +	case PORT_C:
> +		return DPIO_PHY0;
> +	case PORT_D:
> +		return DPIO_PHY1;
> +	default:
> +		BUG();
> +	}
> +}
> +
Looks fine here is my r-b tag
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
> +static inline enum dpio_channel
>   vlv_pipe_to_channel(enum pipe pipe)
>   {
>   	switch (pipe) {


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

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

* Re: [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV
  2015-08-17  2:19   ` Deepak
@ 2015-08-17 11:45     ` Ville Syrjälä
  2015-08-26  8:11       ` Deepak
  0 siblings, 1 reply; 50+ messages in thread
From: Ville Syrjälä @ 2015-08-17 11:45 UTC (permalink / raw)
  To: Deepak; +Cc: intel-gfx

On Mon, Aug 17, 2015 at 07:49:41AM +0530, Deepak wrote:
> 
> 
> On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > When fractional m2 divider isn't used on CHV the fractional part
> > is ignore by the hardware. Despite that, program the fractional
> > value (0 in this case) to the hardware register just to keep
> > things a bit more consistent. Might at least make register dumps
> > a bit less confusing when there isn't some stale fractional part
> > hanging around.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >   drivers/gpu/drm/i915/intel_display.c | 3 +--
> >   1 file changed, 1 insertion(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 0b2ad76..3df9cb2 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -7393,8 +7393,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
> >   			1 << DPIO_CHV_N_DIV_SHIFT);
> >   
> >   	/* M2 fraction division */
> > -	if (bestm2_frac)
> > -		vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
> > +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
> >   
> >   	/* M2 fraction division enable */
> >   	dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
> Since we do not use fractional m2 driver in chv, can we remove other 
> bestm2_frac used in chv pll function?
> like
> if (bestm2_frac)
>      dpio_val |= DPIO_CHV_FRAC_DIV_EN;
> 
> &
> if (!bestm2_frac)
>      dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;
> 
> Do we need this?

We do use the fractional divider, when it's not 0.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 03/15] drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there
  2015-08-17  4:16   ` Deepak
@ 2015-08-17 11:53     ` Ville Syrjälä
  2015-08-26  8:14       ` Deepak
  0 siblings, 1 reply; 50+ messages in thread
From: Ville Syrjälä @ 2015-08-17 11:53 UTC (permalink / raw)
  To: Deepak; +Cc: intel-gfx

On Mon, Aug 17, 2015 at 09:46:01AM +0530, Deepak wrote:
> 
> 
> On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Move the CHV clock buffer disable from chv_disable_pll() to the new
> > encoder .post_pll_disable() hook. This is more symmetric since the
> > clock buffer enable happens from the .pre_pll_enable() hook.
> >
> > We'll have more use for the new hook soon.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >   drivers/gpu/drm/i915/intel_display.c | 15 ++++-----------
> >   drivers/gpu/drm/i915/intel_dp.c      | 23 +++++++++++++++++++++++
> >   drivers/gpu/drm/i915/intel_drv.h     |  1 +
> >   drivers/gpu/drm/i915/intel_hdmi.c    | 23 +++++++++++++++++++++++
> >   4 files changed, 51 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> > index 3df9cb2..db518a7 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -1851,17 +1851,6 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
> >   	val &= ~DPIO_DCLKP_EN;
> >   	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
> >   
> > -	/* disable left/right clock distribution */
> > -	if (pipe != PIPE_B) {
> > -		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> > -		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
> > -		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
> > -	} else {
> > -		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
> > -		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
> > -		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
> > -	}
> > -
> >   	mutex_unlock(&dev_priv->sb_lock);
> >   }
> >   
> > @@ -6171,6 +6160,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
> >   			i9xx_disable_pll(intel_crtc);
> >   	}
> >   
> > +	for_each_encoder_on_crtc(dev, crtc, encoder)
> > +		if (encoder->post_pll_disable)
> > +			encoder->post_pll_disable(encoder);
> > +
> We call "vlv_force_pll_off" in vlv_power_sequencer_kick which call 
> chv_disablepll.
> Should we add the "post_pll_disable"in force pll off?

Nope. .post_pll_disable() is the counterpart to .pre_pll_enable() which
we don't use either in the pps kick procedure.

Apparently we don't need to concern ourselves with the clock
channel/districtution setp to make the pps kick work. Well, it's either
that, or we've just been lucky and those end up being set up in a good
way by accident. But now that you mention it, I do start wonder a bit
how it really works. So this is probably something I should test more
thoroughly at some point.

> >   	if (!IS_GEN2(dev))
> >   		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
> >   }
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 32d7e43..40b8430 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -2906,6 +2906,28 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
> >   	mutex_unlock(&dev_priv->sb_lock);
> >   }
> >   
> > +static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> > +	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
> > +	u32 val;
> > +
> > +	mutex_lock(&dev_priv->sb_lock);
> > +
> > +	/* disable left/right clock distribution */
> > +	if (pipe != PIPE_B) {
> > +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> > +		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
> > +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
> > +	} else {
> > +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
> > +		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
> > +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
> > +	}
> > +
> > +	mutex_unlock(&dev_priv->sb_lock);
> > +}
> > +
> >   /*
> >    * Native read with retry for link status and receiver capability reads for
> >    * cases where the sink may still be asleep.
> > @@ -5931,6 +5953,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
> >   		intel_encoder->pre_enable = chv_pre_enable_dp;
> >   		intel_encoder->enable = vlv_enable_dp;
> >   		intel_encoder->post_disable = chv_post_disable_dp;
> > +		intel_encoder->post_pll_disable = chv_dp_post_pll_disable;
> >   	} else if (IS_VALLEYVIEW(dev)) {
> >   		intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
> >   		intel_encoder->pre_enable = vlv_pre_enable_dp;
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index 4f3b708..42fa135 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -148,6 +148,7 @@ struct intel_encoder {
> >   	void (*mode_set)(struct intel_encoder *intel_encoder);
> >   	void (*disable)(struct intel_encoder *);
> >   	void (*post_disable)(struct intel_encoder *);
> > +	void (*post_pll_disable)(struct intel_encoder *);
> >   	/* Read out the current hw state of this connector, returning true if
> >   	 * the encoder is active. If the encoder is enabled it also set the pipe
> >   	 * it is connected to in the pipe parameter. */
> > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > index 9f79afb..86b1a2c 100644
> > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > @@ -1678,6 +1678,28 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
> >   	mutex_unlock(&dev_priv->sb_lock);
> >   }
> >   
> > +static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
> > +{
> > +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> > +	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
> > +	u32 val;
> > +
> > +	mutex_lock(&dev_priv->sb_lock);
> > +
> > +	/* disable left/right clock distribution */
> > +	if (pipe != PIPE_B) {
> > +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> > +		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
> > +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
> > +	} else {
> > +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
> > +		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
> > +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
> > +	}
> > +
> > +	mutex_unlock(&dev_priv->sb_lock);
> > +}
> > +
> >   static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
> >   {
> >   	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
> > @@ -2073,6 +2095,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
> >   		intel_encoder->pre_enable = chv_hdmi_pre_enable;
> >   		intel_encoder->enable = vlv_enable_hdmi;
> >   		intel_encoder->post_disable = chv_hdmi_post_disable;
> > +		intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable;
> >   	} else if (IS_VALLEYVIEW(dev)) {
> >   		intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
> >   		intel_encoder->pre_enable = vlv_hdmi_pre_enable;
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 08/15] drm/i915: Implement PHY lane power gating for CHV
  2015-07-08 20:45 ` [PATCH 08/15] drm/i915: Implement PHY lane power gating for CHV ville.syrjala
@ 2015-08-19  1:48   ` Deepak
  2015-08-26  8:27   ` Daniel Vetter
  1 sibling, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-19  1:48 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Powergate the PHY lanes when they're not needed. For HDMI all four lanes
> are needed always, but for DP we can enable only the needed lanes. To
> power down the unused lanes we use some power down override bits in the
> DISPLAY_PHY_CONTROL register. Without the overrides it appears that the
> hardware always powers on all the lanes. When the port is disabled the
> power down override is not needed and the lanes will shut off on their
> own. That also means the override is critical to actually be able to
> access the DPIO registers before the port is actually enabled.
>
> Additionally the common lanes will power down when not needed. CL1
> remains on as long as anything else is on, CL2 will shut down when
> all the lanes in the same channel will shut down. There is one exception
> for CL2 that will be dealt in a separate patch for clarity.
>
> With potentially some lanes powered down, the DP code now has to check
> the number of active lanes before accessing PCS/TX registers. All
> registers in powered down blocks will reads as 0xffffffff, and soe we
> would drown in warnings from vlv_dpio_read() if we allowed the code
> to access all those registers.
>
> Another important detail in the DP code is the "TX latency optimal"
> setting. Normally the second TX lane acts as some kind of reset master,
> with the other lanes as slaves. But when only a single lane is enabled,
> that single lane obviously has to be the master.
>
> A bit of extra care is needed to reconstruct the initial state of the
> DISPLAY_PHY_CONTROL register since it can't be read safely. So instead
> read the actual lane status from the DPLL/PHY_STATUS registers and
> use that to determine which lanes ought to be powergated initially.
>
> We also need to switch the PHY power modes to "deep PSR" to avoid
> a hard system hang when powering down the single channel PHY.
>
> Also sprinkle a few debug prints around so that we can monitor the
> DISPLAY_PHY_STATUS changes without having to read it and risk
> corrupting it.
>
> v2: Add locking to chv_powergate_phy_lanes()
> v3: Actually enable dynamic powerdown in the PHY and deal with the
>      fallout
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_reg.h         |   8 ++
>   drivers/gpu/drm/i915/intel_dp.c         | 141 +++++++++++++++++++++-----------
>   drivers/gpu/drm/i915/intel_drv.h        |   4 +
>   drivers/gpu/drm/i915/intel_hdmi.c       |   4 +
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 123 ++++++++++++++++++++++++++--
>   5 files changed, 221 insertions(+), 59 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 17cb7e5..bcfcbb62 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1125,9 +1125,15 @@ enum skl_disp_power_wells {
>   
>   #define _CHV_CMN_DW19_CH0		0x814c
>   #define _CHV_CMN_DW6_CH1		0x8098
> +#define   DPIO_DYNPWRDOWNEN_CH1		(1 << 28) /* CL2 DW6 only */
>   #define   CHV_CMN_USEDCLKCHANNEL	(1 << 13)
> +
>   #define CHV_CMN_DW19(ch) _PIPE(ch, _CHV_CMN_DW19_CH0, _CHV_CMN_DW6_CH1)
>   
> +#define CHV_CMN_DW28			0x8170
> +#define   DPIO_CL1POWERDOWNEN		(1 << 23)
> +#define   DPIO_DYNPWRDOWNEN_CH0		(1 << 22)
> +
>   #define CHV_CMN_DW30			0x8178
>   #define   DPIO_LRC_BYPASS		(1 << 3)
>   
> @@ -2175,10 +2181,12 @@ enum skl_disp_power_wells {
>   #define DPIO_PHY_STATUS			(VLV_DISPLAY_BASE + 0x6240)
>   #define   DPLL_PORTD_READY_MASK		(0xf)
>   #define DISPLAY_PHY_CONTROL (VLV_DISPLAY_BASE + 0x60100)
> +#define   PHY_CH_POWER_DOWN_OVRD_EN(phy, ch)	(1 << (2*(phy)+(ch)+27))
>   #define   PHY_LDO_DELAY_0NS			0x0
>   #define   PHY_LDO_DELAY_200NS			0x1
>   #define   PHY_LDO_DELAY_600NS			0x2
>   #define   PHY_LDO_SEQ_DELAY(delay, phy)		((delay) << (2*(phy)+23))
> +#define   PHY_CH_POWER_DOWN_OVRD(mask, phy, ch)	((mask) << (8*(phy)+4*(ch)+11))
>   #define   PHY_CH_SU_PSR				0x1
>   #define   PHY_CH_DEEP_PSR			0x7
>   #define   PHY_CH_POWER_MODE(mode, phy, ch)	((mode) << (6*(phy)+3*(ch)+2))
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 40b8430..6058129 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -133,6 +133,11 @@ static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp);
>   static void vlv_steal_power_sequencer(struct drm_device *dev,
>   				      enum pipe pipe);
>   
> +static unsigned int intel_dp_unused_lane_mask(int lane_count)
> +{
> +	return ~((1 << lane_count) - 1) & 0xf;
> +}
> +
>   static int
>   intel_dp_max_link_bw(struct intel_dp  *intel_dp)
>   {
> @@ -2395,17 +2400,21 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)
>   	val |= CHV_PCS_REQ_SOFTRESET_EN;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> +		val |= CHV_PCS_REQ_SOFTRESET_EN;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> +	}
>   
>   	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
>   	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> +		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	}
>   
>   	mutex_unlock(&dev_priv->sb_lock);
>   }
> @@ -2525,7 +2534,6 @@ static void intel_enable_dp(struct intel_encoder *encoder)
>   	struct drm_i915_private *dev_priv = dev->dev_private;
>   	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
>   	uint32_t dp_reg = I915_READ(intel_dp->output_reg);
> -	unsigned int lane_mask = 0x0;
>   
>   	if (WARN_ON(dp_reg & DP_PORT_EN))
>   		return;
> @@ -2543,9 +2551,15 @@ static void intel_enable_dp(struct intel_encoder *encoder)
>   
>   	pps_unlock(intel_dp);
>   
> -	if (IS_VALLEYVIEW(dev))
> +	if (IS_VALLEYVIEW(dev)) {
> +		unsigned int lane_mask = 0x0;
> +
> +		if (IS_CHERRYVIEW(dev))
> +			lane_mask = intel_dp_unused_lane_mask(crtc->config->lane_count);
> +
>   		vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp),
>   				    lane_mask);
> +	}
>   
>   	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>   	intel_dp_start_link_train(intel_dp);
> @@ -2772,31 +2786,40 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>   	val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
> -	val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
> +		val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
> +	}
>   
>   	/* Deassert soft data lane reset*/
>   	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
>   	val |= CHV_PCS_REQ_SOFTRESET_EN;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> +		val |= CHV_PCS_REQ_SOFTRESET_EN;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> +	}
>   
>   	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
>   	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> +		val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	}
>   
>   	/* Program Tx lane latency optimal setting*/
> -	for (i = 0; i < 4; i++) {
> +	for (i = 0; i < intel_crtc->config->lane_count; i++) {
>   		/* Set the upar bit */
> -		data = (i == 1) ? 0x0 : 0x1;
> +		if (intel_crtc->config->lane_count == 1)
> +			data = 0x0;
> +		else
> +			data = (i == 1) ? 0x0 : 0x1;
>   		vlv_dpio_write(dev_priv, pipe, CHV_TX_DW14(ch, i),
>   				data << DPIO_UPAR_SHIFT);
>   	}
> @@ -2817,9 +2840,11 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>   	val |= DPIO_TX2_STAGGER_MASK(0x1f);
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
> -	val |= DPIO_TX2_STAGGER_MASK(0x1f);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch));
> +		val |= DPIO_TX2_STAGGER_MASK(0x1f);
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
> +	}
>   
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch),
>   		       DPIO_LANESTAGGER_STRAP(stagger) |
> @@ -2828,12 +2853,14 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>   		       DPIO_TX1_STAGGER_MULT(6) |
>   		       DPIO_TX2_STAGGER_MULT(0));
>   
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch),
> -		       DPIO_LANESTAGGER_STRAP(stagger) |
> -		       DPIO_LANESTAGGER_STRAP_OVRD |
> -		       DPIO_TX1_STAGGER_MASK(0x1f) |
> -		       DPIO_TX1_STAGGER_MULT(7) |
> -		       DPIO_TX2_STAGGER_MULT(5));
> +	if (intel_crtc->config->lane_count > 2) {
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch),
> +			       DPIO_LANESTAGGER_STRAP(stagger) |
> +			       DPIO_LANESTAGGER_STRAP_OVRD |
> +			       DPIO_TX1_STAGGER_MASK(0x1f) |
> +			       DPIO_TX1_STAGGER_MULT(7) |
> +			       DPIO_TX2_STAGGER_MULT(5));
> +	}
>   
>   	mutex_unlock(&dev_priv->sb_lock);
>   
> @@ -2849,10 +2876,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
>   		to_intel_crtc(encoder->base.crtc);
>   	enum dpio_channel ch = vlv_dport_to_channel(dport);
>   	enum pipe pipe = intel_crtc->pipe;
> +	unsigned int lane_mask =
> +		intel_dp_unused_lane_mask(intel_crtc->config->lane_count);
>   	u32 val;
>   
>   	intel_dp_prepare(encoder);
>   
> +	chv_phy_powergate_lanes(encoder, true, lane_mask);
> +
>   	mutex_lock(&dev_priv->sb_lock);
>   
>   	/* program left/right clock distribution */
> @@ -2883,13 +2914,15 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
>   		val |= CHV_PCS_USEDCLKCHANNEL;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
> -	val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
> -	if (pipe != PIPE_B)
> -		val &= ~CHV_PCS_USEDCLKCHANNEL;
> -	else
> -		val |= CHV_PCS_USEDCLKCHANNEL;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch));
> +		val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE;
> +		if (pipe != PIPE_B)
> +			val &= ~CHV_PCS_USEDCLKCHANNEL;
> +		else
> +			val |= CHV_PCS_USEDCLKCHANNEL;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val);
> +	}
>   
>   	/*
>   	 * This a a bit weird since generally CL
> @@ -2926,6 +2959,8 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
>   	}
>   
>   	mutex_unlock(&dev_priv->sb_lock);
> +
> +	chv_phy_powergate_lanes(encoder, false, 0x0);
>   }
>   
>   /*
> @@ -3261,24 +3296,28 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
>   	val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
> -	val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
> -	val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
> -	val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
> +		val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
> +		val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK);
> +		val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
> +	}
>   
>   	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch));
>   	val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
>   	val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch));
> -	val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
> -	val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch));
> +		val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK);
> +		val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val);
> +	}
>   
>   	/* Program swing deemph */
> -	for (i = 0; i < 4; i++) {
> +	for (i = 0; i < intel_crtc->config->lane_count; i++) {
>   		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW4(ch, i));
>   		val &= ~DPIO_SWING_DEEMPH9P5_MASK;
>   		val |= deemph_reg_value << DPIO_SWING_DEEMPH9P5_SHIFT;
> @@ -3286,7 +3325,7 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
>   	}
>   
>   	/* Program swing margin */
> -	for (i = 0; i < 4; i++) {
> +	for (i = 0; i < intel_crtc->config->lane_count; i++) {
>   		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i));
>   
>   		val &= ~DPIO_SWING_MARGIN000_MASK;
> @@ -3309,7 +3348,7 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
>   	 * For now, for this unique transition scale selection, set bit
>   	 * 27 for ch0 and ch1.
>   	 */
> -	for (i = 0; i < 4; i++) {
> +	for (i = 0; i < intel_crtc->config->lane_count; i++) {
>   		val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i));
>   		if (chv_need_uniq_trans_scale(train_set))
>   			val |= DPIO_TX_UNIQ_TRANS_SCALE_EN;
> @@ -3323,9 +3362,11 @@ static uint32_t chv_signal_levels(struct intel_dp *intel_dp)
>   	val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val);
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
> -	val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
> +	if (intel_crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch));
> +		val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
> +	}
>   
>   	/* LRC Bypass */
>   	val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 23d5e46..f8a16dc 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1370,6 +1370,10 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv);
>   
>   void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
>   
> +void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> +			     bool override, unsigned int mask);
> +
> +
>   /* intel_pm.c */
>   void intel_init_clock_gating(struct drm_device *dev);
>   void intel_suspend_hw(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 86b1a2c..b3f6c9f 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1625,6 +1625,8 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>   
>   	intel_hdmi_prepare(encoder);
>   
> +	chv_phy_powergate_lanes(encoder, true, 0x0);
> +
>   	mutex_lock(&dev_priv->sb_lock);
>   
>   	/* program left/right clock distribution */
> @@ -1698,6 +1700,8 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
>   	}
>   
>   	mutex_unlock(&dev_priv->sb_lock);
> +
> +	chv_phy_powergate_lanes(encoder, false, 0x0);
>   }
>   
>   static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index dab1da9..506a8cc 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -946,14 +946,19 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
>   					   struct i915_power_well *power_well)
>   {
>   	enum dpio_phy phy;
> +	enum pipe pipe;
> +	uint32_t tmp;
>   
>   	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
>   		     power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
>   
> -	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC)
> +	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
> +		pipe = PIPE_A;
>   		phy = DPIO_PHY0;
> -	else
> +	} else {
> +		pipe = PIPE_C;
>   		phy = DPIO_PHY1;
> +	}
>   
>   	/* since ref/cri clock was enabled */
>   	udelay(1); /* >10ns for cmnreset, >0ns for sidereset */
> @@ -963,8 +968,26 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
>   	if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
>   		DRM_ERROR("Display PHY %d is not power up\n", phy);
>   
> +	mutex_lock(&dev_priv->sb_lock);
> +
> +	/* Enable dynamic power down */
> +	tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28);
> +	tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN;
> +	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
> +
> +	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
> +		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
> +		tmp |= DPIO_DYNPWRDOWNEN_CH1;
> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
> +	}
> +
> +	mutex_unlock(&dev_priv->sb_lock);
> +
>   	dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
>   	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> +
> +	DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
> +		      phy, dev_priv->chv_phy_control);
>   }
>   
>   static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> @@ -988,6 +1011,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
>   	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
>   
>   	vlv_set_power_well(dev_priv, power_well, false);
> +
> +	DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
> +		      phy, dev_priv->chv_phy_control);
> +}
> +
> +void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> +			     bool override, unsigned int mask)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	enum dpio_phy phy = vlv_dport_to_phy(enc_to_dig_port(&encoder->base));
> +	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
> +
> +	mutex_lock(&power_domains->lock);
> +
> +	dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD(0xf, phy, ch);
> +	dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD(mask, phy, ch);
> +
> +	if (override)
> +		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> +	else
> +		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> +
> +	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> +
> +	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
> +		      phy, ch, mask, dev_priv->chv_phy_control);
> +
> +	mutex_unlock(&power_domains->lock);
>   }
>   
>   static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
> @@ -1620,19 +1672,72 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
>   	 * DISPLAY_PHY_CONTROL can get corrupted if read. As a
>   	 * workaround never ever read DISPLAY_PHY_CONTROL, and
>   	 * instead maintain a shadow copy ourselves. Use the actual
> -	 * power well state to reconstruct the expected initial
> -	 * value.
> +	 * power well state and lane status to reconstruct the
> +	 * expected initial value.
>   	 */
>   	dev_priv->chv_phy_control =
>   		PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY0) |
>   		PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY1) |
> -		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH0) |
> -		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH1) |
> -		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY1, DPIO_CH0);
> -	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc))
> +		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH0) |
> +		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH1) |
> +		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY1, DPIO_CH0);
> +
> +	/*
> +	 * If all lanes are disabled we leave the override disabled
> +	 * with all power down bits cleared to match the state we
> +	 * would use after disabling the port. Otherwise enable the
> +	 * override and set the lane powerdown bits accding to the
> +	 * current lane status.
> +	 */
> +	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
> +		uint32_t status = I915_READ(DPLL(PIPE_A));
> +		unsigned int mask;
> +
> +		mask = status & DPLL_PORTB_READY_MASK;
> +		if (mask == 0xf)
> +			mask = 0x0;
> +		else
> +			dev_priv->chv_phy_control |=
> +				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0);
> +
> +		dev_priv->chv_phy_control |=
> +			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH0);
> +
> +		mask = (status & DPLL_PORTC_READY_MASK) >> 4;
> +		if (mask == 0xf)
> +			mask = 0x0;
> +		else
> +			dev_priv->chv_phy_control |=
> +				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1);
> +
> +		dev_priv->chv_phy_control |=
> +			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1);
> +
>   		dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0);
> -	if (cmn_d->ops->is_enabled(dev_priv, cmn_d))
> +	}
> +
> +	if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
> +		uint32_t status = I915_READ(DPIO_PHY_STATUS);
> +		unsigned int mask;
> +
> +		mask = status & DPLL_PORTD_READY_MASK;
> +
> +		if (mask == 0xf)
> +			mask = 0x0;
> +		else
> +			dev_priv->chv_phy_control |=
> +				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0);
> +
> +		dev_priv->chv_phy_control |=
> +			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0);
> +
>   		dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1);
> +	}
> +
> +	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> +
> +	DRM_DEBUG_KMS("Initial PHY_CONTROL=0x%08x\n",
> +		      dev_priv->chv_phy_control);
>   }
>   
>   static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
Looks fine i think we have covered all the scenarios.
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B
  2015-07-08 20:45 ` [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B ville.syrjala
@ 2015-08-19  2:17   ` Deepak
  2015-08-19 11:29     ` Ville Syrjälä
  0 siblings, 1 reply; 50+ messages in thread
From: Deepak @ 2015-08-19  2:17 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Normmally the common lane in a PHY channel gets powered up when some
> of the data lanes get powered up. But when we're driving port B with
> pipe B we don't want to enabled any of the data lanes, and just want
> the DPLL in the common lane to be active.
>
> To make that happens we have to temporarily enable some data lanes
> after which we can access the DPLL registers in the common lane. Once
> the pipe is up and running we can drop the power override on the data
> lanes allowing them to shut down. From this point forward the common
> lane will in fact stay powered on until the data lanes in the other
> channel get powered down.
Patch looks fine. It does what it says. One Q, why only for port B? Port 
C is also in same common lane right?
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_dp.c         | 23 +++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_drv.h        |  3 +++
>   drivers/gpu/drm/i915/intel_hdmi.c       | 23 +++++++++++++++++++++++
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++++++++++++
>   4 files changed, 78 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 6058129..8d088f3 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2865,6 +2865,12 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>   	mutex_unlock(&dev_priv->sb_lock);
>   
>   	intel_enable_dp(encoder);
> +
> +	/* Second common lane will stay alive on its own now */
> +	if (dport->release_cl2_override) {
> +		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
> +		dport->release_cl2_override = false;
> +	}
>   }
>   
>   static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
> @@ -2882,6 +2888,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
>   
>   	intel_dp_prepare(encoder);
>   
> +	/*
> +	 * Must trick the second common lane into life.
> +	 * Otherwise we can't even access the PLL.
> +	 */
> +	if (ch == DPIO_CH0 && pipe == PIPE_B)
> +		dport->release_cl2_override =
> +			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
> +
>   	chv_phy_powergate_lanes(encoder, true, lane_mask);
>   
>   	mutex_lock(&dev_priv->sb_lock);
> @@ -2960,6 +2974,15 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
>   
>   	mutex_unlock(&dev_priv->sb_lock);
>   
> +	/*
> +	 * Leave the power down bit cleared for at least one
> +	 * lane so that chv_powergate_phy_ch() will power
> +	 * on something when the channel is otherwise unused.
> +	 * When the port is off and the override is removed
> +	 * the lanes power down anyway, so otherwise it doesn't
> +	 * really matter what the state of power down bits is
> +	 * after this.
> +	 */
>   	chv_phy_powergate_lanes(encoder, false, 0x0);
>   }
>   
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index f8a16dc..6133a98 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -782,6 +782,7 @@ struct intel_digital_port {
>   	struct intel_dp dp;
>   	struct intel_hdmi hdmi;
>   	enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
> +	bool release_cl2_override;
>   };
>   
>   struct intel_dp_mst_encoder {
> @@ -1372,6 +1373,8 @@ void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
>   
>   void chv_phy_powergate_lanes(struct intel_encoder *encoder,
>   			     bool override, unsigned int mask);
> +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> +			  enum dpio_channel ch, bool override);
>   
>   
>   /* intel_pm.c */
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index b3f6c9f..4b604ee 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1625,6 +1625,14 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>   
>   	intel_hdmi_prepare(encoder);
>   
> +	/*
> +	 * Must trick the second common lane into life.
> +	 * Otherwise we can't even access the PLL.
> +	 */
> +	if (ch == DPIO_CH0 && pipe == PIPE_B)
> +		dport->release_cl2_override =
> +			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
> +
>   	chv_phy_powergate_lanes(encoder, true, 0x0);
>   
>   	mutex_lock(&dev_priv->sb_lock);
> @@ -1701,6 +1709,15 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
>   
>   	mutex_unlock(&dev_priv->sb_lock);
>   
> +	/*
> +	 * Leave the power down bit cleared for at least one
> +	 * lane so that chv_powergate_phy_ch() will power
> +	 * on something when the channel is otherwise unused.
> +	 * When the port is off and the override is removed
> +	 * the lanes power down anyway, so otherwise it doesn't
> +	 * really matter what the state of power down bits is
> +	 * after this.
> +	 */
>   	chv_phy_powergate_lanes(encoder, false, 0x0);
>   }
>   
> @@ -1922,6 +1939,12 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
>   	g4x_enable_hdmi(encoder);
>   
>   	vlv_wait_port_ready(dev_priv, dport, 0x0);
> +
> +	/* Second common lane will stay alive on its own now */
> +	if (dport->release_cl2_override) {
> +		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
> +		dport->release_cl2_override = false;
> +	}
>   }
>   
>   static void intel_hdmi_destroy(struct drm_connector *connector)
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 506a8cc..551cf08 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -1016,6 +1016,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
>   		      phy, dev_priv->chv_phy_control);
>   }
>   
> +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> +			  enum dpio_channel ch, bool override)
> +{
> +	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	bool was_override;
> +
> +	mutex_lock(&power_domains->lock);
> +
> +	was_override = dev_priv->chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> +
> +	if (override == was_override)
> +		goto out;
> +
> +	if (override)
> +		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> +	else
> +		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> +
> +	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> +
> +	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
> +		      phy, ch, dev_priv->chv_phy_control);
> +
> +out:
> +	mutex_unlock(&power_domains->lock);
> +
> +	return was_override;
> +}
> +
>   void chv_phy_powergate_lanes(struct intel_encoder *encoder,
>   			     bool override, unsigned int mask)
>   {

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

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

* Re: [PATCH 10/15] drm/i915: Force common lane on for the PPS kick on CHV
  2015-07-08 20:45 ` [PATCH 10/15] drm/i915: Force common lane on for the PPS kick on CHV ville.syrjala
  2015-07-10  7:56   ` [PATCH v2 " ville.syrjala
@ 2015-08-19  2:21   ` Deepak
  2015-08-19 11:32     ` Ville Syrjälä
  1 sibling, 1 reply; 50+ messages in thread
From: Deepak @ 2015-08-19  2:21 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> With DPIO powergating active the DPLL can't be accessed unless
> something else is keeping the common lane in the channel on.
> That means the PPS kick procedure could fail to enable the PLL.
>
> Power up some data lanes to force the common lane to power up
> so that the PLL can be enabled temporarily.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_dp.c | 16 +++++++++++++---
>   1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 8d088f3..817df87 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -341,7 +341,9 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
>   	struct drm_device *dev = intel_dig_port->base.base.dev;
>   	struct drm_i915_private *dev_priv = dev->dev_private;
>   	enum pipe pipe = intel_dp->pps_pipe;
> -	bool pll_enabled;
> +	bool pll_enabled, release_cl_override;
> +	enum dpio_phy phy = DPIO_PHY(pipe);
> +	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
>   	uint32_t DP;
>   
>   	if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,
> @@ -371,9 +373,13 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
>   	 * The DPLL for the pipe must be enabled for this to work.
>   	 * So enable temporarily it if it's not already enabled.
>   	 */
> -	if (!pll_enabled)
> +	if (!pll_enabled) {
> +		release_cl_override = IS_CHERRYVIEW(dev) &&
> +			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
> +
>   		vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
>   				 &chv_dpll[0].dpll : &vlv_dpll[0].dpll);
> +	}
>   
>   	/*
>   	 * Similar magic as in intel_dp_enable_port().
> @@ -390,8 +396,12 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
>   	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
>   	POSTING_READ(intel_dp->output_reg);
>   
> -	if (!pll_enabled)
> +	if (!pll_enabled) {
>   		vlv_force_pll_off(dev, pipe);
> +
> +		if (release_cl_override)
> +			chv_phy_powergate_ch(dev_priv, phy, ch, false);
> +	}
>   }
>   
>   static enum pipe
Change looks fine
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B
  2015-08-19  2:17   ` Deepak
@ 2015-08-19 11:29     ` Ville Syrjälä
  2015-08-26 12:36       ` Daniel Vetter
  0 siblings, 1 reply; 50+ messages in thread
From: Ville Syrjälä @ 2015-08-19 11:29 UTC (permalink / raw)
  To: Deepak; +Cc: intel-gfx

On Wed, Aug 19, 2015 at 07:47:41AM +0530, Deepak wrote:
> 
> 
> On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Normmally the common lane in a PHY channel gets powered up when some
> > of the data lanes get powered up. But when we're driving port B with
> > pipe B we don't want to enabled any of the data lanes, and just want
> > the DPLL in the common lane to be active.
> >
> > To make that happens we have to temporarily enable some data lanes
> > after which we can access the DPLL registers in the common lane. Once
> > the pipe is up and running we can drop the power override on the data
> > lanes allowing them to shut down. From this point forward the common
> > lane will in fact stay powered on until the data lanes in the other
> > channel get powered down.
> Patch looks fine. It does what it says. One Q, why only for port B? Port 
> C is also in same common lane right?

Port B is in the first PHY channel which also houses CL1. CL1 always
powers up whenever any lanes in either PHY channel are powered up.
CL2 only powers up if lanes in the second channel (ie. the one with
port C) powers up.

So in this scenario (pipe B->port B) we want the DPLL from CL2, but
ideally we only want to power up the lanes for port B. Powering up
port B lanes will only power up CL1, but as we need CL2 instead we
need to, temporarily, power up some lanes in port C as well.

Crossing the streams the other way (pipe A->port C) is not a problem
since CL1 powers up whenever anything else powers up. So powering up
some port C lanes is enough on its own to make the CL1 DPLL
operational, even though CL1 and the lanes live in separate channels.

> Reviewed-by: Deepak S <deepak.s@linux.intel.com>
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >   drivers/gpu/drm/i915/intel_dp.c         | 23 +++++++++++++++++++++++
> >   drivers/gpu/drm/i915/intel_drv.h        |  3 +++
> >   drivers/gpu/drm/i915/intel_hdmi.c       | 23 +++++++++++++++++++++++
> >   drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++++++++++++
> >   4 files changed, 78 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 6058129..8d088f3 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -2865,6 +2865,12 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
> >   	mutex_unlock(&dev_priv->sb_lock);
> >   
> >   	intel_enable_dp(encoder);
> > +
> > +	/* Second common lane will stay alive on its own now */
> > +	if (dport->release_cl2_override) {
> > +		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
> > +		dport->release_cl2_override = false;
> > +	}
> >   }
> >   
> >   static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
> > @@ -2882,6 +2888,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
> >   
> >   	intel_dp_prepare(encoder);
> >   
> > +	/*
> > +	 * Must trick the second common lane into life.
> > +	 * Otherwise we can't even access the PLL.
> > +	 */
> > +	if (ch == DPIO_CH0 && pipe == PIPE_B)
> > +		dport->release_cl2_override =
> > +			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
> > +
> >   	chv_phy_powergate_lanes(encoder, true, lane_mask);
> >   
> >   	mutex_lock(&dev_priv->sb_lock);
> > @@ -2960,6 +2974,15 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
> >   
> >   	mutex_unlock(&dev_priv->sb_lock);
> >   
> > +	/*
> > +	 * Leave the power down bit cleared for at least one
> > +	 * lane so that chv_powergate_phy_ch() will power
> > +	 * on something when the channel is otherwise unused.
> > +	 * When the port is off and the override is removed
> > +	 * the lanes power down anyway, so otherwise it doesn't
> > +	 * really matter what the state of power down bits is
> > +	 * after this.
> > +	 */
> >   	chv_phy_powergate_lanes(encoder, false, 0x0);
> >   }
> >   
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > index f8a16dc..6133a98 100644
> > --- a/drivers/gpu/drm/i915/intel_drv.h
> > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > @@ -782,6 +782,7 @@ struct intel_digital_port {
> >   	struct intel_dp dp;
> >   	struct intel_hdmi hdmi;
> >   	enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
> > +	bool release_cl2_override;
> >   };
> >   
> >   struct intel_dp_mst_encoder {
> > @@ -1372,6 +1373,8 @@ void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
> >   
> >   void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> >   			     bool override, unsigned int mask);
> > +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> > +			  enum dpio_channel ch, bool override);
> >   
> >   
> >   /* intel_pm.c */
> > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > index b3f6c9f..4b604ee 100644
> > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > @@ -1625,6 +1625,14 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
> >   
> >   	intel_hdmi_prepare(encoder);
> >   
> > +	/*
> > +	 * Must trick the second common lane into life.
> > +	 * Otherwise we can't even access the PLL.
> > +	 */
> > +	if (ch == DPIO_CH0 && pipe == PIPE_B)
> > +		dport->release_cl2_override =
> > +			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
> > +
> >   	chv_phy_powergate_lanes(encoder, true, 0x0);
> >   
> >   	mutex_lock(&dev_priv->sb_lock);
> > @@ -1701,6 +1709,15 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
> >   
> >   	mutex_unlock(&dev_priv->sb_lock);
> >   
> > +	/*
> > +	 * Leave the power down bit cleared for at least one
> > +	 * lane so that chv_powergate_phy_ch() will power
> > +	 * on something when the channel is otherwise unused.
> > +	 * When the port is off and the override is removed
> > +	 * the lanes power down anyway, so otherwise it doesn't
> > +	 * really matter what the state of power down bits is
> > +	 * after this.
> > +	 */
> >   	chv_phy_powergate_lanes(encoder, false, 0x0);
> >   }
> >   
> > @@ -1922,6 +1939,12 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
> >   	g4x_enable_hdmi(encoder);
> >   
> >   	vlv_wait_port_ready(dev_priv, dport, 0x0);
> > +
> > +	/* Second common lane will stay alive on its own now */
> > +	if (dport->release_cl2_override) {
> > +		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
> > +		dport->release_cl2_override = false;
> > +	}
> >   }
> >   
> >   static void intel_hdmi_destroy(struct drm_connector *connector)
> > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > index 506a8cc..551cf08 100644
> > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > @@ -1016,6 +1016,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> >   		      phy, dev_priv->chv_phy_control);
> >   }
> >   
> > +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> > +			  enum dpio_channel ch, bool override)
> > +{
> > +	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> > +	bool was_override;
> > +
> > +	mutex_lock(&power_domains->lock);
> > +
> > +	was_override = dev_priv->chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > +
> > +	if (override == was_override)
> > +		goto out;
> > +
> > +	if (override)
> > +		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > +	else
> > +		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > +
> > +	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> > +
> > +	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
> > +		      phy, ch, dev_priv->chv_phy_control);
> > +
> > +out:
> > +	mutex_unlock(&power_domains->lock);
> > +
> > +	return was_override;
> > +}
> > +
> >   void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> >   			     bool override, unsigned int mask)
> >   {
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 10/15] drm/i915: Force common lane on for the PPS kick on CHV
  2015-08-19  2:21   ` [PATCH " Deepak
@ 2015-08-19 11:32     ` Ville Syrjälä
  0 siblings, 0 replies; 50+ messages in thread
From: Ville Syrjälä @ 2015-08-19 11:32 UTC (permalink / raw)
  To: Deepak; +Cc: intel-gfx

On Wed, Aug 19, 2015 at 07:51:57AM +0530, Deepak wrote:
> 
> 
> On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > With DPIO powergating active the DPLL can't be accessed unless
> > something else is keeping the common lane in the channel on.
> > That means the PPS kick procedure could fail to enable the PLL.
> >
> > Power up some data lanes to force the common lane to power up
> > so that the PLL can be enabled temporarily.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >   drivers/gpu/drm/i915/intel_dp.c | 16 +++++++++++++---
> >   1 file changed, 13 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 8d088f3..817df87 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -341,7 +341,9 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
> >   	struct drm_device *dev = intel_dig_port->base.base.dev;
> >   	struct drm_i915_private *dev_priv = dev->dev_private;
> >   	enum pipe pipe = intel_dp->pps_pipe;
> > -	bool pll_enabled;
> > +	bool pll_enabled, release_cl_override;
> > +	enum dpio_phy phy = DPIO_PHY(pipe);
> > +	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
> >   	uint32_t DP;
> >   
> >   	if (WARN(I915_READ(intel_dp->output_reg) & DP_PORT_EN,
> > @@ -371,9 +373,13 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
> >   	 * The DPLL for the pipe must be enabled for this to work.
> >   	 * So enable temporarily it if it's not already enabled.
> >   	 */
> > -	if (!pll_enabled)
> > +	if (!pll_enabled) {
> > +		release_cl_override = IS_CHERRYVIEW(dev) &&
> > +			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
> > +
> >   		vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ?
> >   				 &chv_dpll[0].dpll : &vlv_dpll[0].dpll);
> > +	}
> >   
> >   	/*
> >   	 * Similar magic as in intel_dp_enable_port().
> > @@ -390,8 +396,12 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
> >   	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
> >   	POSTING_READ(intel_dp->output_reg);
> >   
> > -	if (!pll_enabled)
> > +	if (!pll_enabled) {
> >   		vlv_force_pll_off(dev, pipe);
> > +
> > +		if (release_cl_override)
> > +			chv_phy_powergate_ch(dev_priv, phy, ch, false);
> > +	}
> >   }
> >   
> >   static enum pipe
> Change looks fine
> Reviewed-by: Deepak S <deepak.s@linux.intel.com>

Note to Daniel: Please pick up v2 of this patch. The only change
was release_cl_override=false initialization to avoid a gcc warning.

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 11/15] drm/i915: Enable DPIO SUS clock gating on CHV
  2015-07-08 20:45 ` [PATCH 11/15] drm/i915: Enable DPIO SUS clock gating " ville.syrjala
@ 2015-08-19 13:09   ` Deepak
  0 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-19 13:09 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> CHV has supports some form of automagic clock gating for the
> DPIO SUS clock. We can simply enable the magic bits and the
> hardware should take care of the rest.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_reg.h         | 4 ++++
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 3 ++-
>   2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index bcfcbb62..8010200 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1133,6 +1133,10 @@ enum skl_disp_power_wells {
>   #define CHV_CMN_DW28			0x8170
>   #define   DPIO_CL1POWERDOWNEN		(1 << 23)
>   #define   DPIO_DYNPWRDOWNEN_CH0		(1 << 22)
> +#define   DPIO_SUS_CLK_CONFIG_ON		(0 << 0)
> +#define   DPIO_SUS_CLK_CONFIG_CLKREQ		(1 << 0)
> +#define   DPIO_SUS_CLK_CONFIG_GATE		(2 << 0)
> +#define   DPIO_SUS_CLK_CONFIG_GATE_CLKREQ	(3 << 0)
>   
>   #define CHV_CMN_DW30			0x8178
>   #define   DPIO_LRC_BYPASS		(1 << 3)
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 551cf08..37e4375 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -972,7 +972,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
>   
>   	/* Enable dynamic power down */
>   	tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28);
> -	tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN;
> +	tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN |
> +		DPIO_SUS_CLK_CONFIG_GATE_CLKREQ;
>   	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
>   
>   	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
Changes looks fine as per Bspec.
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 12/15] drm/i915: Force CL2 off in CHV x1 PHY
  2015-07-08 20:45 ` [PATCH 12/15] drm/i915: Force CL2 off in CHV x1 PHY ville.syrjala
@ 2015-08-19 13:22   ` Deepak
  2015-08-19 13:39     ` Ville Syrjälä
  0 siblings, 1 reply; 50+ messages in thread
From: Deepak @ 2015-08-19 13:22 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We can choose to leave the display PHY CL2 powerdown up to some hardware
> signals, or we can force it. The BXT code forces the nonexistent CL2 in
> the x1 PHY to power down. Follow suit on CHV. Maybe it can still save
> some extra power by disabling some extra logic in CL1, or something.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_reg.h         | 1 +
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 9 +++++++++
>   2 files changed, 10 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 8010200..395f556 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1139,6 +1139,7 @@ enum skl_disp_power_wells {
>   #define   DPIO_SUS_CLK_CONFIG_GATE_CLKREQ	(3 << 0)
>   
>   #define CHV_CMN_DW30			0x8178
> +#define   DPIO_CL2_LDOFUSE_PWRENB	(1 << 6)
>   #define   DPIO_LRC_BYPASS		(1 << 3)
>   
>   #define _TXLANE(ch, lane, offset) ((ch ? 0x2400 : 0) + \
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 37e4375..002b78f 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -980,6 +980,15 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
>   		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
>   		tmp |= DPIO_DYNPWRDOWNEN_CH1;
>   		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
> +	} else {
> +		/*
> +		 * Force the non-existing CL2 off. BXT does this
> +		 * too, so maybe it saves some power even though
> +		 * CL2 doesn't exist?
> +		 */
> +		tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
> +		tmp |= DPIO_CL2_LDOFUSE_PWRENB;
> +		vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, tmp);
>   	}
>   
Do we need to turn off CL2 each time we enable dpio cmn power wells?

btw, changes looks fine
Reviewed-by: Deepak S <deepak.s@linux.intel.com>


>   	mutex_unlock(&dev_priv->sb_lock);

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

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

* Re: [PATCH 12/15] drm/i915: Force CL2 off in CHV x1 PHY
  2015-08-19 13:22   ` Deepak
@ 2015-08-19 13:39     ` Ville Syrjälä
  2015-08-26 12:38       ` Daniel Vetter
  0 siblings, 1 reply; 50+ messages in thread
From: Ville Syrjälä @ 2015-08-19 13:39 UTC (permalink / raw)
  To: Deepak; +Cc: intel-gfx

On Wed, Aug 19, 2015 at 06:52:57PM +0530, Deepak wrote:
> 
> 
> On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > We can choose to leave the display PHY CL2 powerdown up to some hardware
> > signals, or we can force it. The BXT code forces the nonexistent CL2 in
> > the x1 PHY to power down. Follow suit on CHV. Maybe it can still save
> > some extra power by disabling some extra logic in CL1, or something.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >   drivers/gpu/drm/i915/i915_reg.h         | 1 +
> >   drivers/gpu/drm/i915/intel_runtime_pm.c | 9 +++++++++
> >   2 files changed, 10 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 8010200..395f556 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -1139,6 +1139,7 @@ enum skl_disp_power_wells {
> >   #define   DPIO_SUS_CLK_CONFIG_GATE_CLKREQ	(3 << 0)
> >   
> >   #define CHV_CMN_DW30			0x8178
> > +#define   DPIO_CL2_LDOFUSE_PWRENB	(1 << 6)
> >   #define   DPIO_LRC_BYPASS		(1 << 3)
> >   
> >   #define _TXLANE(ch, lane, offset) ((ch ? 0x2400 : 0) + \
> > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > index 37e4375..002b78f 100644
> > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > @@ -980,6 +980,15 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
> >   		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
> >   		tmp |= DPIO_DYNPWRDOWNEN_CH1;
> >   		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
> > +	} else {
> > +		/*
> > +		 * Force the non-existing CL2 off. BXT does this
> > +		 * too, so maybe it saves some power even though
> > +		 * CL2 doesn't exist?
> > +		 */
> > +		tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
> > +		tmp |= DPIO_CL2_LDOFUSE_PWRENB;
> > +		vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, tmp);
> >   	}
> >   
> Do we need to turn off CL2 each time we enable dpio cmn power wells?

Yes, all DPIO registers lose their state when the power well is off.

> 
> btw, changes looks fine
> Reviewed-by: Deepak S <deepak.s@linux.intel.com>
> 
> 
> >   	mutex_unlock(&dev_priv->sb_lock);
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV
  2015-08-17 11:45     ` Ville Syrjälä
@ 2015-08-26  8:11       ` Deepak
  0 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-26  8:11 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx



On 08/17/2015 05:15 PM, Ville Syrjälä wrote:
> On Mon, Aug 17, 2015 at 07:49:41AM +0530, Deepak wrote:
>>
>> On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> When fractional m2 divider isn't used on CHV the fractional part
>>> is ignore by the hardware. Despite that, program the fractional
>>> value (0 in this case) to the hardware register just to keep
>>> things a bit more consistent. Might at least make register dumps
>>> a bit less confusing when there isn't some stale fractional part
>>> hanging around.
>>>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/intel_display.c | 3 +--
>>>    1 file changed, 1 insertion(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 0b2ad76..3df9cb2 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -7393,8 +7393,7 @@ static void chv_prepare_pll(struct intel_crtc *crtc,
>>>    			1 << DPIO_CHV_N_DIV_SHIFT);
>>>    
>>>    	/* M2 fraction division */
>>> -	if (bestm2_frac)
>>> -		vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
>>> +	vlv_dpio_write(dev_priv, pipe, CHV_PLL_DW2(port), bestm2_frac);
>>>    
>>>    	/* M2 fraction division enable */
>>>    	dpio_val = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port));
>> Since we do not use fractional m2 driver in chv, can we remove other
>> bestm2_frac used in chv pll function?
>> like
>> if (bestm2_frac)
>>       dpio_val |= DPIO_CHV_FRAC_DIV_EN;
>>
>> &
>> if (!bestm2_frac)
>>       dpio_val |= DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE;
>>
>> Do we need this?
> We do use the fractional divider, when it's not 0.
>
Ok thanks...
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 03/15] drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there
  2015-08-17 11:53     ` Ville Syrjälä
@ 2015-08-26  8:14       ` Deepak
  0 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-26  8:14 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx



On 08/17/2015 05:23 PM, Ville Syrjälä wrote:
> On Mon, Aug 17, 2015 at 09:46:01AM +0530, Deepak wrote:
>>
>> On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> Move the CHV clock buffer disable from chv_disable_pll() to the new
>>> encoder .post_pll_disable() hook. This is more symmetric since the
>>> clock buffer enable happens from the .pre_pll_enable() hook.
>>>
>>> We'll have more use for the new hook soon.
>>>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/intel_display.c | 15 ++++-----------
>>>    drivers/gpu/drm/i915/intel_dp.c      | 23 +++++++++++++++++++++++
>>>    drivers/gpu/drm/i915/intel_drv.h     |  1 +
>>>    drivers/gpu/drm/i915/intel_hdmi.c    | 23 +++++++++++++++++++++++
>>>    4 files changed, 51 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
>>> index 3df9cb2..db518a7 100644
>>> --- a/drivers/gpu/drm/i915/intel_display.c
>>> +++ b/drivers/gpu/drm/i915/intel_display.c
>>> @@ -1851,17 +1851,6 @@ static void chv_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
>>>    	val &= ~DPIO_DCLKP_EN;
>>>    	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW14(port), val);
>>>    
>>> -	/* disable left/right clock distribution */
>>> -	if (pipe != PIPE_B) {
>>> -		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
>>> -		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
>>> -		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
>>> -	} else {
>>> -		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
>>> -		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
>>> -		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
>>> -	}
>>> -
>>>    	mutex_unlock(&dev_priv->sb_lock);
>>>    }
>>>    
>>> @@ -6171,6 +6160,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
>>>    			i9xx_disable_pll(intel_crtc);
>>>    	}
>>>    
>>> +	for_each_encoder_on_crtc(dev, crtc, encoder)
>>> +		if (encoder->post_pll_disable)
>>> +			encoder->post_pll_disable(encoder);
>>> +
>> We call "vlv_force_pll_off" in vlv_power_sequencer_kick which call
>> chv_disablepll.
>> Should we add the "post_pll_disable"in force pll off?
> Nope. .post_pll_disable() is the counterpart to .pre_pll_enable() which
> we don't use either in the pps kick procedure.
>
> Apparently we don't need to concern ourselves with the clock
> channel/districtution setp to make the pps kick work. Well, it's either
> that, or we've just been lucky and those end up being set up in a good
> way by accident. But now that you mention it, I do start wonder a bit
> how it really works. So this is probably something I should test more
> thoroughly at some point.
Thanks Ville, Yes we need to do more testing around pps kick. for now 
changes looks fine with matching pre/post

Reviewed-by: Deepak S <deepak.s@linux.intel.com>
>>>    	if (!IS_GEN2(dev))
>>>    		intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false);
>>>    }
>>> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>>> index 32d7e43..40b8430 100644
>>> --- a/drivers/gpu/drm/i915/intel_dp.c
>>> +++ b/drivers/gpu/drm/i915/intel_dp.c
>>> @@ -2906,6 +2906,28 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
>>>    	mutex_unlock(&dev_priv->sb_lock);
>>>    }
>>>    
>>> +static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
>>> +{
>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> +	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
>>> +	u32 val;
>>> +
>>> +	mutex_lock(&dev_priv->sb_lock);
>>> +
>>> +	/* disable left/right clock distribution */
>>> +	if (pipe != PIPE_B) {
>>> +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
>>> +		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
>>> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
>>> +	} else {
>>> +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
>>> +		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
>>> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
>>> +	}
>>> +
>>> +	mutex_unlock(&dev_priv->sb_lock);
>>> +}
>>> +
>>>    /*
>>>     * Native read with retry for link status and receiver capability reads for
>>>     * cases where the sink may still be asleep.
>>> @@ -5931,6 +5953,7 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
>>>    		intel_encoder->pre_enable = chv_pre_enable_dp;
>>>    		intel_encoder->enable = vlv_enable_dp;
>>>    		intel_encoder->post_disable = chv_post_disable_dp;
>>> +		intel_encoder->post_pll_disable = chv_dp_post_pll_disable;
>>>    	} else if (IS_VALLEYVIEW(dev)) {
>>>    		intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable;
>>>    		intel_encoder->pre_enable = vlv_pre_enable_dp;
>>> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
>>> index 4f3b708..42fa135 100644
>>> --- a/drivers/gpu/drm/i915/intel_drv.h
>>> +++ b/drivers/gpu/drm/i915/intel_drv.h
>>> @@ -148,6 +148,7 @@ struct intel_encoder {
>>>    	void (*mode_set)(struct intel_encoder *intel_encoder);
>>>    	void (*disable)(struct intel_encoder *);
>>>    	void (*post_disable)(struct intel_encoder *);
>>> +	void (*post_pll_disable)(struct intel_encoder *);
>>>    	/* Read out the current hw state of this connector, returning true if
>>>    	 * the encoder is active. If the encoder is enabled it also set the pipe
>>>    	 * it is connected to in the pipe parameter. */
>>> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
>>> index 9f79afb..86b1a2c 100644
>>> --- a/drivers/gpu/drm/i915/intel_hdmi.c
>>> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
>>> @@ -1678,6 +1678,28 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>>>    	mutex_unlock(&dev_priv->sb_lock);
>>>    }
>>>    
>>> +static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
>>> +{
>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> +	enum pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe;
>>> +	u32 val;
>>> +
>>> +	mutex_lock(&dev_priv->sb_lock);
>>> +
>>> +	/* disable left/right clock distribution */
>>> +	if (pipe != PIPE_B) {
>>> +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
>>> +		val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK);
>>> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val);
>>> +	} else {
>>> +		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1);
>>> +		val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK);
>>> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
>>> +	}
>>> +
>>> +	mutex_unlock(&dev_priv->sb_lock);
>>> +}
>>> +
>>>    static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
>>>    {
>>>    	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
>>> @@ -2073,6 +2095,7 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port)
>>>    		intel_encoder->pre_enable = chv_hdmi_pre_enable;
>>>    		intel_encoder->enable = vlv_enable_hdmi;
>>>    		intel_encoder->post_disable = chv_hdmi_post_disable;
>>> +		intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable;
>>>    	} else if (IS_VALLEYVIEW(dev)) {
>>>    		intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable;
>>>    		intel_encoder->pre_enable = vlv_hdmi_pre_enable;
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 07/15] drm/i915: Add vlv_dport_to_phy()
  2015-07-08 20:45 ` [PATCH 07/15] drm/i915: Add vlv_dport_to_phy() ville.syrjala
  2015-08-17  4:56   ` Deepak
@ 2015-08-26  8:24   ` Daniel Vetter
  1 sibling, 0 replies; 50+ messages in thread
From: Daniel Vetter @ 2015-08-26  8:24 UTC (permalink / raw)
  To: ville.syrjala; +Cc: DeepakS, deepak.s, intel-gfx

On Wed, Jul 08, 2015 at 11:45:53PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Add vlv_dport_to_phy() and fix up the return values of
> vlv_dport_to_channel() and vlv_pipe_to_channel() to use
> the appropriate enums.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_drv.h | 18 ++++++++++++++++--
>  1 file changed, 16 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 42fa135..23d5e46 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -791,7 +791,7 @@ struct intel_dp_mst_encoder {
>  	void *port; /* store this opaque as its illegal to dereference it */
>  };
>  
> -static inline int
> +static inline enum dpio_channel
>  vlv_dport_to_channel(struct intel_digital_port *dport)
>  {
>  	switch (dport->port) {
> @@ -805,7 +805,21 @@ vlv_dport_to_channel(struct intel_digital_port *dport)
>  	}
>  }
>  
> -static inline int
> +static inline enum dpio_phy
> +vlv_dport_to_phy(struct intel_digital_port *dport)
> +{
> +	switch (dport->port) {
> +	case PORT_B:
> +	case PORT_C:
> +		return DPIO_PHY0;
> +	case PORT_D:
> +		return DPIO_PHY1;
> +	default:
> +		BUG();

BUG considered harmful in modeset code. Can you pls replace this with
something that kills machines less reliable in a follow-up?
-Daniel

> +	}
> +}
> +
> +static inline enum dpio_channel
>  vlv_pipe_to_channel(enum pipe pipe)
>  {
>  	switch (pipe) {
> -- 
> 2.3.6
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 08/15] drm/i915: Implement PHY lane power gating for CHV
  2015-07-08 20:45 ` [PATCH 08/15] drm/i915: Implement PHY lane power gating for CHV ville.syrjala
  2015-08-19  1:48   ` Deepak
@ 2015-08-26  8:27   ` Daniel Vetter
  1 sibling, 0 replies; 50+ messages in thread
From: Daniel Vetter @ 2015-08-26  8:27 UTC (permalink / raw)
  To: ville.syrjala; +Cc: DeepakS, deepak.s, intel-gfx

On Wed, Jul 08, 2015 at 11:45:54PM +0300, ville.syrjala@linux.intel.com wrote:
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index dab1da9..506a8cc 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -946,14 +946,19 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
>  					   struct i915_power_well *power_well)
>  {
>  	enum dpio_phy phy;
> +	enum pipe pipe;
> +	uint32_t tmp;
>  
>  	WARN_ON_ONCE(power_well->data != PUNIT_POWER_WELL_DPIO_CMN_BC &&
>  		     power_well->data != PUNIT_POWER_WELL_DPIO_CMN_D);
>  
> -	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC)
> +	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
> +		pipe = PIPE_A;
>  		phy = DPIO_PHY0;
> -	else
> +	} else {
> +		pipe = PIPE_C;
>  		phy = DPIO_PHY1;
> +	}
>  
>  	/* since ref/cri clock was enabled */
>  	udelay(1); /* >10ns for cmnreset, >0ns for sidereset */

I have some minor context conflicts in this hunk and the next one and it
looks like I'm missing a patch. Since I'm not sure what's going on here
please either rebase or tell me which series I'm missing.

Merged the first 7 patches from this series meanwhile, thanks.
-Daniel

> @@ -963,8 +968,26 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
>  	if (wait_for(I915_READ(DISPLAY_PHY_STATUS) & PHY_POWERGOOD(phy), 1))
>  		DRM_ERROR("Display PHY %d is not power up\n", phy);
>  
> +	mutex_lock(&dev_priv->sb_lock);
> +
> +	/* Enable dynamic power down */
> +	tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW28);
> +	tmp |= DPIO_DYNPWRDOWNEN_CH0 | DPIO_CL1POWERDOWNEN;
> +	vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW28, tmp);
> +
> +	if (power_well->data == PUNIT_POWER_WELL_DPIO_CMN_BC) {
> +		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
> +		tmp |= DPIO_DYNPWRDOWNEN_CH1;
> +		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
> +	}
> +
> +	mutex_unlock(&dev_priv->sb_lock);
> +
>  	dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(phy);
>  	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> +
> +	DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
> +		      phy, dev_priv->chv_phy_control);
>  }
>  
>  static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> @@ -988,6 +1011,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
>  	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
>  
>  	vlv_set_power_well(dev_priv, power_well, false);
> +
> +	DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
> +		      phy, dev_priv->chv_phy_control);
> +}
> +
> +void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> +			     bool override, unsigned int mask)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	enum dpio_phy phy = vlv_dport_to_phy(enc_to_dig_port(&encoder->base));
> +	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
> +
> +	mutex_lock(&power_domains->lock);
> +
> +	dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD(0xf, phy, ch);
> +	dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD(mask, phy, ch);
> +
> +	if (override)
> +		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> +	else
> +		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> +
> +	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> +
> +	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
> +		      phy, ch, mask, dev_priv->chv_phy_control);
> +
> +	mutex_unlock(&power_domains->lock);
>  }
>  
>  static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv,
> @@ -1620,19 +1672,72 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv)
>  	 * DISPLAY_PHY_CONTROL can get corrupted if read. As a
>  	 * workaround never ever read DISPLAY_PHY_CONTROL, and
>  	 * instead maintain a shadow copy ourselves. Use the actual
> -	 * power well state to reconstruct the expected initial
> -	 * value.
> +	 * power well state and lane status to reconstruct the
> +	 * expected initial value.
>  	 */
>  	dev_priv->chv_phy_control =
>  		PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY0) |
>  		PHY_LDO_SEQ_DELAY(PHY_LDO_DELAY_600NS, DPIO_PHY1) |
> -		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH0) |
> -		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY0, DPIO_CH1) |
> -		PHY_CH_POWER_MODE(PHY_CH_SU_PSR, DPIO_PHY1, DPIO_CH0);
> -	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc))
> +		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH0) |
> +		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY0, DPIO_CH1) |
> +		PHY_CH_POWER_MODE(PHY_CH_DEEP_PSR, DPIO_PHY1, DPIO_CH0);
> +
> +	/*
> +	 * If all lanes are disabled we leave the override disabled
> +	 * with all power down bits cleared to match the state we
> +	 * would use after disabling the port. Otherwise enable the
> +	 * override and set the lane powerdown bits accding to the
> +	 * current lane status.
> +	 */
> +	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
> +		uint32_t status = I915_READ(DPLL(PIPE_A));
> +		unsigned int mask;
> +
> +		mask = status & DPLL_PORTB_READY_MASK;
> +		if (mask == 0xf)
> +			mask = 0x0;
> +		else
> +			dev_priv->chv_phy_control |=
> +				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0);
> +
> +		dev_priv->chv_phy_control |=
> +			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH0);
> +
> +		mask = (status & DPLL_PORTC_READY_MASK) >> 4;
> +		if (mask == 0xf)
> +			mask = 0x0;
> +		else
> +			dev_priv->chv_phy_control |=
> +				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1);
> +
> +		dev_priv->chv_phy_control |=
> +			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY0, DPIO_CH1);
> +
>  		dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY0);
> -	if (cmn_d->ops->is_enabled(dev_priv, cmn_d))
> +	}
> +
> +	if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
> +		uint32_t status = I915_READ(DPIO_PHY_STATUS);
> +		unsigned int mask;
> +
> +		mask = status & DPLL_PORTD_READY_MASK;
> +
> +		if (mask == 0xf)
> +			mask = 0x0;
> +		else
> +			dev_priv->chv_phy_control |=
> +				PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0);
> +
> +		dev_priv->chv_phy_control |=
> +			PHY_CH_POWER_DOWN_OVRD(mask, DPIO_PHY1, DPIO_CH0);
> +
>  		dev_priv->chv_phy_control |= PHY_COM_LANE_RESET_DEASSERT(DPIO_PHY1);
> +	}
> +
> +	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> +
> +	DRM_DEBUG_KMS("Initial PHY_CONTROL=0x%08x\n",
> +		      dev_priv->chv_phy_control);
>  }
>  
>  static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv)
> -- 
> 2.3.6
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B
  2015-08-19 11:29     ` Ville Syrjälä
@ 2015-08-26 12:36       ` Daniel Vetter
  0 siblings, 0 replies; 50+ messages in thread
From: Daniel Vetter @ 2015-08-26 12:36 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Aug 19, 2015 at 02:29:37PM +0300, Ville Syrjälä wrote:
> On Wed, Aug 19, 2015 at 07:47:41AM +0530, Deepak wrote:
> > 
> > 
> > On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > > Normmally the common lane in a PHY channel gets powered up when some
> > > of the data lanes get powered up. But when we're driving port B with
> > > pipe B we don't want to enabled any of the data lanes, and just want
> > > the DPLL in the common lane to be active.
> > >
> > > To make that happens we have to temporarily enable some data lanes
> > > after which we can access the DPLL registers in the common lane. Once
> > > the pipe is up and running we can drop the power override on the data
> > > lanes allowing them to shut down. From this point forward the common
> > > lane will in fact stay powered on until the data lanes in the other
> > > channel get powered down.
> > Patch looks fine. It does what it says. One Q, why only for port B? Port 
> > C is also in same common lane right?
> 
> Port B is in the first PHY channel which also houses CL1. CL1 always
> powers up whenever any lanes in either PHY channel are powered up.
> CL2 only powers up if lanes in the second channel (ie. the one with
> port C) powers up.
> 
> So in this scenario (pipe B->port B) we want the DPLL from CL2, but
> ideally we only want to power up the lanes for port B. Powering up
> port B lanes will only power up CL1, but as we need CL2 instead we
> need to, temporarily, power up some lanes in port C as well.
> 
> Crossing the streams the other way (pipe A->port C) is not a problem
> since CL1 powers up whenever anything else powers up. So powering up
> some port C lanes is enough on its own to make the CL1 DPLL
> operational, even though CL1 and the lanes live in separate channels.

I added this to the commit message when merging, seemed useful for the
future.
-Daniel

> 
> > Reviewed-by: Deepak S <deepak.s@linux.intel.com>
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >   drivers/gpu/drm/i915/intel_dp.c         | 23 +++++++++++++++++++++++
> > >   drivers/gpu/drm/i915/intel_drv.h        |  3 +++
> > >   drivers/gpu/drm/i915/intel_hdmi.c       | 23 +++++++++++++++++++++++
> > >   drivers/gpu/drm/i915/intel_runtime_pm.c | 29 +++++++++++++++++++++++++++++
> > >   4 files changed, 78 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index 6058129..8d088f3 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -2865,6 +2865,12 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
> > >   	mutex_unlock(&dev_priv->sb_lock);
> > >   
> > >   	intel_enable_dp(encoder);
> > > +
> > > +	/* Second common lane will stay alive on its own now */
> > > +	if (dport->release_cl2_override) {
> > > +		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
> > > +		dport->release_cl2_override = false;
> > > +	}
> > >   }
> > >   
> > >   static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
> > > @@ -2882,6 +2888,14 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
> > >   
> > >   	intel_dp_prepare(encoder);
> > >   
> > > +	/*
> > > +	 * Must trick the second common lane into life.
> > > +	 * Otherwise we can't even access the PLL.
> > > +	 */
> > > +	if (ch == DPIO_CH0 && pipe == PIPE_B)
> > > +		dport->release_cl2_override =
> > > +			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
> > > +
> > >   	chv_phy_powergate_lanes(encoder, true, lane_mask);
> > >   
> > >   	mutex_lock(&dev_priv->sb_lock);
> > > @@ -2960,6 +2974,15 @@ static void chv_dp_post_pll_disable(struct intel_encoder *encoder)
> > >   
> > >   	mutex_unlock(&dev_priv->sb_lock);
> > >   
> > > +	/*
> > > +	 * Leave the power down bit cleared for at least one
> > > +	 * lane so that chv_powergate_phy_ch() will power
> > > +	 * on something when the channel is otherwise unused.
> > > +	 * When the port is off and the override is removed
> > > +	 * the lanes power down anyway, so otherwise it doesn't
> > > +	 * really matter what the state of power down bits is
> > > +	 * after this.
> > > +	 */
> > >   	chv_phy_powergate_lanes(encoder, false, 0x0);
> > >   }
> > >   
> > > diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> > > index f8a16dc..6133a98 100644
> > > --- a/drivers/gpu/drm/i915/intel_drv.h
> > > +++ b/drivers/gpu/drm/i915/intel_drv.h
> > > @@ -782,6 +782,7 @@ struct intel_digital_port {
> > >   	struct intel_dp dp;
> > >   	struct intel_hdmi hdmi;
> > >   	enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool);
> > > +	bool release_cl2_override;
> > >   };
> > >   
> > >   struct intel_dp_mst_encoder {
> > > @@ -1372,6 +1373,8 @@ void intel_display_set_init_power(struct drm_i915_private *dev, bool enable);
> > >   
> > >   void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> > >   			     bool override, unsigned int mask);
> > > +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> > > +			  enum dpio_channel ch, bool override);
> > >   
> > >   
> > >   /* intel_pm.c */
> > > diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> > > index b3f6c9f..4b604ee 100644
> > > --- a/drivers/gpu/drm/i915/intel_hdmi.c
> > > +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> > > @@ -1625,6 +1625,14 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
> > >   
> > >   	intel_hdmi_prepare(encoder);
> > >   
> > > +	/*
> > > +	 * Must trick the second common lane into life.
> > > +	 * Otherwise we can't even access the PLL.
> > > +	 */
> > > +	if (ch == DPIO_CH0 && pipe == PIPE_B)
> > > +		dport->release_cl2_override =
> > > +			!chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true);
> > > +
> > >   	chv_phy_powergate_lanes(encoder, true, 0x0);
> > >   
> > >   	mutex_lock(&dev_priv->sb_lock);
> > > @@ -1701,6 +1709,15 @@ static void chv_hdmi_post_pll_disable(struct intel_encoder *encoder)
> > >   
> > >   	mutex_unlock(&dev_priv->sb_lock);
> > >   
> > > +	/*
> > > +	 * Leave the power down bit cleared for at least one
> > > +	 * lane so that chv_powergate_phy_ch() will power
> > > +	 * on something when the channel is otherwise unused.
> > > +	 * When the port is off and the override is removed
> > > +	 * the lanes power down anyway, so otherwise it doesn't
> > > +	 * really matter what the state of power down bits is
> > > +	 * after this.
> > > +	 */
> > >   	chv_phy_powergate_lanes(encoder, false, 0x0);
> > >   }
> > >   
> > > @@ -1922,6 +1939,12 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
> > >   	g4x_enable_hdmi(encoder);
> > >   
> > >   	vlv_wait_port_ready(dev_priv, dport, 0x0);
> > > +
> > > +	/* Second common lane will stay alive on its own now */
> > > +	if (dport->release_cl2_override) {
> > > +		chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false);
> > > +		dport->release_cl2_override = false;
> > > +	}
> > >   }
> > >   
> > >   static void intel_hdmi_destroy(struct drm_connector *connector)
> > > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > index 506a8cc..551cf08 100644
> > > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > @@ -1016,6 +1016,35 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> > >   		      phy, dev_priv->chv_phy_control);
> > >   }
> > >   
> > > +bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> > > +			  enum dpio_channel ch, bool override)
> > > +{
> > > +	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> > > +	bool was_override;
> > > +
> > > +	mutex_lock(&power_domains->lock);
> > > +
> > > +	was_override = dev_priv->chv_phy_control & PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > > +
> > > +	if (override == was_override)
> > > +		goto out;
> > > +
> > > +	if (override)
> > > +		dev_priv->chv_phy_control |= PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > > +	else
> > > +		dev_priv->chv_phy_control &= ~PHY_CH_POWER_DOWN_OVRD_EN(phy, ch);
> > > +
> > > +	I915_WRITE(DISPLAY_PHY_CONTROL, dev_priv->chv_phy_control);
> > > +
> > > +	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
> > > +		      phy, ch, dev_priv->chv_phy_control);
> > > +
> > > +out:
> > > +	mutex_unlock(&power_domains->lock);
> > > +
> > > +	return was_override;
> > > +}
> > > +
> > >   void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> > >   			     bool override, unsigned int mask)
> > >   {
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Ville Syrjälä
> Intel OTC
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 12/15] drm/i915: Force CL2 off in CHV x1 PHY
  2015-08-19 13:39     ` Ville Syrjälä
@ 2015-08-26 12:38       ` Daniel Vetter
  0 siblings, 0 replies; 50+ messages in thread
From: Daniel Vetter @ 2015-08-26 12:38 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Wed, Aug 19, 2015 at 04:39:41PM +0300, Ville Syrjälä wrote:
> On Wed, Aug 19, 2015 at 06:52:57PM +0530, Deepak wrote:
> > 
> > 
> > On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > > We can choose to leave the display PHY CL2 powerdown up to some hardware
> > > signals, or we can force it. The BXT code forces the nonexistent CL2 in
> > > the x1 PHY to power down. Follow suit on CHV. Maybe it can still save
> > > some extra power by disabling some extra logic in CL1, or something.
> > >
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >   drivers/gpu/drm/i915/i915_reg.h         | 1 +
> > >   drivers/gpu/drm/i915/intel_runtime_pm.c | 9 +++++++++
> > >   2 files changed, 10 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > > index 8010200..395f556 100644
> > > --- a/drivers/gpu/drm/i915/i915_reg.h
> > > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > > @@ -1139,6 +1139,7 @@ enum skl_disp_power_wells {
> > >   #define   DPIO_SUS_CLK_CONFIG_GATE_CLKREQ	(3 << 0)
> > >   
> > >   #define CHV_CMN_DW30			0x8178
> > > +#define   DPIO_CL2_LDOFUSE_PWRENB	(1 << 6)
> > >   #define   DPIO_LRC_BYPASS		(1 << 3)
> > >   
> > >   #define _TXLANE(ch, lane, offset) ((ch ? 0x2400 : 0) + \
> > > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > index 37e4375..002b78f 100644
> > > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > @@ -980,6 +980,15 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
> > >   		tmp = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW6_CH1);
> > >   		tmp |= DPIO_DYNPWRDOWNEN_CH1;
> > >   		vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW6_CH1, tmp);
> > > +	} else {
> > > +		/*
> > > +		 * Force the non-existing CL2 off. BXT does this
> > > +		 * too, so maybe it saves some power even though
> > > +		 * CL2 doesn't exist?
> > > +		 */
> > > +		tmp = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW30);
> > > +		tmp |= DPIO_CL2_LDOFUSE_PWRENB;
> > > +		vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW30, tmp);
> > >   	}
> > >   
> > Do we need to turn off CL2 each time we enable dpio cmn power wells?
> 
> Yes, all DPIO registers lose their state when the power well is off.
> 
> > 
> > btw, changes looks fine
> > Reviewed-by: Deepak S <deepak.s@linux.intel.com>

Merged up to this one with the one patch from the dpll series
cherry-picked. Later patches seem to still lack r-bs.

Thanks, Daniel
> > 
> > 
> > >   	mutex_unlock(&dev_priv->sb_lock);
> > 
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Ville Syrjälä
> Intel OTC
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming
  2015-07-08 20:45 ` [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming ville.syrjala
  2015-07-09 16:27   ` Daniel Vetter
  2015-07-09 17:14   ` [PATCH v2 " ville.syrjala
@ 2015-08-27  4:25   ` Deepak
  2 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-27  4:25 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:15 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Currently we relesar the lane soft reset before lane stagger settings
> have been programmed. I believe that means we don't actually do lane
> staggering. So move the soft reset deassert to happen after lane
> staggering has been programmed.
>
> The one confusing thing in this is that when we remove the power down
> override from the lanes, they power up with defaul register values,
> which do not have the soft reset overrides enabled. And according to
> some docs by default the data lane resets are tied to cmnreset. So that
> would mean that lanes would come out of reset without staggering as
> soon as the power down overrides are removed. But sine we can't access
> either the lane stagger register nor the soft reset override registers
> until the lanes are powered on, we can really do anything about it.
> So let's just set the soft reset overrides as soon as the lane is
> powered on and hope for the best.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_dp.c   | 91 +++++++++++++++++++++------------------
>   drivers/gpu/drm/i915/intel_hdmi.c | 91 ++++++++++++++++++++++-----------------
>   2 files changed, 100 insertions(+), 82 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 817df87..297bd14 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2389,42 +2389,62 @@ static void vlv_post_disable_dp(struct intel_encoder *encoder)
>   	intel_dp_link_down(intel_dp);
>   }
>   
> -static void chv_post_disable_dp(struct intel_encoder *encoder)
> +static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
> +				     bool reset)
>   {
> -	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> -	struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
> -	struct drm_device *dev = encoder->base.dev;
> -	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_crtc *intel_crtc =
> -		to_intel_crtc(encoder->base.crtc);
> -	enum dpio_channel ch = vlv_dport_to_channel(dport);
> -	enum pipe pipe = intel_crtc->pipe;
> -	u32 val;
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
> +	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
> +	enum pipe pipe = crtc->pipe;
> +	uint32_t val;
>   
> -	intel_dp_link_down(intel_dp);
> +	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> +	if (reset)
> +		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +	else
> +		val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
> +	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
>   
> -	mutex_lock(&dev_priv->sb_lock);
> +	if (crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> +		if (reset)
> +			val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +		else
> +			val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	}
>   
> -	/* Propagate soft reset to data lane reset */
>   	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
>   	val |= CHV_PCS_REQ_SOFTRESET_EN;
> +	if (reset)
> +		val &= ~DPIO_PCS_CLK_SOFT_RESET;
> +	else
> +		val |= DPIO_PCS_CLK_SOFT_RESET;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
>   
> -	if (intel_crtc->config->lane_count > 2) {
> +	if (crtc->config->lane_count > 2) {
>   		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
>   		val |= CHV_PCS_REQ_SOFTRESET_EN;
> +		if (reset)
> +			val &= ~DPIO_PCS_CLK_SOFT_RESET;
> +		else
> +			val |= DPIO_PCS_CLK_SOFT_RESET;
>   		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
>   	}
> +}
>   
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> -	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> +static void chv_post_disable_dp(struct intel_encoder *encoder)
> +{
> +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>   
> -	if (intel_crtc->config->lane_count > 2) {
> -		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> -	}
> +	intel_dp_link_down(intel_dp);
> +
> +	mutex_lock(&dev_priv->sb_lock);
> +
> +	/* Assert data lane reset */
> +	chv_data_lane_soft_reset(encoder, true);
>   
>   	mutex_unlock(&dev_priv->sb_lock);
>   }
> @@ -2802,27 +2822,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>   		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
>   	}
>   
> -	/* Deassert soft data lane reset*/
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
> -
> -	if (intel_crtc->config->lane_count > 2) {
> -		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> -		val |= CHV_PCS_REQ_SOFTRESET_EN;
> -		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> -	}
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> -	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> -
> -	if (intel_crtc->config->lane_count > 2) {
> -		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -		val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> -	}
> -
>   	/* Program Tx lane latency optimal setting*/
>   	for (i = 0; i < intel_crtc->config->lane_count; i++) {
>   		/* Set the upar bit */
> @@ -2872,6 +2871,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>   			       DPIO_TX2_STAGGER_MULT(5));
>   	}
>   
> +	/* Deassert data lane reset */
> +	chv_data_lane_soft_reset(encoder, false);
> +
>   	mutex_unlock(&dev_priv->sb_lock);
>   
>   	intel_enable_dp(encoder);
> @@ -2910,6 +2912,9 @@ static void chv_dp_pre_pll_enable(struct intel_encoder *encoder)
>   
>   	mutex_lock(&dev_priv->sb_lock);
>   
> +	/* Assert data lane reset */
> +	chv_data_lane_soft_reset(encoder, true);
> +
>   	/* program left/right clock distribution */
>   	if (pipe != PIPE_B) {
>   		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
> index 4b604ee..176d681 100644
> --- a/drivers/gpu/drm/i915/intel_hdmi.c
> +++ b/drivers/gpu/drm/i915/intel_hdmi.c
> @@ -1612,6 +1612,50 @@ static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>   	mutex_unlock(&dev_priv->sb_lock);
>   }
>   
> +static void chv_data_lane_soft_reset(struct intel_encoder *encoder,
> +				     bool reset)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base));
> +	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
> +	enum pipe pipe = crtc->pipe;
> +	uint32_t val;
> +
> +	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> +	if (reset)
> +		val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +	else
> +		val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
> +	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> +
> +	if (crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> +		if (reset)
> +			val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> +		else
> +			val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	}
> +
> +	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
> +	val |= CHV_PCS_REQ_SOFTRESET_EN;
> +	if (reset)
> +		val &= ~DPIO_PCS_CLK_SOFT_RESET;
> +	else
> +		val |= DPIO_PCS_CLK_SOFT_RESET;
> +	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
> +
> +	if (crtc->config->lane_count > 2) {
> +		val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> +		val |= CHV_PCS_REQ_SOFTRESET_EN;
> +		if (reset)
> +			val &= ~DPIO_PCS_CLK_SOFT_RESET;
> +		else
> +			val |= DPIO_PCS_CLK_SOFT_RESET;
> +		vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> +	}
> +}
> +
>   static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>   {
>   	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
> @@ -1637,6 +1681,9 @@ static void chv_hdmi_pre_pll_enable(struct intel_encoder *encoder)
>   
>   	mutex_lock(&dev_priv->sb_lock);
>   
> +	/* Assert data lane reset */
> +	chv_data_lane_soft_reset(encoder, true);
> +
>   	/* program left/right clock distribution */
>   	if (pipe != PIPE_B) {
>   		val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0);
> @@ -1739,33 +1786,13 @@ static void vlv_hdmi_post_disable(struct intel_encoder *encoder)
>   
>   static void chv_hdmi_post_disable(struct intel_encoder *encoder)
>   {
> -	struct intel_digital_port *dport = enc_to_dig_port(&encoder->base);
>   	struct drm_device *dev = encoder->base.dev;
>   	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_crtc *intel_crtc =
> -		to_intel_crtc(encoder->base.crtc);
> -	enum dpio_channel ch = vlv_dport_to_channel(dport);
> -	enum pipe pipe = intel_crtc->pipe;
> -	u32 val;
>   
>   	mutex_lock(&dev_priv->sb_lock);
>   
> -	/* Propagate soft reset to data lane reset */
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> -	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -	val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> +	/* Assert data lane reset */
> +	chv_data_lane_soft_reset(encoder, true);
>   
>   	mutex_unlock(&dev_priv->sb_lock);
>   }
> @@ -1796,23 +1823,6 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
>   	val &= ~DPIO_LANEDESKEW_STRAP_OVRD;
>   	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val);
>   
> -	/* Deassert soft data lane reset*/
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch));
> -	val |= CHV_PCS_REQ_SOFTRESET_EN;
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch));
> -	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val);
> -
> -	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch));
> -	val |= (DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET);
> -	vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val);
> -
>   	/* Program Tx latency optimal setting */
>   	for (i = 0; i < 4; i++) {
>   		/* Set the upar bit */
> @@ -1855,6 +1865,9 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder)
>   		       DPIO_TX1_STAGGER_MULT(7) |
>   		       DPIO_TX2_STAGGER_MULT(5));
>   
> +	/* Deassert data lane reset */
> +	chv_data_lane_soft_reset(encoder, false);
> +
>   	/* Clear calc init */
>   	val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
>   	val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3);
Changes looks fine
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 14/15] drm/i915: Add some CHV DPIO lane power state asserts
  2015-07-08 20:46 ` [PATCH 14/15] drm/i915: Add some CHV DPIO lane power state asserts ville.syrjala
@ 2015-08-27  4:36   ` Deepak
  2015-08-27 11:02     ` Ville Syrjälä
  0 siblings, 1 reply; 50+ messages in thread
From: Deepak @ 2015-08-27  4:36 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:16 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Add some checks that the state of the DPIO lanes is more or less what we
> expect based on the overrides.
>
> The hardware only provides two bits per channel indicating whether all
> or some of the lanes are powered down, so we can't do an exact check.
>
> Additionally, CL2 powering down before we can check it adds another
> twist. To work around this we simply check for the 0 value of the
> CL2 register (which is what we get when it's powered down) and
> adjust our expectations.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_reg.h         |  8 +++++
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 54 +++++++++++++++++++++++++++++++++
>   2 files changed, 62 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 395f556..586a0f7 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -1089,6 +1089,12 @@ enum skl_disp_power_wells {
>   #define  DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE	1 /* 1: coarse & 0 : fine  */
>   #define CHV_PLL_DW9(ch) _PIPE(ch, _CHV_PLL_DW9_CH0, _CHV_PLL_DW9_CH1)
>   
> +#define _CHV_CMN_DW0_CH0               0x8100
> +#define   DPIO_ALLDL_POWERDOWN_SHIFT_CH0	19
> +#define   DPIO_ANYDL_POWERDOWN_SHIFT_CH0	18
> +#define   DPIO_ALLDL_POWERDOWN			(1 << 1)
> +#define   DPIO_ANYDL_POWERDOWN			(1 << 0)
> +
>   #define _CHV_CMN_DW5_CH0               0x8114
>   #define   CHV_BUFRIGHTENA1_DISABLE	(0 << 20)
>   #define   CHV_BUFRIGHTENA1_NORMAL	(1 << 20)
> @@ -1125,6 +1131,8 @@ enum skl_disp_power_wells {
>   
>   #define _CHV_CMN_DW19_CH0		0x814c
>   #define _CHV_CMN_DW6_CH1		0x8098
> +#define   DPIO_ALLDL_POWERDOWN_SHIFT_CH1	30 /* CL2 DW6 only */
> +#define   DPIO_ANYDL_POWERDOWN_SHIFT_CH1	29 /* CL2 DW6 only */
>   #define   DPIO_DYNPWRDOWNEN_CH1		(1 << 28) /* CL2 DW6 only */
>   #define   CHV_CMN_USEDCLKCHANNEL	(1 << 13)
>   
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index 002b78f..a1d9676 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -1026,6 +1026,58 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
>   		      phy, dev_priv->chv_phy_control);
>   }
>   
> +static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> +				     enum dpio_channel ch, bool override, unsigned int mask)
> +{
> +	enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C;
Why not PIPE B? I think PIPE B can also be used to drive using PHY0?
> +	u32 reg, val, expected, actual;
> +
> +	if (ch == DPIO_CH0)
> +		reg = _CHV_CMN_DW0_CH0;
> +	else
> +		reg = _CHV_CMN_DW6_CH1;
> +
> +	mutex_lock(&dev_priv->sb_lock);
> +	val = vlv_dpio_read(dev_priv, pipe, reg);
> +	mutex_unlock(&dev_priv->sb_lock);
> +
> +	/*
> +	 * This assumes !override is only used when the port is disabled.
> +	 * All lanes should power down even without the override when
> +	 * the port is disabled.
> +	 */
> +	if (!override || mask == 0xf) {
> +		expected = DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
> +		/*
> +		 * If CH1 common lane is not active anymore
> +		 * (eg. for pipe B DPLL) the entire channel will
> +		 * shut down, which causes the common lane registers
> +		 * to read as 0. That means we can't actually check
> +		 * the lane power down status bits, but as the entire
> +		 * register reads as 0 it's a good indication that the
> +		 * channel is indeed entirely powered down.
> +		 */
> +		if (ch == DPIO_CH1 && val == 0)
> +			expected = 0;
> +	} else if (mask != 0x0) {
> +		expected = DPIO_ANYDL_POWERDOWN;
> +	} else {
> +		expected = 0;
> +	}
> +
> +	if (ch == DPIO_CH0)
> +		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH0;
> +	else
> +		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH1;
> +	actual &= DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
> +
> +	WARN(actual != expected,
> +	     "Unexpected DPIO lane power down: all %d, any %d. Expected: all %d, any %d. (0x%x = 0x%08x)\n",
> +	     !!(actual & DPIO_ALLDL_POWERDOWN), !!(actual & DPIO_ANYDL_POWERDOWN),
> +	     !!(expected & DPIO_ALLDL_POWERDOWN), !!(expected & DPIO_ANYDL_POWERDOWN),
> +	     reg, val);
> +}
> +
>   bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
>   			  enum dpio_channel ch, bool override)
>   {
> @@ -1078,6 +1130,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
>   	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
>   		      phy, ch, mask, dev_priv->chv_phy_control);
>   
> +	assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
> +
>   	mutex_unlock(&power_domains->lock);
>   }
>   

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

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

* Re: [PATCH 15/15] drm/i915: Add CHV PHY LDO power sanity checks
  2015-07-08 20:46 ` [PATCH 15/15] drm/i915: Add CHV PHY LDO power sanity checks ville.syrjala
@ 2015-08-27  4:39   ` Deepak
  2015-09-01  9:45     ` Daniel Vetter
  0 siblings, 1 reply; 50+ messages in thread
From: Deepak @ 2015-08-27  4:39 UTC (permalink / raw)
  To: intel-gfx



On 07/09/2015 02:16 AM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> At various points when changing the DPIO lane/phy power states,
> construct an expected value of the DISPLAY_PHY_STATUS register
> and compare it with the real thing.
>
> To construct the expected value we look at our shadow PHY_CONTROL
> register value (which should match what we've just written to the
> hardware), and we also need to look at the actual state of the cmn
> power wells as a disabled power well causes the relevant LDO status
> to be reported as 'on' in DISPLAY_PHY_STATUS.
>
> When initially powering up the PHY it performs various internal
> calibrations for which it fully powers up. That means that if we check
> for the expetected power state immediately upon releasing cmnreset we
> would get the occasional false positive. But we can of course
> poll until the expected value appears. It shouldn't be too long so
> this shouldn't make modesets substantially longer.
>
> One extra complication is introduced when we cross the streams, ie.
> drive port B with pipe B. In this case we trick CL2 (where the DPLL lives)
> into life by temporaily powering up the lanes in the second channel,
> and once the pipe is up and runnign we release the lane power override.
> At that point the power state of CL2 has somehow gotten entangled with
> the power state of the first channel. That means that constructing the
> expected DISPLAY_PHY_STATUS value is a bit tricky since based on the
> lane power states in the second channel, CL2 should also be powered
> down. But we can use the DPLL enable bit to determine when CL2 should
> be alive even if the lanes are powered down. However the power state
> of CL2 isn't actually tied in with the DPLL state, but to the state
> of the lanes in first channel, so we have to avoid checking the
> expected state between shutting down the DPLL and powering down
> the lanes in the first channel. So no calling assert_chv_phy_status()
> before the DISPLAY_PHY_CONTROL write in chv_phy_powergate_lanes(),
> but after the write is a safe time to check.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_reg.h         |   2 +
>   drivers/gpu/drm/i915/intel_runtime_pm.c | 126 +++++++++++++++++++++++++++-----
>   2 files changed, 111 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 586a0f7..429105e 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2206,6 +2206,8 @@ enum skl_disp_power_wells {
>   #define   PHY_COM_LANE_RESET_DEASSERT(phy)	(1 << (phy))
>   #define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104)
>   #define   PHY_POWERGOOD(phy)	(((phy) == DPIO_PHY0) ? (1<<31) : (1<<30))
> +#define   PHY_STATUS_CMN_LDO(phy, ch)                   (1 << (6-(6*(phy)+3*(ch))))
> +#define   PHY_STATUS_SPLINE_LDO(phy, ch, spline)        (1 << (8-(6*(phy)+3*(ch)+(spline))))
>   
>   /*
>    * The i830 generation, in LVDS mode, defines P1 as the bit number set within
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index a1d9676..e6f1b4ee 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -942,6 +942,107 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
>   	vlv_set_power_well(dev_priv, power_well, false);
>   }
>   
> +#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
> +
> +static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
> +						 int power_well_id)
> +{
> +	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> +	struct i915_power_well *power_well;
> +	int i;
> +
> +	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> +		if (power_well->data == power_well_id)
> +			return power_well;
> +	}
> +
> +	return NULL;
> +}
> +
> +#define BITS_SET(val, bits) (((val) & (bits)) == (bits))
> +
> +static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
> +{
> +	struct i915_power_well *cmn_bc =
> +		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
> +	struct i915_power_well *cmn_d =
> +		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
> +	u32 phy_control = dev_priv->chv_phy_control;
> +	u32 phy_status = 0;
> +	u32 tmp;
> +
> +	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
> +		phy_status |= PHY_POWERGOOD(DPIO_PHY0);
> +
> +		/* this assumes override is only used to enable lanes */
> +		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0)) == 0)
> +			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0);
> +
> +		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1)) == 0)
> +			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1);
> +
> +		/* CL1 is on whenever anything is on in either channel */
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0) |
> +			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)))
> +			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0);
> +
> +		/*
> +		 * The DPLLB check accounts for the pipe B + port A usage
> +		 * with CL2 powered up but all the lanes in the second channel
> +		 * powered down.
> +		 */
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)) &&
> +		    (I915_READ(DPLL(PIPE_B)) & DPLL_VCO_ENABLE) == 0)
> +			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1);
> +
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH0)))
> +			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0);
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH0)))
> +			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1);
> +
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH1)))
> +			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0);
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH1)))
> +			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1);
> +	}
> +
> +	if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
> +		phy_status |= PHY_POWERGOOD(DPIO_PHY1);
> +
> +		/* this assumes override is only used to enable lanes */
> +		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0)) == 0)
> +			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0);
> +
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0)))
> +			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0);
> +
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY1, DPIO_CH0)))
> +			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0);
> +		if (BITS_SET(phy_control,
> +			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY1, DPIO_CH0)))
> +			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1);
> +	}
> +
> +	/*
> +	 * The PHY may be busy with some initial calibration and whatnot,
> +	 * so the power state can take a while to actually change.
> +	 */
> +	if (wait_for((tmp = I915_READ(DISPLAY_PHY_STATUS)) == phy_status, 10))
> +		WARN(phy_status != tmp,
> +		     "Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n",
> +		     tmp, phy_status, dev_priv->chv_phy_control);
> +}
> +
> +#undef BITS_SET
> +
>   static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
>   					   struct i915_power_well *power_well)
>   {
> @@ -998,6 +1099,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
>   
>   	DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
>   		      phy, dev_priv->chv_phy_control);
> +
> +	assert_chv_phy_status(dev_priv);
>   }
>   
>   static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> @@ -1024,6 +1127,8 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
>   
>   	DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
>   		      phy, dev_priv->chv_phy_control);
> +
> +	assert_chv_phy_status(dev_priv);
>   }
>   
>   static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> @@ -1101,6 +1206,8 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
>   	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
>   		      phy, ch, dev_priv->chv_phy_control);
>   
> +	assert_chv_phy_status(dev_priv);
> +
>   out:
>   	mutex_unlock(&power_domains->lock);
>   
> @@ -1130,6 +1237,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
>   	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
>   		      phy, ch, mask, dev_priv->chv_phy_control);
>   
> +	assert_chv_phy_status(dev_priv);
> +
Patch looks fine with assertion at right places
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
>   	assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
>   
>   	mutex_unlock(&power_domains->lock);
> @@ -1302,8 +1411,6 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
>   	intel_runtime_pm_put(dev_priv);
>   }
>   
> -#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) |		\
> @@ -1565,21 +1672,6 @@ static struct i915_power_well chv_power_wells[] = {
>   	},
>   };
>   
> -static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
> -						 int power_well_id)
> -{
> -	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> -	struct i915_power_well *power_well;
> -	int i;
> -
> -	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> -		if (power_well->data == power_well_id)
> -			return power_well;
> -	}
> -
> -	return NULL;
> -}
> -
>   bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
>   				    int power_well_id)
>   {

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

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

* Re: [PATCH 14/15] drm/i915: Add some CHV DPIO lane power state asserts
  2015-08-27  4:36   ` Deepak
@ 2015-08-27 11:02     ` Ville Syrjälä
  2015-08-31 10:47       ` Deepak
  0 siblings, 1 reply; 50+ messages in thread
From: Ville Syrjälä @ 2015-08-27 11:02 UTC (permalink / raw)
  To: Deepak; +Cc: intel-gfx

On Thu, Aug 27, 2015 at 10:06:09AM +0530, Deepak wrote:
> 
> 
> On 07/09/2015 02:16 AM, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Add some checks that the state of the DPIO lanes is more or less what we
> > expect based on the overrides.
> >
> > The hardware only provides two bits per channel indicating whether all
> > or some of the lanes are powered down, so we can't do an exact check.
> >
> > Additionally, CL2 powering down before we can check it adds another
> > twist. To work around this we simply check for the 0 value of the
> > CL2 register (which is what we get when it's powered down) and
> > adjust our expectations.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >   drivers/gpu/drm/i915/i915_reg.h         |  8 +++++
> >   drivers/gpu/drm/i915/intel_runtime_pm.c | 54 +++++++++++++++++++++++++++++++++
> >   2 files changed, 62 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> > index 395f556..586a0f7 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -1089,6 +1089,12 @@ enum skl_disp_power_wells {
> >   #define  DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE	1 /* 1: coarse & 0 : fine  */
> >   #define CHV_PLL_DW9(ch) _PIPE(ch, _CHV_PLL_DW9_CH0, _CHV_PLL_DW9_CH1)
> >   
> > +#define _CHV_CMN_DW0_CH0               0x8100
> > +#define   DPIO_ALLDL_POWERDOWN_SHIFT_CH0	19
> > +#define   DPIO_ANYDL_POWERDOWN_SHIFT_CH0	18
> > +#define   DPIO_ALLDL_POWERDOWN			(1 << 1)
> > +#define   DPIO_ANYDL_POWERDOWN			(1 << 0)
> > +
> >   #define _CHV_CMN_DW5_CH0               0x8114
> >   #define   CHV_BUFRIGHTENA1_DISABLE	(0 << 20)
> >   #define   CHV_BUFRIGHTENA1_NORMAL	(1 << 20)
> > @@ -1125,6 +1131,8 @@ enum skl_disp_power_wells {
> >   
> >   #define _CHV_CMN_DW19_CH0		0x814c
> >   #define _CHV_CMN_DW6_CH1		0x8098
> > +#define   DPIO_ALLDL_POWERDOWN_SHIFT_CH1	30 /* CL2 DW6 only */
> > +#define   DPIO_ANYDL_POWERDOWN_SHIFT_CH1	29 /* CL2 DW6 only */
> >   #define   DPIO_DYNPWRDOWNEN_CH1		(1 << 28) /* CL2 DW6 only */
> >   #define   CHV_CMN_USEDCLKCHANNEL	(1 << 13)
> >   
> > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > index 002b78f..a1d9676 100644
> > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > @@ -1026,6 +1026,58 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> >   		      phy, dev_priv->chv_phy_control);
> >   }
> >   
> > +static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> > +				     enum dpio_channel ch, bool override, unsigned int mask)
> > +{
> > +	enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C;
> Why not PIPE B? I think PIPE B can also be used to drive using PHY0?

Here we only pass 'pipe' to vlv_dpio_read() and it will just use
'DPIO_PHY(pipe)' to turn it back into an enum dpio_phy :) Since pipe A
and B are hooked up the same phy we don't need pipe B here.

I've been meaning to change vlv_dpio_read/write() to take enum dpio_phy
instead of enum pipe to get rid of this kind of sillyness, but haven't
gotten around to it yet. There may also be a few other functions that
could use the same treatment.

> > +	u32 reg, val, expected, actual;
> > +
> > +	if (ch == DPIO_CH0)
> > +		reg = _CHV_CMN_DW0_CH0;
> > +	else
> > +		reg = _CHV_CMN_DW6_CH1;
> > +
> > +	mutex_lock(&dev_priv->sb_lock);
> > +	val = vlv_dpio_read(dev_priv, pipe, reg);
> > +	mutex_unlock(&dev_priv->sb_lock);
> > +
> > +	/*
> > +	 * This assumes !override is only used when the port is disabled.
> > +	 * All lanes should power down even without the override when
> > +	 * the port is disabled.
> > +	 */
> > +	if (!override || mask == 0xf) {
> > +		expected = DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
> > +		/*
> > +		 * If CH1 common lane is not active anymore
> > +		 * (eg. for pipe B DPLL) the entire channel will
> > +		 * shut down, which causes the common lane registers
> > +		 * to read as 0. That means we can't actually check
> > +		 * the lane power down status bits, but as the entire
> > +		 * register reads as 0 it's a good indication that the
> > +		 * channel is indeed entirely powered down.
> > +		 */
> > +		if (ch == DPIO_CH1 && val == 0)
> > +			expected = 0;
> > +	} else if (mask != 0x0) {
> > +		expected = DPIO_ANYDL_POWERDOWN;
> > +	} else {
> > +		expected = 0;
> > +	}
> > +
> > +	if (ch == DPIO_CH0)
> > +		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH0;
> > +	else
> > +		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH1;
> > +	actual &= DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
> > +
> > +	WARN(actual != expected,
> > +	     "Unexpected DPIO lane power down: all %d, any %d. Expected: all %d, any %d. (0x%x = 0x%08x)\n",
> > +	     !!(actual & DPIO_ALLDL_POWERDOWN), !!(actual & DPIO_ANYDL_POWERDOWN),
> > +	     !!(expected & DPIO_ALLDL_POWERDOWN), !!(expected & DPIO_ANYDL_POWERDOWN),
> > +	     reg, val);
> > +}
> > +
> >   bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> >   			  enum dpio_channel ch, bool override)
> >   {
> > @@ -1078,6 +1130,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> >   	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
> >   		      phy, ch, mask, dev_priv->chv_phy_control);
> >   
> > +	assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
> > +
> >   	mutex_unlock(&power_domains->lock);
> >   }
> >   
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

* Re: [PATCH 14/15] drm/i915: Add some CHV DPIO lane power state asserts
  2015-08-27 11:02     ` Ville Syrjälä
@ 2015-08-31 10:47       ` Deepak
  0 siblings, 0 replies; 50+ messages in thread
From: Deepak @ 2015-08-31 10:47 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx



On 08/27/2015 04:32 PM, Ville Syrjälä wrote:
> On Thu, Aug 27, 2015 at 10:06:09AM +0530, Deepak wrote:
>>
>> On 07/09/2015 02:16 AM, ville.syrjala@linux.intel.com wrote:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> Add some checks that the state of the DPIO lanes is more or less what we
>>> expect based on the overrides.
>>>
>>> The hardware only provides two bits per channel indicating whether all
>>> or some of the lanes are powered down, so we can't do an exact check.
>>>
>>> Additionally, CL2 powering down before we can check it adds another
>>> twist. To work around this we simply check for the 0 value of the
>>> CL2 register (which is what we get when it's powered down) and
>>> adjust our expectations.
>>>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/i915_reg.h         |  8 +++++
>>>    drivers/gpu/drm/i915/intel_runtime_pm.c | 54 +++++++++++++++++++++++++++++++++
>>>    2 files changed, 62 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
>>> index 395f556..586a0f7 100644
>>> --- a/drivers/gpu/drm/i915/i915_reg.h
>>> +++ b/drivers/gpu/drm/i915/i915_reg.h
>>> @@ -1089,6 +1089,12 @@ enum skl_disp_power_wells {
>>>    #define  DPIO_CHV_INT_LOCK_THRESHOLD_SEL_COARSE	1 /* 1: coarse & 0 : fine  */
>>>    #define CHV_PLL_DW9(ch) _PIPE(ch, _CHV_PLL_DW9_CH0, _CHV_PLL_DW9_CH1)
>>>    
>>> +#define _CHV_CMN_DW0_CH0               0x8100
>>> +#define   DPIO_ALLDL_POWERDOWN_SHIFT_CH0	19
>>> +#define   DPIO_ANYDL_POWERDOWN_SHIFT_CH0	18
>>> +#define   DPIO_ALLDL_POWERDOWN			(1 << 1)
>>> +#define   DPIO_ANYDL_POWERDOWN			(1 << 0)
>>> +
>>>    #define _CHV_CMN_DW5_CH0               0x8114
>>>    #define   CHV_BUFRIGHTENA1_DISABLE	(0 << 20)
>>>    #define   CHV_BUFRIGHTENA1_NORMAL	(1 << 20)
>>> @@ -1125,6 +1131,8 @@ enum skl_disp_power_wells {
>>>    
>>>    #define _CHV_CMN_DW19_CH0		0x814c
>>>    #define _CHV_CMN_DW6_CH1		0x8098
>>> +#define   DPIO_ALLDL_POWERDOWN_SHIFT_CH1	30 /* CL2 DW6 only */
>>> +#define   DPIO_ANYDL_POWERDOWN_SHIFT_CH1	29 /* CL2 DW6 only */
>>>    #define   DPIO_DYNPWRDOWNEN_CH1		(1 << 28) /* CL2 DW6 only */
>>>    #define   CHV_CMN_USEDCLKCHANNEL	(1 << 13)
>>>    
>>> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
>>> index 002b78f..a1d9676 100644
>>> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
>>> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
>>> @@ -1026,6 +1026,58 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
>>>    		      phy, dev_priv->chv_phy_control);
>>>    }
>>>    
>>> +static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
>>> +				     enum dpio_channel ch, bool override, unsigned int mask)
>>> +{
>>> +	enum pipe pipe = phy == DPIO_PHY0 ? PIPE_A : PIPE_C;
>> Why not PIPE B? I think PIPE B can also be used to drive using PHY0?
> Here we only pass 'pipe' to vlv_dpio_read() and it will just use
> 'DPIO_PHY(pipe)' to turn it back into an enum dpio_phy :) Since pipe A
> and B are hooked up the same phy we don't need pipe B here.
>
> I've been meaning to change vlv_dpio_read/write() to take enum dpio_phy
> instead of enum pipe to get rid of this kind of sillyness, but haven't
> gotten around to it yet. There may also be a few other functions that
> could use the same treatment.
>
Thanks for the clarification
Reviewed-by: Deepak S <deepak.s@linux.intel.com>
>>> +	u32 reg, val, expected, actual;
>>> +
>>> +	if (ch == DPIO_CH0)
>>> +		reg = _CHV_CMN_DW0_CH0;
>>> +	else
>>> +		reg = _CHV_CMN_DW6_CH1;
>>> +
>>> +	mutex_lock(&dev_priv->sb_lock);
>>> +	val = vlv_dpio_read(dev_priv, pipe, reg);
>>> +	mutex_unlock(&dev_priv->sb_lock);
>>> +
>>> +	/*
>>> +	 * This assumes !override is only used when the port is disabled.
>>> +	 * All lanes should power down even without the override when
>>> +	 * the port is disabled.
>>> +	 */
>>> +	if (!override || mask == 0xf) {
>>> +		expected = DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
>>> +		/*
>>> +		 * If CH1 common lane is not active anymore
>>> +		 * (eg. for pipe B DPLL) the entire channel will
>>> +		 * shut down, which causes the common lane registers
>>> +		 * to read as 0. That means we can't actually check
>>> +		 * the lane power down status bits, but as the entire
>>> +		 * register reads as 0 it's a good indication that the
>>> +		 * channel is indeed entirely powered down.
>>> +		 */
>>> +		if (ch == DPIO_CH1 && val == 0)
>>> +			expected = 0;
>>> +	} else if (mask != 0x0) {
>>> +		expected = DPIO_ANYDL_POWERDOWN;
>>> +	} else {
>>> +		expected = 0;
>>> +	}
>>> +
>>> +	if (ch == DPIO_CH0)
>>> +		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH0;
>>> +	else
>>> +		actual = val >> DPIO_ANYDL_POWERDOWN_SHIFT_CH1;
>>> +	actual &= DPIO_ALLDL_POWERDOWN | DPIO_ANYDL_POWERDOWN;
>>> +
>>> +	WARN(actual != expected,
>>> +	     "Unexpected DPIO lane power down: all %d, any %d. Expected: all %d, any %d. (0x%x = 0x%08x)\n",
>>> +	     !!(actual & DPIO_ALLDL_POWERDOWN), !!(actual & DPIO_ANYDL_POWERDOWN),
>>> +	     !!(expected & DPIO_ALLDL_POWERDOWN), !!(expected & DPIO_ANYDL_POWERDOWN),
>>> +	     reg, val);
>>> +}
>>> +
>>>    bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
>>>    			  enum dpio_channel ch, bool override)
>>>    {
>>> @@ -1078,6 +1130,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
>>>    	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
>>>    		      phy, ch, mask, dev_priv->chv_phy_control);
>>>    
>>> +	assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
>>> +
>>>    	mutex_unlock(&power_domains->lock);
>>>    }
>>>    
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 15/15] drm/i915: Add CHV PHY LDO power sanity checks
  2015-08-27  4:39   ` Deepak
@ 2015-09-01  9:45     ` Daniel Vetter
  0 siblings, 0 replies; 50+ messages in thread
From: Daniel Vetter @ 2015-09-01  9:45 UTC (permalink / raw)
  To: Deepak; +Cc: intel-gfx

On Thu, Aug 27, 2015 at 10:09:37AM +0530, Deepak wrote:
> 
> 
> On 07/09/2015 02:16 AM, ville.syrjala@linux.intel.com wrote:
> >From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> >At various points when changing the DPIO lane/phy power states,
> >construct an expected value of the DISPLAY_PHY_STATUS register
> >and compare it with the real thing.
> >
> >To construct the expected value we look at our shadow PHY_CONTROL
> >register value (which should match what we've just written to the
> >hardware), and we also need to look at the actual state of the cmn
> >power wells as a disabled power well causes the relevant LDO status
> >to be reported as 'on' in DISPLAY_PHY_STATUS.
> >
> >When initially powering up the PHY it performs various internal
> >calibrations for which it fully powers up. That means that if we check
> >for the expetected power state immediately upon releasing cmnreset we
> >would get the occasional false positive. But we can of course
> >poll until the expected value appears. It shouldn't be too long so
> >this shouldn't make modesets substantially longer.
> >
> >One extra complication is introduced when we cross the streams, ie.
> >drive port B with pipe B. In this case we trick CL2 (where the DPLL lives)
> >into life by temporaily powering up the lanes in the second channel,
> >and once the pipe is up and runnign we release the lane power override.
> >At that point the power state of CL2 has somehow gotten entangled with
> >the power state of the first channel. That means that constructing the
> >expected DISPLAY_PHY_STATUS value is a bit tricky since based on the
> >lane power states in the second channel, CL2 should also be powered
> >down. But we can use the DPLL enable bit to determine when CL2 should
> >be alive even if the lanes are powered down. However the power state
> >of CL2 isn't actually tied in with the DPLL state, but to the state
> >of the lanes in first channel, so we have to avoid checking the
> >expected state between shutting down the DPLL and powering down
> >the lanes in the first channel. So no calling assert_chv_phy_status()
> >before the DISPLAY_PHY_CONTROL write in chv_phy_powergate_lanes(),
> >but after the write is a safe time to check.
> >
> >Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Remaining 3 patches pulled into dinq, thanks.
-Daniel

> >---
> >  drivers/gpu/drm/i915/i915_reg.h         |   2 +
> >  drivers/gpu/drm/i915/intel_runtime_pm.c | 126 +++++++++++++++++++++++++++-----
> >  2 files changed, 111 insertions(+), 17 deletions(-)
> >
> >diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> >index 586a0f7..429105e 100644
> >--- a/drivers/gpu/drm/i915/i915_reg.h
> >+++ b/drivers/gpu/drm/i915/i915_reg.h
> >@@ -2206,6 +2206,8 @@ enum skl_disp_power_wells {
> >  #define   PHY_COM_LANE_RESET_DEASSERT(phy)	(1 << (phy))
> >  #define DISPLAY_PHY_STATUS (VLV_DISPLAY_BASE + 0x60104)
> >  #define   PHY_POWERGOOD(phy)	(((phy) == DPIO_PHY0) ? (1<<31) : (1<<30))
> >+#define   PHY_STATUS_CMN_LDO(phy, ch)                   (1 << (6-(6*(phy)+3*(ch))))
> >+#define   PHY_STATUS_SPLINE_LDO(phy, ch, spline)        (1 << (8-(6*(phy)+3*(ch)+(spline))))
> >  /*
> >   * The i830 generation, in LVDS mode, defines P1 as the bit number set within
> >diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
> >index a1d9676..e6f1b4ee 100644
> >--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> >+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> >@@ -942,6 +942,107 @@ static void vlv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> >  	vlv_set_power_well(dev_priv, power_well, false);
> >  }
> >+#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1)
> >+
> >+static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
> >+						 int power_well_id)
> >+{
> >+	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> >+	struct i915_power_well *power_well;
> >+	int i;
> >+
> >+	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> >+		if (power_well->data == power_well_id)
> >+			return power_well;
> >+	}
> >+
> >+	return NULL;
> >+}
> >+
> >+#define BITS_SET(val, bits) (((val) & (bits)) == (bits))
> >+
> >+static void assert_chv_phy_status(struct drm_i915_private *dev_priv)
> >+{
> >+	struct i915_power_well *cmn_bc =
> >+		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_BC);
> >+	struct i915_power_well *cmn_d =
> >+		lookup_power_well(dev_priv, PUNIT_POWER_WELL_DPIO_CMN_D);
> >+	u32 phy_control = dev_priv->chv_phy_control;
> >+	u32 phy_status = 0;
> >+	u32 tmp;
> >+
> >+	if (cmn_bc->ops->is_enabled(dev_priv, cmn_bc)) {
> >+		phy_status |= PHY_POWERGOOD(DPIO_PHY0);
> >+
> >+		/* this assumes override is only used to enable lanes */
> >+		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH0)) == 0)
> >+			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0);
> >+
> >+		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY0, DPIO_CH1)) == 0)
> >+			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1);
> >+
> >+		/* CL1 is on whenever anything is on in either channel */
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH0) |
> >+			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)))
> >+			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH0);
> >+
> >+		/*
> >+		 * The DPLLB check accounts for the pipe B + port A usage
> >+		 * with CL2 powered up but all the lanes in the second channel
> >+		 * powered down.
> >+		 */
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY0, DPIO_CH1)) &&
> >+		    (I915_READ(DPLL(PIPE_B)) & DPLL_VCO_ENABLE) == 0)
> >+			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY0, DPIO_CH1);
> >+
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH0)))
> >+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 0);
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH0)))
> >+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH0, 1);
> >+
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY0, DPIO_CH1)))
> >+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 0);
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY0, DPIO_CH1)))
> >+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1);
> >+	}
> >+
> >+	if (cmn_d->ops->is_enabled(dev_priv, cmn_d)) {
> >+		phy_status |= PHY_POWERGOOD(DPIO_PHY1);
> >+
> >+		/* this assumes override is only used to enable lanes */
> >+		if ((phy_control & PHY_CH_POWER_DOWN_OVRD_EN(DPIO_PHY1, DPIO_CH0)) == 0)
> >+			phy_control |= PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0);
> >+
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0xf, DPIO_PHY1, DPIO_CH0)))
> >+			phy_status |= PHY_STATUS_CMN_LDO(DPIO_PHY1, DPIO_CH0);
> >+
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0x3, DPIO_PHY1, DPIO_CH0)))
> >+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0);
> >+		if (BITS_SET(phy_control,
> >+			     PHY_CH_POWER_DOWN_OVRD(0xc, DPIO_PHY1, DPIO_CH0)))
> >+			phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1);
> >+	}
> >+
> >+	/*
> >+	 * The PHY may be busy with some initial calibration and whatnot,
> >+	 * so the power state can take a while to actually change.
> >+	 */
> >+	if (wait_for((tmp = I915_READ(DISPLAY_PHY_STATUS)) == phy_status, 10))
> >+		WARN(phy_status != tmp,
> >+		     "Unexpected PHY_STATUS 0x%08x, expected 0x%08x (PHY_CONTROL=0x%08x)\n",
> >+		     tmp, phy_status, dev_priv->chv_phy_control);
> >+}
> >+
> >+#undef BITS_SET
> >+
> >  static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
> >  					   struct i915_power_well *power_well)
> >  {
> >@@ -998,6 +1099,8 @@ static void chv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
> >  	DRM_DEBUG_KMS("Enabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
> >  		      phy, dev_priv->chv_phy_control);
> >+
> >+	assert_chv_phy_status(dev_priv);
> >  }
> >  static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> >@@ -1024,6 +1127,8 @@ static void chv_dpio_cmn_power_well_disable(struct drm_i915_private *dev_priv,
> >  	DRM_DEBUG_KMS("Disabled DPIO PHY%d (PHY_CONTROL=0x%08x)\n",
> >  		      phy, dev_priv->chv_phy_control);
> >+
> >+	assert_chv_phy_status(dev_priv);
> >  }
> >  static void assert_chv_phy_powergate(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> >@@ -1101,6 +1206,8 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
> >  	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d (DPIO_PHY_CONTROL=0x%08x)\n",
> >  		      phy, ch, dev_priv->chv_phy_control);
> >+	assert_chv_phy_status(dev_priv);
> >+
> >  out:
> >  	mutex_unlock(&power_domains->lock);
> >@@ -1130,6 +1237,8 @@ void chv_phy_powergate_lanes(struct intel_encoder *encoder,
> >  	DRM_DEBUG_KMS("Power gating DPIO PHY%d CH%d lanes 0x%x (PHY_CONTROL=0x%08x)\n",
> >  		      phy, ch, mask, dev_priv->chv_phy_control);
> >+	assert_chv_phy_status(dev_priv);
> >+
> Patch looks fine with assertion at right places
> Reviewed-by: Deepak S <deepak.s@linux.intel.com>
> >  	assert_chv_phy_powergate(dev_priv, phy, ch, override, mask);
> >  	mutex_unlock(&power_domains->lock);
> >@@ -1302,8 +1411,6 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
> >  	intel_runtime_pm_put(dev_priv);
> >  }
> >-#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) |		\
> >@@ -1565,21 +1672,6 @@ static struct i915_power_well chv_power_wells[] = {
> >  	},
> >  };
> >-static struct i915_power_well *lookup_power_well(struct drm_i915_private *dev_priv,
> >-						 int power_well_id)
> >-{
> >-	struct i915_power_domains *power_domains = &dev_priv->power_domains;
> >-	struct i915_power_well *power_well;
> >-	int i;
> >-
> >-	for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
> >-		if (power_well->data == power_well_id)
> >-			return power_well;
> >-	}
> >-
> >-	return NULL;
> >-}
> >-
> >  bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
> >  				    int power_well_id)
> >  {
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

end of thread, other threads:[~2015-09-01  9:45 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-08 20:45 [PATCH 00/15] drm/i915: CHV DPIO power gating, take two ville.syrjala
2015-07-08 20:45 ` [PATCH 01/15] drm/i915: Always program m2 fractional value on CHV ville.syrjala
2015-08-17  2:19   ` Deepak
2015-08-17 11:45     ` Ville Syrjälä
2015-08-26  8:11       ` Deepak
2015-07-08 20:45 ` [PATCH 02/15] drm/i915: Always program unique transition scale for CHV ville.syrjala
2015-08-17  2:31   ` Deepak
2015-07-08 20:45 ` [PATCH 03/15] drm/i915: Add encoder->post_pll_disable() hooks and move CHV clock buffer disables there ville.syrjala
2015-08-17  4:16   ` Deepak
2015-08-17 11:53     ` Ville Syrjälä
2015-08-26  8:14       ` Deepak
2015-07-08 20:45 ` [PATCH 04/15] drm/i915: Move DPIO port init earlier ville.syrjala
2015-08-17  4:18   ` Deepak
2015-07-08 20:45 ` [PATCH 05/15] drm/i915: Add locking around chv_phy_control_init() ville.syrjala
2015-08-17  4:23   ` Deepak
2015-07-08 20:45 ` [PATCH 06/15] drm/i915: Move VLV/CHV prepare_pll later ville.syrjala
2015-08-17  4:36   ` Deepak
2015-08-17  4:39   ` Deepak
2015-07-08 20:45 ` [PATCH 07/15] drm/i915: Add vlv_dport_to_phy() ville.syrjala
2015-08-17  4:56   ` Deepak
2015-08-26  8:24   ` Daniel Vetter
2015-07-08 20:45 ` [PATCH 08/15] drm/i915: Implement PHY lane power gating for CHV ville.syrjala
2015-08-19  1:48   ` Deepak
2015-08-26  8:27   ` Daniel Vetter
2015-07-08 20:45 ` [PATCH 09/15] drm/i915: Trick CL2 into life on CHV when using pipe B with port B ville.syrjala
2015-08-19  2:17   ` Deepak
2015-08-19 11:29     ` Ville Syrjälä
2015-08-26 12:36       ` Daniel Vetter
2015-07-08 20:45 ` [PATCH 10/15] drm/i915: Force common lane on for the PPS kick on CHV ville.syrjala
2015-07-10  7:56   ` [PATCH v2 " ville.syrjala
2015-08-19  2:21   ` [PATCH " Deepak
2015-08-19 11:32     ` Ville Syrjälä
2015-07-08 20:45 ` [PATCH 11/15] drm/i915: Enable DPIO SUS clock gating " ville.syrjala
2015-08-19 13:09   ` Deepak
2015-07-08 20:45 ` [PATCH 12/15] drm/i915: Force CL2 off in CHV x1 PHY ville.syrjala
2015-08-19 13:22   ` Deepak
2015-08-19 13:39     ` Ville Syrjälä
2015-08-26 12:38       ` Daniel Vetter
2015-07-08 20:45 ` [PATCH 13/15] drm/i915: Clean up CHV lane soft reset programming ville.syrjala
2015-07-09 16:27   ` Daniel Vetter
2015-07-09 17:14   ` [PATCH v2 " ville.syrjala
2015-08-27  4:25   ` [PATCH " Deepak
2015-07-08 20:46 ` [PATCH 14/15] drm/i915: Add some CHV DPIO lane power state asserts ville.syrjala
2015-08-27  4:36   ` Deepak
2015-08-27 11:02     ` Ville Syrjälä
2015-08-31 10:47       ` Deepak
2015-07-08 20:46 ` [PATCH 15/15] drm/i915: Add CHV PHY LDO power sanity checks ville.syrjala
2015-08-27  4:39   ` Deepak
2015-09-01  9:45     ` Daniel Vetter
2015-07-09 13:24 ` [PATCH 00/15] drm/i915: CHV DPIO power gating, take two Deepak

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.