All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick
@ 2014-08-18 19:15 ville.syrjala
  2014-08-18 19:15 ` [PATCH 01/14] drm/i915: Parametrize PANEL_PORT_SELECT_VLV ville.syrjala
                   ` (15 more replies)
  0 siblings, 16 replies; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:15 UTC (permalink / raw)
  To: intel-gfx

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

While wrestling with the VLV/CHV panel power sequencer I noticed the locking
in our edp vdd code was rather broken. This series aims to fix that by
introducing a power seqeuencer mutex. I was already thinking about using the
aux.hw_mutex for this since it's already locked around the aux ->transfer()
function, but the VLV/CHV multiple power sequencer issue requires a single
lock instead of per-port.

At the end of the series there's a bit of reordering of the DP port
enable/disable sequences to make subsequent power sequencer kick patches
easier. The last patch fixes the wait_pipe_off() timeouts on my ILK.
Strictly speaking it shouldn't be part of this series, but I couldn't
really test this on my ILK without suffering tons of warnings so I
included it here anyway.

Ville Syrjälä (14):
  drm/i915: Parametrize PANEL_PORT_SELECT_VLV
  drm/i915: Reorganize vlv eDP reboot notifier
  drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst()
  drm/i915: Rename edp vdd funcs for consistency
  drm/i915: Add a note explaining vdd on/off handling in
    intel_dp_aux_ch()
  drm/i915: Replace big nested if block with early return
  drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
  drm/i915: Flatten intel_edp_panel_vdd_on()
  drm/i915: Fix edp vdd locking
  drm/i915: Track which port is using which pipe's power sequencer
  drm/i915: Be more careful when picking the initial power sequencer
    pipe
  drm/i915: Turn on panel power before doing aux transfers
  drm/i915: Enable DP port earlier
  drm/i915: Move DP port disable to post_disable for pch platforms

 drivers/gpu/drm/i915/i915_drv.h      |   3 +
 drivers/gpu/drm/i915/i915_reg.h      |   3 +-
 drivers/gpu/drm/i915/intel_display.c |   2 +
 drivers/gpu/drm/i915/intel_dp.c      | 619 +++++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_drv.h     |   6 +
 5 files changed, 463 insertions(+), 170 deletions(-)

-- 
1.8.5.5

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

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

* [PATCH 01/14] drm/i915: Parametrize PANEL_PORT_SELECT_VLV
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
@ 2014-08-18 19:15 ` ville.syrjala
  2014-08-19  6:58   ` Jani Nikula
  2014-08-18 19:15 ` [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier ville.syrjala
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:15 UTC (permalink / raw)
  To: intel-gfx

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

Passing the port as a parameter to PANEL_PORT_SELECT_VLV results in
neater code. Sadly the PCH port select bits aren't suitable for the
same treatment and the resulting macro would be much uglier, so
leave those defines as is.

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

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index daac02b..9503d96 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5383,8 +5383,7 @@ enum punit_power_well {
 #define PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
 #define PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
 #define PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
-#define  PANEL_PORT_SELECT_DPB_VLV	(1 << 30)
-#define  PANEL_PORT_SELECT_DPC_VLV	(2 << 30)
+#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
 #define PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
 #define PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4f69648..43dd226 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -308,9 +308,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
 		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
 			PANEL_PORT_SELECT_MASK;
-		if (port_sel == PANEL_PORT_SELECT_DPB_VLV && port == PORT_B)
-			return pipe;
-		if (port_sel == PANEL_PORT_SELECT_DPC_VLV && port == PORT_C)
+		if (port_sel == PANEL_PORT_SELECT_VLV(port))
 			return pipe;
 	}
 
@@ -4294,6 +4292,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 	u32 pp_on, pp_off, pp_div, port_sel = 0;
 	int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
 	int pp_on_reg, pp_off_reg, pp_div_reg;
+	enum port port = dp_to_dig_port(intel_dp)->port;
 
 	if (HAS_PCH_SPLIT(dev)) {
 		pp_on_reg = PCH_PP_ON_DELAYS;
@@ -4328,12 +4327,9 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 	/* Haswell doesn't have any port selection bits for the panel
 	 * power sequencer any more. */
 	if (IS_VALLEYVIEW(dev)) {
-		if (dp_to_dig_port(intel_dp)->port == PORT_B)
-			port_sel = PANEL_PORT_SELECT_DPB_VLV;
-		else
-			port_sel = PANEL_PORT_SELECT_DPC_VLV;
+		port_sel = PANEL_PORT_SELECT_VLV(port);
 	} else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
-		if (dp_to_dig_port(intel_dp)->port == PORT_A)
+		if (port == PORT_A)
 			port_sel = PANEL_PORT_SELECT_DPA;
 		else
 			port_sel = PANEL_PORT_SELECT_DPD;
-- 
1.8.5.5

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

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

* [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
  2014-08-18 19:15 ` [PATCH 01/14] drm/i915: Parametrize PANEL_PORT_SELECT_VLV ville.syrjala
@ 2014-08-18 19:15 ` ville.syrjala
  2014-08-18 21:28   ` Clint Taylor
  2014-08-19  7:00   ` Jani Nikula
  2014-08-18 19:15 ` [PATCH 03/14] drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst() ville.syrjala
                   ` (13 subsequent siblings)
  15 siblings, 2 replies; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:15 UTC (permalink / raw)
  To: intel-gfx

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

Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
and flatten the rest of the function.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 43dd226..a9ed2a6 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -347,22 +347,22 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp_div;
 	u32 pp_ctrl_reg, pp_div_reg;
-	enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+	enum pipe pipe;
 
-	if (!is_edp(intel_dp) || code != SYS_RESTART)
+	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
 		return 0;
 
-	if (IS_VALLEYVIEW(dev)) {
-		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
-		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
-		pp_div = I915_READ(pp_div_reg);
-		pp_div &= PP_REFERENCE_DIVIDER_MASK;
+	pipe = vlv_power_sequencer_pipe(intel_dp);
 
-		/* 0x1F write to PP_DIV_REG sets max cycle delay */
-		I915_WRITE(pp_div_reg, pp_div | 0x1F);
-		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
-		msleep(intel_dp->panel_power_cycle_delay);
-	}
+	pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
+	pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
+	pp_div = I915_READ(pp_div_reg);
+	pp_div &= PP_REFERENCE_DIVIDER_MASK;
+
+	/* 0x1F write to PP_DIV_REG sets max cycle delay */
+	I915_WRITE(pp_div_reg, pp_div | 0x1F);
+	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
+	msleep(intel_dp->panel_power_cycle_delay);
 
 	return 0;
 }
-- 
1.8.5.5

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

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

* [PATCH 03/14] drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst()
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
  2014-08-18 19:15 ` [PATCH 01/14] drm/i915: Parametrize PANEL_PORT_SELECT_VLV ville.syrjala
  2014-08-18 19:15 ` [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier ville.syrjala
@ 2014-08-18 19:15 ` ville.syrjala
  2014-08-19  7:12   ` Jani Nikula
  2014-08-18 19:15 ` [PATCH 04/14] drm/i915: Rename edp vdd funcs for consistency ville.syrjala
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:15 UTC (permalink / raw)
  To: intel-gfx

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

We want to use the higher level vdd on func here. Not a big deal
yet (we'd just get the warn when things go awry) but when the
locking gets fixed this becomes more important.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a9ed2a6..28d0183 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3419,7 +3419,7 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
 		return false;
 
-	_edp_panel_vdd_on(intel_dp);
+	intel_edp_panel_vdd_on(intel_dp);
 	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
 		if (buf[0] & DP_MST_CAP) {
 			DRM_DEBUG_KMS("Sink is MST capable\n");
-- 
1.8.5.5

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

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

* [PATCH 04/14] drm/i915: Rename edp vdd funcs for consistency
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (2 preceding siblings ...)
  2014-08-18 19:15 ` [PATCH 03/14] drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst() ville.syrjala
@ 2014-08-18 19:15 ` ville.syrjala
  2014-08-19  7:20   ` Jani Nikula
  2014-08-18 19:16 ` [PATCH 05/14] drm/i915: Add a note explaining vdd on/off handling in intel_dp_aux_ch() ville.syrjala
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:15 UTC (permalink / raw)
  To: intel-gfx

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

edp_* are now the lower level functions and intel_edp_* the higher level
ones. One should use them in pairs.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 28d0183..30943a5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -111,7 +111,7 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 }
 
 static void intel_dp_link_down(struct intel_dp *intel_dp);
-static bool _edp_panel_vdd_on(struct intel_dp *intel_dp);
+static bool edp_panel_vdd_on(struct intel_dp *intel_dp);
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
 
 int
@@ -533,7 +533,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
 	bool vdd;
 
-	vdd = _edp_panel_vdd_on(intel_dp);
+	vdd = edp_panel_vdd_on(intel_dp);
 
 	/* dp aux is extremely sensitive to irq latency, hence request the
 	 * lowest possible wakeup latency and so prevent the cpu from going into
@@ -1165,7 +1165,7 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	return control;
 }
 
-static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
+static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -1216,7 +1216,7 @@ static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	if (is_edp(intel_dp)) {
-		bool vdd = _edp_panel_vdd_on(intel_dp);
+		bool vdd = edp_panel_vdd_on(intel_dp);
 
 		WARN(!vdd, "eDP VDD already requested on\n");
 	}
@@ -1299,6 +1299,11 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 		edp_panel_vdd_schedule_off(intel_dp);
 }
 
+static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+{
+	return edp_panel_vdd_off(intel_dp, sync);
+}
+
 void intel_edp_panel_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -2102,7 +2107,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_start_link_train(intel_dp);
 	intel_edp_panel_on(intel_dp);
-	edp_panel_vdd_off(intel_dp, true);
+	intel_edp_panel_vdd_off(intel_dp, true);
 	intel_dp_complete_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
 }
@@ -3405,7 +3410,7 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 
-	edp_panel_vdd_off(intel_dp, false);
+	intel_edp_panel_vdd_off(intel_dp, false);
 }
 
 static bool
@@ -3429,7 +3434,7 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
 			intel_dp->is_mst = false;
 		}
 	}
-	edp_panel_vdd_off(intel_dp, false);
+	intel_edp_panel_vdd_off(intel_dp, false);
 
 	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
 	return intel_dp->is_mst;
@@ -4527,7 +4532,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	/* Cache DPCD and EDID for edp. */
 	intel_edp_panel_vdd_on(intel_dp);
 	has_dpcd = intel_dp_get_dpcd(intel_dp);
-	edp_panel_vdd_off(intel_dp, false);
+	intel_edp_panel_vdd_off(intel_dp, false);
 
 	if (has_dpcd) {
 		if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
-- 
1.8.5.5

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

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

* [PATCH 05/14] drm/i915: Add a note explaining vdd on/off handling in intel_dp_aux_ch()
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (3 preceding siblings ...)
  2014-08-18 19:15 ` [PATCH 04/14] drm/i915: Rename edp vdd funcs for consistency ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-08-19  7:07   ` Jani Nikula
  2014-08-18 19:16 ` [PATCH 06/14] drm/i915: Replace big nested if block with early return ville.syrjala
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

Add a comment to explain why we care about the current want_panel_vdd
state in intel_dp_aux_ch().

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 30943a5..19a818f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -533,6 +533,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
 	bool vdd;
 
+	/*
+	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
+	 * In such cases we want to leave VDD enabled and it's up to upper layers
+	 * to turn it off. But for eg. i2c-dev access we need to turn it on/off
+	 * ourselves.
+	 */
 	vdd = edp_panel_vdd_on(intel_dp);
 
 	/* dp aux is extremely sensitive to irq latency, hence request the
-- 
1.8.5.5

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

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

* [PATCH 06/14] drm/i915: Replace big nested if block with early return
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (4 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 05/14] drm/i915: Add a note explaining vdd on/off handling in intel_dp_aux_ch() ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-08-19  7:24   ` Jani Nikula
  2014-08-18 19:16 ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() ville.syrjala
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

Looks nicer.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 19a818f..e6b4d4d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1232,38 +1232,38 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_digital_port *intel_dig_port =
+		dp_to_dig_port(intel_dp);
+	struct intel_encoder *intel_encoder = &intel_dig_port->base;
+	enum intel_display_power_domain power_domain;
 	u32 pp;
 	u32 pp_stat_reg, pp_ctrl_reg;
 
 	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
 
-	if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) {
-		struct intel_digital_port *intel_dig_port =
-						dp_to_dig_port(intel_dp);
-		struct intel_encoder *intel_encoder = &intel_dig_port->base;
-		enum intel_display_power_domain power_domain;
+	if (intel_dp->want_panel_vdd || !edp_have_panel_vdd(intel_dp))
+		return;
 
-		DRM_DEBUG_KMS("Turning eDP VDD off\n");
+	DRM_DEBUG_KMS("Turning eDP VDD off\n");
 
-		pp = ironlake_get_pp_control(intel_dp);
-		pp &= ~EDP_FORCE_VDD;
+	pp = ironlake_get_pp_control(intel_dp);
+	pp &= ~EDP_FORCE_VDD;
 
-		pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-		pp_stat_reg = _pp_stat_reg(intel_dp);
+	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+	pp_stat_reg = _pp_stat_reg(intel_dp);
 
-		I915_WRITE(pp_ctrl_reg, pp);
-		POSTING_READ(pp_ctrl_reg);
+	I915_WRITE(pp_ctrl_reg, pp);
+	POSTING_READ(pp_ctrl_reg);
 
-		/* Make sure sequencer is idle before allowing subsequent activity */
-		DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
-		I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
+	/* Make sure sequencer is idle before allowing subsequent activity */
+	DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
+	I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
 
-		if ((pp & POWER_TARGET_ON) == 0)
-			intel_dp->last_power_cycle = jiffies;
+	if ((pp & POWER_TARGET_ON) == 0)
+		intel_dp->last_power_cycle = jiffies;
 
-		power_domain = intel_display_port_power_domain(intel_encoder);
-		intel_display_power_put(dev_priv, power_domain);
-	}
+	power_domain = intel_display_port_power_domain(intel_encoder);
+	intel_display_power_put(dev_priv, power_domain);
 }
 
 static void edp_panel_vdd_work(struct work_struct *__work)
-- 
1.8.5.5

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

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

* [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (5 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 06/14] drm/i915: Replace big nested if block with early return ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-08-19  7:36   ` Jani Nikula
  2014-08-18 19:16 ` [PATCH 08/14] drm/i915: Flatten intel_edp_panel_vdd_on() ville.syrjala
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

If we force vdd off warn if someone is still using it. With this
change the delayed vdd off work needs to check want_panel_vdd
itself to make sure it doesn't try to turn vdd off when someone
is using it.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e6b4d4d..0fb510c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1241,7 +1241,9 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 
 	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
 
-	if (intel_dp->want_panel_vdd || !edp_have_panel_vdd(intel_dp))
+	WARN_ON(intel_dp->want_panel_vdd);
+
+	if (!edp_have_panel_vdd(intel_dp))
 		return;
 
 	DRM_DEBUG_KMS("Turning eDP VDD off\n");
@@ -1273,7 +1275,8 @@ static void edp_panel_vdd_work(struct work_struct *__work)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
 	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-	edp_panel_vdd_off_sync(intel_dp);
+	if (!intel_dp->want_panel_vdd)
+		edp_panel_vdd_off_sync(intel_dp);
 	drm_modeset_unlock(&dev->mode_config.connection_mutex);
 }
 
-- 
1.8.5.5

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

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

* [PATCH 08/14] drm/i915: Flatten intel_edp_panel_vdd_on()
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (6 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-08-19  7:30   ` Jani Nikula
  2014-08-18 19:16 ` [PATCH 09/14] drm/i915: Fix edp vdd locking ville.syrjala
                   ` (7 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

Less pointless indentation is always nice. There will be a bit more
code in this function once the power sequencer locking is fixed.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0fb510c..7ae9a9a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1221,11 +1221,14 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
-	if (is_edp(intel_dp)) {
-		bool vdd = edp_panel_vdd_on(intel_dp);
+	bool vdd;
 
-		WARN(!vdd, "eDP VDD already requested on\n");
-	}
+	if (!is_edp(intel_dp))
+		return;
+
+	vdd = edp_panel_vdd_on(intel_dp);
+
+	WARN(!vdd, "eDP VDD already requested on\n");
 }
 
 static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
-- 
1.8.5.5

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

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

* [PATCH 09/14] drm/i915: Fix edp vdd locking
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (7 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 08/14] drm/i915: Flatten intel_edp_panel_vdd_on() ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-08-19 17:32   ` [PATCH v2 " ville.syrjala
  2014-08-18 19:16 ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer ville.syrjala
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

Introduce a new mutex (pps_mutex) to protect the power sequencer
state. For now this state includes want_panel_vdd as well as the
power sequencer registers.

We need a single mutex (as opposed to per port) because later on we
will need to deal with VLV/CHV which have multiple power sequencer
which can be reassigned to different ports.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  3 ++
 drivers/gpu/drm/i915/intel_display.c |  2 +
 drivers/gpu/drm/i915/intel_dp.c      | 97 +++++++++++++++++++++++++++++++-----
 3 files changed, 90 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 4754328..8684898 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1501,6 +1501,9 @@ struct drm_i915_private {
 	/* LVDS info */
 	bool no_aux_handshake;
 
+	/* protects panel power sequencer state */
+	struct mutex pps_mutex;
+
 	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3f8e037..04c0e5d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12437,6 +12437,8 @@ static void intel_init_display(struct drm_device *dev)
 	}
 
 	intel_panel_init_backlight_funcs(dev);
+
+	mutex_init(&dev_priv->pps_mutex);
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 7ae9a9a..556e4de 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -300,6 +300,8 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 	enum port port = intel_dig_port->port;
 	enum pipe pipe;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	/* modeset should have pipe */
 	if (crtc)
 		return to_intel_crtc(crtc)->pipe;
@@ -352,6 +354,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
 		return 0;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	pipe = vlv_power_sequencer_pipe(intel_dp);
 
 	pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
@@ -364,6 +368,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
 	msleep(intel_dp->panel_power_cycle_delay);
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
 	return 0;
 }
 
@@ -372,6 +378,8 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
 }
 
@@ -383,6 +391,8 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	enum intel_display_power_domain power_domain;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	return intel_display_power_enabled(dev_priv, power_domain) &&
 	       (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
@@ -533,6 +543,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
 	bool vdd;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	/*
 	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
 	 * In such cases we want to leave VDD enabled and it's up to upper layers
@@ -648,6 +660,8 @@ out:
 	if (vdd)
 		edp_panel_vdd_off(intel_dp, false);
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
 	return ret;
 }
 
@@ -1102,6 +1116,8 @@ static void wait_panel_status(struct intel_dp *intel_dp,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp_stat_reg, pp_ctrl_reg;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	pp_stat_reg = _pp_stat_reg(intel_dp);
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
@@ -1165,6 +1181,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 control;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	control = I915_READ(_pp_ctrl_reg(intel_dp));
 	control &= ~PANEL_UNLOCK_MASK;
 	control |= PANEL_UNLOCK_REGS;
@@ -1182,6 +1200,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 	u32 pp_stat_reg, pp_ctrl_reg;
 	bool need_to_disable = !intel_dp->want_panel_vdd;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (!is_edp(intel_dp))
 		return false;
 
@@ -1221,12 +1241,16 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
 	bool vdd;
 
 	if (!is_edp(intel_dp))
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
 	vdd = edp_panel_vdd_on(intel_dp);
+	mutex_unlock(&dev_priv->pps_mutex);
 
 	WARN(!vdd, "eDP VDD already requested on\n");
 }
@@ -1242,7 +1266,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 	u32 pp;
 	u32 pp_stat_reg, pp_ctrl_reg;
 
-	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	WARN_ON(intel_dp->want_panel_vdd);
 
@@ -1275,12 +1299,13 @@ static void edp_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
 						 struct intel_dp, panel_vdd_work);
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
 
-	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	mutex_lock(&dev_priv->pps_mutex);
 	if (!intel_dp->want_panel_vdd)
 		edp_panel_vdd_off_sync(intel_dp);
-	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
@@ -1298,6 +1323,11 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
 
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (!is_edp(intel_dp))
 		return;
 
@@ -1313,7 +1343,15 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
 static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
-	return edp_panel_vdd_off(intel_dp, sync);
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
+
+	if (!is_edp(intel_dp))
+		return;
+
+	mutex_lock(&dev_priv->pps_mutex);
+	edp_panel_vdd_off(intel_dp, sync);
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_panel_on(struct intel_dp *intel_dp)
@@ -1328,9 +1366,11 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power on\n");
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	if (edp_have_panel_power(intel_dp)) {
 		DRM_DEBUG_KMS("eDP power already on\n");
-		return;
+		goto out;
 	}
 
 	wait_panel_power_cycle(intel_dp);
@@ -1359,6 +1399,9 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 		I915_WRITE(pp_ctrl_reg, pp);
 		POSTING_READ(pp_ctrl_reg);
 	}
+
+ out:
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
@@ -1376,6 +1419,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
 
 	pp = ironlake_get_pp_control(intel_dp);
@@ -1397,6 +1442,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 	/* We got a reference when we enabled the VDD. */
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	intel_display_power_put(dev_priv, power_domain);
+
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1421,6 +1468,9 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
 	 * allowing it to appear.
 	 */
 	wait_backlight_on(intel_dp);
+
+	mutex_lock(&dev_priv->pps_mutex);
+
 	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_BLC_ENABLE;
 
@@ -1428,6 +1478,8 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
+
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_backlight_off(struct intel_dp *intel_dp)
@@ -1440,6 +1492,8 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
 	if (!is_edp(intel_dp))
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	DRM_DEBUG_KMS("\n");
 	pp = ironlake_get_pp_control(intel_dp);
 	pp &= ~EDP_BLC_ENABLE;
@@ -1448,8 +1502,10 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
-	intel_dp->last_backlight_off = jiffies;
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
+	intel_dp->last_backlight_off = jiffies;
 	edp_wait_backlight_off(intel_dp);
 
 	intel_panel_disable_backlight(intel_dp->attached_connector);
@@ -2182,9 +2238,11 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 
 	if (is_edp(intel_dp)) {
 		/* init power sequencer on this pipe and port */
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
 							      &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_enable_dp(encoder);
@@ -2284,9 +2342,11 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 
 	if (is_edp(intel_dp)) {
 		/* init power sequencer on this pipe and port */
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
 							      &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_enable_dp(encoder);
@@ -4024,15 +4084,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	drm_dp_aux_unregister(&intel_dp->aux);
 	intel_dp_mst_encoder_cleanup(intel_dig_port);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+		mutex_lock(&dev_priv->pps_mutex);
 		edp_panel_vdd_off_sync(intel_dp);
-		drm_modeset_unlock(&dev->mode_config.connection_mutex);
+		mutex_unlock(&dev_priv->pps_mutex);
 		if (intel_dp->edp_notifier.notifier_call) {
 			unregister_reboot_notifier(&intel_dp->edp_notifier);
 			intel_dp->edp_notifier.notifier_call = NULL;
@@ -4210,6 +4271,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 	u32 pp_on, pp_off, pp_div, pp;
 	int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (HAS_PCH_SPLIT(dev)) {
 		pp_ctrl_reg = PCH_PP_CONTROL;
 		pp_on_reg = PCH_PP_ON_DELAYS;
@@ -4311,6 +4374,8 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 	int pp_on_reg, pp_off_reg, pp_div_reg;
 	enum port port = dp_to_dig_port(intel_dp)->port;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (HAS_PCH_SPLIT(dev)) {
 		pp_on_reg = PCH_PP_ON_DELAYS;
 		pp_off_reg = PCH_PP_OFF_DELAYS;
@@ -4503,9 +4568,11 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	intel_dp = enc_to_intel_dp(&intel_encoder->base);
 	if (!edp_have_panel_vdd(intel_dp))
-		return;
+		goto out;
 	/*
 	 * The VDD bit needs a power domain reference, so if the bit is
 	 * already enabled when we boot or resume, grab this reference and
@@ -4517,6 +4584,8 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 	intel_display_power_get(dev_priv, power_domain);
 
 	edp_panel_vdd_schedule_off(intel_dp);
+ out:
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
@@ -4558,7 +4627,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 
 	/* We now know it's not a ghost, init power sequence regs. */
+	mutex_lock(&dev_priv->pps_mutex);
 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
+	mutex_unlock(&dev_priv->pps_mutex);
 
 	mutex_lock(&dev->mode_config.mutex);
 	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
@@ -4690,8 +4761,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	}
 
 	if (is_edp(intel_dp)) {
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_timestamps(intel_dp);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_dp_aux_init(intel_dp, intel_connector);
@@ -4707,9 +4780,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		drm_dp_aux_unregister(&intel_dp->aux);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-			drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+			mutex_lock(&dev_priv->pps_mutex);
 			edp_panel_vdd_off_sync(intel_dp);
-			drm_modeset_unlock(&dev->mode_config.connection_mutex);
+			mutex_unlock(&dev_priv->pps_mutex);
 		}
 		drm_connector_unregister(connector);
 		drm_connector_cleanup(connector);
-- 
1.8.5.5

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

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

* [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (8 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 09/14] drm/i915: Fix edp vdd locking ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-08-19 17:45   ` [PATCH 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off ville.syrjala
                     ` (2 more replies)
  2014-08-18 19:16 ` [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe ville.syrjala
                   ` (5 subsequent siblings)
  15 siblings, 3 replies; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

VLV/CHV have a per-pipe panel power sequencer which locks onto the
port once used. We need to keep track wich power sequencers are
locked to which ports.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 185 ++++++++++++++++++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_drv.h |   6 ++
 2 files changed, 168 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 556e4de..4614e6e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -294,28 +294,99 @@ static enum pipe
 vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	enum port port = intel_dig_port->port;
-	enum pipe pipe;
+	struct intel_encoder *encoder;
+	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
+	struct edp_power_seq power_seq;
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	/* modeset should have pipe */
-	if (crtc)
-		return to_intel_crtc(crtc)->pipe;
+	if (intel_dp->pps_pipe != INVALID_PIPE)
+		return intel_dp->pps_pipe;
+
+	/*
+	 * We don't have power sequencer currently.
+	 * Pick one that's not used by other ports.
+	 */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		struct intel_dp *tmp;
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		tmp = enc_to_intel_dp(&encoder->base);
+
+		if (tmp->pps_pipe != INVALID_PIPE)
+			pipes &= ~(1 << tmp->pps_pipe);
+	}
+
+	/*
+	 * Didn't find one. This should not happen since there
+	 * are two power sequencers and up to two eDP ports.
+	 */
+	if (WARN_ON(pipes == 0))
+		return PIPE_A;
+
+	intel_dp->pps_pipe = ffs(pipes) - 1;
+
+	DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n",
+		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
+
+	/* init power sequencer on this pipe and port */
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
+
+	return intel_dp->pps_pipe;
+}
+
+static enum pipe
+vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
+				 enum port port)
+{
+	enum pipe pipe;
 
-	/* init time, try to find a pipe with this port selected */
 	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
 		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
 			PANEL_PORT_SELECT_MASK;
-		if (port_sel == PANEL_PORT_SELECT_VLV(port))
-			return pipe;
+
+		if (port_sel != PANEL_PORT_SELECT_VLV(port))
+			continue;
+
+		return pipe;
+	}
+
+	return INVALID_PIPE;
+}
+
+static void
+vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct edp_power_seq power_seq;
+	enum port port = intel_dig_port->port;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	/* try to find a pipe with this port selected */
+	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port);
+
+	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
+	if (intel_dp->pps_pipe == INVALID_PIPE) {
+		DRM_DEBUG_KMS("no initial power sequencer for port %c\n",
+			      port_name(port));
+		return;
 	}
 
-	/* shrug */
-	return PIPE_A;
+	DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n",
+		      port_name(port), pipe_name(intel_dp->pps_pipe));
+
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
 }
 
 static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
@@ -2209,6 +2280,76 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder)
 	}
 }
 
+static void vlv_steal_power_sequencer(struct drm_device *dev,
+				      enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		struct intel_dp *intel_dp;
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		intel_dp = enc_to_intel_dp(&encoder->base);
+
+		if (intel_dp->pps_pipe != pipe)
+			continue;
+
+		DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
+			      pipe_name(pipe),
+			      port_name(dp_to_dig_port(intel_dp)->port));
+
+		/* make sure vdd is off before we steal it */
+		edp_panel_vdd_off_sync(intel_dp);
+
+		intel_dp->pps_pipe = INVALID_PIPE;
+	}
+}
+
+static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &intel_dig_port->base;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	struct edp_power_seq power_seq;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if (intel_dp->pps_pipe == crtc->pipe)
+		return;
+
+	/*
+	 * If another power sequencer was being used on this
+	 * port previously make sure to turn off vdd there while
+	 * we still have control of it.
+	 */
+	if (intel_dp->pps_pipe != INVALID_PIPE)
+		edp_panel_vdd_off_sync(intel_dp);
+
+	/*
+	 * We may be stealing the power
+	 * sequencer from another port.
+	 */
+	vlv_steal_power_sequencer(dev, crtc->pipe);
+
+	/* now it's all ours */
+	intel_dp->pps_pipe = crtc->pipe;
+
+	DRM_DEBUG_KMS("initializing pipe %c power sequencer for port %c\n",
+		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
+
+	/* init power sequencer on this pipe and port */
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
+}
+
 static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -2218,7 +2359,6 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	enum dpio_channel port = vlv_dport_to_channel(dport);
 	int pipe = intel_crtc->pipe;
-	struct edp_power_seq power_seq;
 	u32 val;
 
 	mutex_lock(&dev_priv->dpio_lock);
@@ -2237,11 +2377,8 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		/* init power sequencer on this pipe and port */
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-							      &power_seq);
+		vlv_init_panel_power_sequencer(intel_dp);
 		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
@@ -2286,7 +2423,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	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 edp_power_seq power_seq;
 	struct intel_crtc *intel_crtc =
 		to_intel_crtc(encoder->base.crtc);
 	enum dpio_channel ch = vlv_dport_to_channel(dport);
@@ -2341,11 +2477,8 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		/* init power sequencer on this pipe and port */
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-							      &power_seq);
+		vlv_init_panel_power_sequencer(intel_dp);
 		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
@@ -4691,6 +4824,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	struct edp_power_seq power_seq = { 0 };
 	int type;
 
+	intel_dp->pps_pipe = INVALID_PIPE;
+
 	/* intel_dp vfuncs */
 	if (IS_VALLEYVIEW(dev))
 		intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
@@ -4762,8 +4897,12 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 
 	if (is_edp(intel_dp)) {
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_timestamps(intel_dp);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+		if (IS_VALLEYVIEW(dev)) {
+			vlv_initial_power_sequencer_setup(intel_dp);
+		} else {
+			intel_dp_init_panel_power_timestamps(intel_dp);
+			intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+		}
 		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index ad4e69b..d36299b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -560,6 +560,12 @@ struct intel_dp {
 
 	struct notifier_block edp_notifier;
 
+	/*
+	 * Pipe whose power sequencer is currently locked into
+	 * this port. Only relevant on VLV/CHV.
+	 */
+	enum pipe pps_pipe;
+
 	bool use_tps3;
 	bool can_mst; /* this port supports mst */
 	bool is_mst;
-- 
1.8.5.5

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

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

* [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (9 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-09-02 13:52   ` Imre Deak
  2014-09-04 12:59   ` Daniel Vetter
  2014-08-18 19:16 ` [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers ville.syrjala
                   ` (4 subsequent siblings)
  15 siblings, 2 replies; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

Try to make sure we find the power sequencer that the BIOS used
by first looking for one which has the panel power enabled, then
fall back to one with VDD force bit enabled, and finally look at
just the port select bits. This should make us pick the correct
power sequencer when the BIOS has already enabled the panel.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4614e6e..4952783 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -341,9 +341,31 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 	return intel_dp->pps_pipe;
 }
 
+typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
+			       enum pipe pipe);
+
+static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
+			       enum pipe pipe)
+{
+	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
+}
+
+static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
+				enum pipe pipe)
+{
+	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
+}
+
+static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
+			 enum pipe pipe)
+{
+	return true;
+}
+
 static enum pipe
 vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
-				 enum port port)
+				 enum port port,
+				 vlv_pipe_check pipe_check)
 {
 	enum pipe pipe;
 
@@ -354,6 +376,9 @@ vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
 		if (port_sel != PANEL_PORT_SELECT_VLV(port))
 			continue;
 
+		if (!pipe_check(dev_priv, pipe))
+			continue;
+
 		return pipe;
 	}
 
@@ -372,7 +397,14 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	/* try to find a pipe with this port selected */
-	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port);
+	/* first pick one where the panel is on */
+	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_has_pp_on);
+	/* didn't find one? pick one where vdd is on */
+	if (intel_dp->pps_pipe == INVALID_PIPE)
+		intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_has_vdd_on);
+	/* didn't find one? pick one with just the correct port */
+	if (intel_dp->pps_pipe == INVALID_PIPE)
+		intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_any);
 
 	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
 	if (intel_dp->pps_pipe == INVALID_PIPE) {
-- 
1.8.5.5

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

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

* [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (10 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-08-19  7:33   ` Jani Nikula
  2014-09-02 14:02   ` Imre Deak
  2014-08-18 19:16 ` [PATCH 13/14] drm/i915: Enable DP port earlier ville.syrjala
                   ` (3 subsequent siblings)
  15 siblings, 2 replies; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

On VLV/CHV the panel power sequencer may need to be "kicked" a bit to
lock onto the new port, and that needs to happen before any aux
transfers are attempted if we want the aux transfers to actaully
succeed. So turn on panel power (part of the "kick") before aux
transfers (DPMS_ON + link training).

This also matches the documented modeset sequence better for pch
platforms. The documentation doesn't explicitly state anything about the
DPMS or link training DPCD writes, but the panel power on step is
always listed before link training is mentioned.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 4952783..28bc652 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2275,10 +2275,10 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 		return;
 
 	intel_edp_panel_vdd_on(intel_dp);
-	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
-	intel_dp_start_link_train(intel_dp);
 	intel_edp_panel_on(intel_dp);
 	intel_edp_panel_vdd_off(intel_dp, true);
+	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+	intel_dp_start_link_train(intel_dp);
 	intel_dp_complete_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
 }
-- 
1.8.5.5

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

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

* [PATCH 13/14] drm/i915: Enable DP port earlier
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (11 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-09-03 11:02   ` Imre Deak
  2014-08-18 19:16 ` [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms ville.syrjala
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

Bspec says we should enable the DP port before enabling panel power,
and that the port must be enabled with training pattern 1. Do so.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 28bc652..12925be 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2264,6 +2264,104 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 }
 
+static void
+_intel_dp_set_link_train(struct intel_dp *intel_dp,
+			 uint32_t *DP,
+			 uint8_t dp_train_pat)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum port port = intel_dig_port->port;
+
+	if (HAS_DDI(dev)) {
+		uint32_t temp = I915_READ(DP_TP_CTL(port));
+
+		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
+			temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
+		else
+			temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
+
+		temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
+		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+		case DP_TRAINING_PATTERN_DISABLE:
+			temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
+
+			break;
+		case DP_TRAINING_PATTERN_1:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
+			break;
+		case DP_TRAINING_PATTERN_2:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
+			break;
+		case DP_TRAINING_PATTERN_3:
+			temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
+			break;
+		}
+		I915_WRITE(DP_TP_CTL(port), temp);
+
+	} else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
+		*DP &= ~DP_LINK_TRAIN_MASK_CPT;
+
+		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+		case DP_TRAINING_PATTERN_DISABLE:
+			*DP |= DP_LINK_TRAIN_OFF_CPT;
+			break;
+		case DP_TRAINING_PATTERN_1:
+			*DP |= DP_LINK_TRAIN_PAT_1_CPT;
+			break;
+		case DP_TRAINING_PATTERN_2:
+			*DP |= DP_LINK_TRAIN_PAT_2_CPT;
+			break;
+		case DP_TRAINING_PATTERN_3:
+			DRM_ERROR("DP training pattern 3 not supported\n");
+			*DP |= DP_LINK_TRAIN_PAT_2_CPT;
+			break;
+		}
+
+	} else {
+		if (IS_CHERRYVIEW(dev))
+			*DP &= ~DP_LINK_TRAIN_MASK_CHV;
+		else
+			*DP &= ~DP_LINK_TRAIN_MASK;
+
+		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
+		case DP_TRAINING_PATTERN_DISABLE:
+			*DP |= DP_LINK_TRAIN_OFF;
+			break;
+		case DP_TRAINING_PATTERN_1:
+			*DP |= DP_LINK_TRAIN_PAT_1;
+			break;
+		case DP_TRAINING_PATTERN_2:
+			*DP |= DP_LINK_TRAIN_PAT_2;
+			break;
+		case DP_TRAINING_PATTERN_3:
+			if (IS_CHERRYVIEW(dev)) {
+				*DP |= DP_LINK_TRAIN_PAT_3_CHV;
+			} else {
+				DRM_ERROR("DP training pattern 3 not supported\n");
+				*DP |= DP_LINK_TRAIN_PAT_2;
+			}
+			break;
+		}
+	}
+}
+
+static void intel_dp_enable_port(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	intel_dp->DP |= DP_PORT_EN;
+
+	/* enable with pattern 1 (as per spec) */
+	_intel_dp_set_link_train(intel_dp, &intel_dp->DP,
+				 DP_TRAINING_PATTERN_1);
+
+	I915_WRITE(intel_dp->output_reg, intel_dp->DP);
+	POSTING_READ(intel_dp->output_reg);
+}
+
 static void intel_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -2274,6 +2372,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	if (WARN_ON(dp_reg & DP_PORT_EN))
 		return;
 
+	intel_dp_enable_port(intel_dp);
 	intel_edp_panel_vdd_on(intel_dp);
 	intel_edp_panel_on(intel_dp);
 	intel_edp_panel_vdd_off(intel_dp, true);
@@ -3174,81 +3273,10 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	enum port port = intel_dig_port->port;
 	uint8_t buf[sizeof(intel_dp->train_set) + 1];
 	int ret, len;
 
-	if (HAS_DDI(dev)) {
-		uint32_t temp = I915_READ(DP_TP_CTL(port));
-
-		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
-			temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
-		else
-			temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
-
-		temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
-		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
-		case DP_TRAINING_PATTERN_DISABLE:
-			temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
-
-			break;
-		case DP_TRAINING_PATTERN_1:
-			temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
-			break;
-		case DP_TRAINING_PATTERN_2:
-			temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
-			break;
-		case DP_TRAINING_PATTERN_3:
-			temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
-			break;
-		}
-		I915_WRITE(DP_TP_CTL(port), temp);
-
-	} else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
-		*DP &= ~DP_LINK_TRAIN_MASK_CPT;
-
-		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
-		case DP_TRAINING_PATTERN_DISABLE:
-			*DP |= DP_LINK_TRAIN_OFF_CPT;
-			break;
-		case DP_TRAINING_PATTERN_1:
-			*DP |= DP_LINK_TRAIN_PAT_1_CPT;
-			break;
-		case DP_TRAINING_PATTERN_2:
-			*DP |= DP_LINK_TRAIN_PAT_2_CPT;
-			break;
-		case DP_TRAINING_PATTERN_3:
-			DRM_ERROR("DP training pattern 3 not supported\n");
-			*DP |= DP_LINK_TRAIN_PAT_2_CPT;
-			break;
-		}
-
-	} else {
-		if (IS_CHERRYVIEW(dev))
-			*DP &= ~DP_LINK_TRAIN_MASK_CHV;
-		else
-			*DP &= ~DP_LINK_TRAIN_MASK;
-
-		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
-		case DP_TRAINING_PATTERN_DISABLE:
-			*DP |= DP_LINK_TRAIN_OFF;
-			break;
-		case DP_TRAINING_PATTERN_1:
-			*DP |= DP_LINK_TRAIN_PAT_1;
-			break;
-		case DP_TRAINING_PATTERN_2:
-			*DP |= DP_LINK_TRAIN_PAT_2;
-			break;
-		case DP_TRAINING_PATTERN_3:
-			if (IS_CHERRYVIEW(dev)) {
-				*DP |= DP_LINK_TRAIN_PAT_3_CHV;
-			} else {
-				DRM_ERROR("DP training pattern 3 not supported\n");
-				*DP |= DP_LINK_TRAIN_PAT_2;
-			}
-			break;
-		}
-	}
+	_intel_dp_set_link_train(intel_dp, DP, dp_train_pat);
 
 	I915_WRITE(intel_dp->output_reg, *DP);
 	POSTING_READ(intel_dp->output_reg);
-- 
1.8.5.5

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

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

* [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (12 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 13/14] drm/i915: Enable DP port earlier ville.syrjala
@ 2014-08-18 19:16 ` ville.syrjala
  2014-08-26  9:43   ` Daniel Vetter
  2014-09-03 11:20   ` Imre Deak
  2014-08-19  7:45 ` [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick Jani Nikula
  2014-08-19  8:08 ` Jani Nikula
  15 siblings, 2 replies; 63+ messages in thread
From: ville.syrjala @ 2014-08-18 19:16 UTC (permalink / raw)
  To: intel-gfx

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

We need to turn the DP port off after the pipe, otherwise the pipe won't
turn off properly on certain pch platforms at least (happens on my ILK for
example).  This also matches the BSpec modeset sequence better. We still
don't match the spec exactly though (eg. audio disable should happen
much earlier), but at last this eliminates the nasty
wait_for_pipe_off() timeouts.

We already did the port disable after the pipe for VLV/CHV and for CPU
eDP.

For g4x leave the port disable where it is since that matches the
modeset sequence in the documentation and I don't have a suitable
machine to test if the other order would work.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 12925be..915d4ec 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2194,7 +2194,6 @@ void intel_edp_psr_init(struct drm_device *dev)
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
-	enum port port = dp_to_dig_port(intel_dp)->port;
 	struct drm_device *dev = encoder->base.dev;
 
 	/* Make sure the panel is off before trying to change the mode. But also
@@ -2204,21 +2203,19 @@ static void intel_disable_dp(struct intel_encoder *encoder)
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
 	intel_edp_panel_off(intel_dp);
 
-	/* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */
-	if (!(port == PORT_A || IS_VALLEYVIEW(dev)))
+	/* disable the port before the pipe on g4x */
+	if (INTEL_INFO(dev)->gen < 5)
 		intel_dp_link_down(intel_dp);
 }
 
-static void g4x_post_disable_dp(struct intel_encoder *encoder)
+static void ilk_post_disable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
 	enum port port = dp_to_dig_port(intel_dp)->port;
 
-	if (port != PORT_A)
-		return;
-
 	intel_dp_link_down(intel_dp);
-	ironlake_edp_pll_off(intel_dp);
+	if (port == PORT_A)
+		ironlake_edp_pll_off(intel_dp);
 }
 
 static void vlv_post_disable_dp(struct intel_encoder *encoder)
@@ -5044,7 +5041,8 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
 	} else {
 		intel_encoder->pre_enable = g4x_pre_enable_dp;
 		intel_encoder->enable = g4x_enable_dp;
-		intel_encoder->post_disable = g4x_post_disable_dp;
+		if (INTEL_INFO(dev)->gen >= 5)
+			intel_encoder->post_disable = ilk_post_disable_dp;
 	}
 
 	intel_dig_port->port = port;
-- 
1.8.5.5

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

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-18 19:15 ` [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier ville.syrjala
@ 2014-08-18 21:28   ` Clint Taylor
  2014-08-19  7:00   ` Jani Nikula
  1 sibling, 0 replies; 63+ messages in thread
From: Clint Taylor @ 2014-08-18 21:28 UTC (permalink / raw)
  To: intel-gfx

On 08/18/2014 12:15 PM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
> and flatten the rest of the function.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/intel_dp.c | 24 ++++++++++++------------
>   1 file changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 43dd226..a9ed2a6 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -347,22 +347,22 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>   	struct drm_i915_private *dev_priv = dev->dev_private;
>   	u32 pp_div;
>   	u32 pp_ctrl_reg, pp_div_reg;
> -	enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> +	enum pipe pipe;
>
> -	if (!is_edp(intel_dp) || code != SYS_RESTART)
> +	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
>   		return 0;
>
> -	if (IS_VALLEYVIEW(dev)) {
> -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> -		pp_div = I915_READ(pp_div_reg);
> -		pp_div &= PP_REFERENCE_DIVIDER_MASK;
> +	pipe = vlv_power_sequencer_pipe(intel_dp);
>
> -		/* 0x1F write to PP_DIV_REG sets max cycle delay */
> -		I915_WRITE(pp_div_reg, pp_div | 0x1F);
> -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> -		msleep(intel_dp->panel_power_cycle_delay);
> -	}
> +	pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> +	pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> +	pp_div = I915_READ(pp_div_reg);
> +	pp_div &= PP_REFERENCE_DIVIDER_MASK;
> +
> +	/* 0x1F write to PP_DIV_REG sets max cycle delay */
> +	I915_WRITE(pp_div_reg, pp_div | 0x1F);
> +	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> +	msleep(intel_dp->panel_power_cycle_delay);

Looks better..

>
>   	return 0;
>   }
>

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

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

* Re: [PATCH 01/14] drm/i915: Parametrize PANEL_PORT_SELECT_VLV
  2014-08-18 19:15 ` [PATCH 01/14] drm/i915: Parametrize PANEL_PORT_SELECT_VLV ville.syrjala
@ 2014-08-19  6:58   ` Jani Nikula
  0 siblings, 0 replies; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  6:58 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Passing the port as a parameter to PANEL_PORT_SELECT_VLV results in
> neater code. Sadly the PCH port select bits aren't suitable for the
> same treatment and the resulting macro would be much uglier, so
> leave those defines as is.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_reg.h |  3 +--
>  drivers/gpu/drm/i915/intel_dp.c | 12 ++++--------
>  2 files changed, 5 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index daac02b..9503d96 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -5383,8 +5383,7 @@ enum punit_power_well {
>  #define PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
>  #define PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
>  #define PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
> -#define  PANEL_PORT_SELECT_DPB_VLV	(1 << 30)
> -#define  PANEL_PORT_SELECT_DPC_VLV	(2 << 30)
> +#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
>  #define PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
>  #define PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)
>  
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4f69648..43dd226 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -308,9 +308,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
>  		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
>  			PANEL_PORT_SELECT_MASK;
> -		if (port_sel == PANEL_PORT_SELECT_DPB_VLV && port == PORT_B)
> -			return pipe;
> -		if (port_sel == PANEL_PORT_SELECT_DPC_VLV && port == PORT_C)
> +		if (port_sel == PANEL_PORT_SELECT_VLV(port))
>  			return pipe;
>  	}
>  
> @@ -4294,6 +4292,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>  	u32 pp_on, pp_off, pp_div, port_sel = 0;
>  	int div = HAS_PCH_SPLIT(dev) ? intel_pch_rawclk(dev) : intel_hrawclk(dev);
>  	int pp_on_reg, pp_off_reg, pp_div_reg;
> +	enum port port = dp_to_dig_port(intel_dp)->port;
>  
>  	if (HAS_PCH_SPLIT(dev)) {
>  		pp_on_reg = PCH_PP_ON_DELAYS;
> @@ -4328,12 +4327,9 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>  	/* Haswell doesn't have any port selection bits for the panel
>  	 * power sequencer any more. */
>  	if (IS_VALLEYVIEW(dev)) {
> -		if (dp_to_dig_port(intel_dp)->port == PORT_B)
> -			port_sel = PANEL_PORT_SELECT_DPB_VLV;
> -		else
> -			port_sel = PANEL_PORT_SELECT_DPC_VLV;
> +		port_sel = PANEL_PORT_SELECT_VLV(port);
>  	} else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) {
> -		if (dp_to_dig_port(intel_dp)->port == PORT_A)
> +		if (port == PORT_A)
>  			port_sel = PANEL_PORT_SELECT_DPA;
>  		else
>  			port_sel = PANEL_PORT_SELECT_DPD;
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-18 19:15 ` [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier ville.syrjala
  2014-08-18 21:28   ` Clint Taylor
@ 2014-08-19  7:00   ` Jani Nikula
  2014-08-26 12:58     ` Ville Syrjälä
  1 sibling, 1 reply; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:00 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
> and flatten the rest of the function.

Please imagine adding another platform there, and realize this just adds
unnecessary churn.

BR,
Jani.


>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 43dd226..a9ed2a6 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -347,22 +347,22 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u32 pp_div;
>  	u32 pp_ctrl_reg, pp_div_reg;
> -	enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> +	enum pipe pipe;
>  
> -	if (!is_edp(intel_dp) || code != SYS_RESTART)
> +	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
>  		return 0;
>  
> -	if (IS_VALLEYVIEW(dev)) {
> -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> -		pp_div = I915_READ(pp_div_reg);
> -		pp_div &= PP_REFERENCE_DIVIDER_MASK;
> +	pipe = vlv_power_sequencer_pipe(intel_dp);
>  
> -		/* 0x1F write to PP_DIV_REG sets max cycle delay */
> -		I915_WRITE(pp_div_reg, pp_div | 0x1F);
> -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> -		msleep(intel_dp->panel_power_cycle_delay);
> -	}
> +	pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> +	pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> +	pp_div = I915_READ(pp_div_reg);
> +	pp_div &= PP_REFERENCE_DIVIDER_MASK;
> +
> +	/* 0x1F write to PP_DIV_REG sets max cycle delay */
> +	I915_WRITE(pp_div_reg, pp_div | 0x1F);
> +	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> +	msleep(intel_dp->panel_power_cycle_delay);
>  
>  	return 0;
>  }
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 05/14] drm/i915: Add a note explaining vdd on/off handling in intel_dp_aux_ch()
  2014-08-18 19:16 ` [PATCH 05/14] drm/i915: Add a note explaining vdd on/off handling in intel_dp_aux_ch() ville.syrjala
@ 2014-08-19  7:07   ` Jani Nikula
  0 siblings, 0 replies; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:07 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Add a comment to explain why we care about the current want_panel_vdd
> state in intel_dp_aux_ch().

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 30943a5..19a818f 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -533,6 +533,12 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
>  	bool has_aux_irq = HAS_AUX_IRQ(dev);
>  	bool vdd;
>  
> +	/*
> +	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
> +	 * In such cases we want to leave VDD enabled and it's up to upper layers
> +	 * to turn it off. But for eg. i2c-dev access we need to turn it on/off
> +	 * ourselves.
> +	 */
>  	vdd = edp_panel_vdd_on(intel_dp);
>  
>  	/* dp aux is extremely sensitive to irq latency, hence request the
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 03/14] drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst()
  2014-08-18 19:15 ` [PATCH 03/14] drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst() ville.syrjala
@ 2014-08-19  7:12   ` Jani Nikula
  0 siblings, 0 replies; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:12 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We want to use the higher level vdd on func here. Not a big deal
> yet (we'd just get the warn when things go awry) but when the
> locking gets fixed this becomes more important.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index a9ed2a6..28d0183 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -3419,7 +3419,7 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
>  	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
>  		return false;
>  
> -	_edp_panel_vdd_on(intel_dp);
> +	intel_edp_panel_vdd_on(intel_dp);
>  	if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_MSTM_CAP, buf, 1)) {
>  		if (buf[0] & DP_MST_CAP) {
>  			DRM_DEBUG_KMS("Sink is MST capable\n");
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 04/14] drm/i915: Rename edp vdd funcs for consistency
  2014-08-18 19:15 ` [PATCH 04/14] drm/i915: Rename edp vdd funcs for consistency ville.syrjala
@ 2014-08-19  7:20   ` Jani Nikula
  2014-08-19 10:24     ` [PATCH v2 " ville.syrjala
  0 siblings, 1 reply; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:20 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> edp_* are now the lower level functions and intel_edp_* the higher level
> ones. One should use them in pairs.

Yeah I should've done this when I added the lower level ones. One thing
you need to fix below though.

> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 21 +++++++++++++--------
>  1 file changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 28d0183..30943a5 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -111,7 +111,7 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
>  }
>  
>  static void intel_dp_link_down(struct intel_dp *intel_dp);
> -static bool _edp_panel_vdd_on(struct intel_dp *intel_dp);
> +static bool edp_panel_vdd_on(struct intel_dp *intel_dp);
>  static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
>  
>  int
> @@ -533,7 +533,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
>  	bool has_aux_irq = HAS_AUX_IRQ(dev);
>  	bool vdd;
>  
> -	vdd = _edp_panel_vdd_on(intel_dp);
> +	vdd = edp_panel_vdd_on(intel_dp);
>  
>  	/* dp aux is extremely sensitive to irq latency, hence request the
>  	 * lowest possible wakeup latency and so prevent the cpu from going into
> @@ -1165,7 +1165,7 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
>  	return control;
>  }
>  
> -static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
> +static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> @@ -1216,7 +1216,7 @@ static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
>  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
>  	if (is_edp(intel_dp)) {
> -		bool vdd = _edp_panel_vdd_on(intel_dp);
> +		bool vdd = edp_panel_vdd_on(intel_dp);
>  
>  		WARN(!vdd, "eDP VDD already requested on\n");
>  	}
> @@ -1299,6 +1299,11 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  		edp_panel_vdd_schedule_off(intel_dp);
>  }
>  
> +static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
> +{
> +	return edp_panel_vdd_off(intel_dp, sync);

Please don't return voids. With that fixed,

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> +}
> +
>  void intel_edp_panel_on(struct intel_dp *intel_dp)
>  {
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -2102,7 +2107,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
>  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>  	intel_dp_start_link_train(intel_dp);
>  	intel_edp_panel_on(intel_dp);
> -	edp_panel_vdd_off(intel_dp, true);
> +	intel_edp_panel_vdd_off(intel_dp, true);
>  	intel_dp_complete_link_train(intel_dp);
>  	intel_dp_stop_link_train(intel_dp);
>  }
> @@ -3405,7 +3410,7 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
>  		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
>  			      buf[0], buf[1], buf[2]);
>  
> -	edp_panel_vdd_off(intel_dp, false);
> +	intel_edp_panel_vdd_off(intel_dp, false);
>  }
>  
>  static bool
> @@ -3429,7 +3434,7 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
>  			intel_dp->is_mst = false;
>  		}
>  	}
> -	edp_panel_vdd_off(intel_dp, false);
> +	intel_edp_panel_vdd_off(intel_dp, false);
>  
>  	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
>  	return intel_dp->is_mst;
> @@ -4527,7 +4532,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	/* Cache DPCD and EDID for edp. */
>  	intel_edp_panel_vdd_on(intel_dp);
>  	has_dpcd = intel_dp_get_dpcd(intel_dp);
> -	edp_panel_vdd_off(intel_dp, false);
> +	intel_edp_panel_vdd_off(intel_dp, false);
>  
>  	if (has_dpcd) {
>  		if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 06/14] drm/i915: Replace big nested if block with early return
  2014-08-18 19:16 ` [PATCH 06/14] drm/i915: Replace big nested if block with early return ville.syrjala
@ 2014-08-19  7:24   ` Jani Nikula
  0 siblings, 0 replies; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:24 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Looks nicer.

Side note, I kind of like adding "No functional changes." in the commit
messages of patches that do not intend to do functional changes. I find
it helpful.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 40 ++++++++++++++++++++--------------------
>  1 file changed, 20 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 19a818f..e6b4d4d 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1232,38 +1232,38 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
>  {
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_digital_port *intel_dig_port =
> +		dp_to_dig_port(intel_dp);
> +	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> +	enum intel_display_power_domain power_domain;
>  	u32 pp;
>  	u32 pp_stat_reg, pp_ctrl_reg;
>  
>  	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
>  
> -	if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) {
> -		struct intel_digital_port *intel_dig_port =
> -						dp_to_dig_port(intel_dp);
> -		struct intel_encoder *intel_encoder = &intel_dig_port->base;
> -		enum intel_display_power_domain power_domain;
> +	if (intel_dp->want_panel_vdd || !edp_have_panel_vdd(intel_dp))
> +		return;
>  
> -		DRM_DEBUG_KMS("Turning eDP VDD off\n");
> +	DRM_DEBUG_KMS("Turning eDP VDD off\n");
>  
> -		pp = ironlake_get_pp_control(intel_dp);
> -		pp &= ~EDP_FORCE_VDD;
> +	pp = ironlake_get_pp_control(intel_dp);
> +	pp &= ~EDP_FORCE_VDD;
>  
> -		pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -		pp_stat_reg = _pp_stat_reg(intel_dp);
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +	pp_stat_reg = _pp_stat_reg(intel_dp);
>  
> -		I915_WRITE(pp_ctrl_reg, pp);
> -		POSTING_READ(pp_ctrl_reg);
> +	I915_WRITE(pp_ctrl_reg, pp);
> +	POSTING_READ(pp_ctrl_reg);
>  
> -		/* Make sure sequencer is idle before allowing subsequent activity */
> -		DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> -		I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
> +	/* Make sure sequencer is idle before allowing subsequent activity */
> +	DRM_DEBUG_KMS("PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> +	I915_READ(pp_stat_reg), I915_READ(pp_ctrl_reg));
>  
> -		if ((pp & POWER_TARGET_ON) == 0)
> -			intel_dp->last_power_cycle = jiffies;
> +	if ((pp & POWER_TARGET_ON) == 0)
> +		intel_dp->last_power_cycle = jiffies;
>  
> -		power_domain = intel_display_port_power_domain(intel_encoder);
> -		intel_display_power_put(dev_priv, power_domain);
> -	}
> +	power_domain = intel_display_port_power_domain(intel_encoder);
> +	intel_display_power_put(dev_priv, power_domain);
>  }
>  
>  static void edp_panel_vdd_work(struct work_struct *__work)
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 08/14] drm/i915: Flatten intel_edp_panel_vdd_on()
  2014-08-18 19:16 ` [PATCH 08/14] drm/i915: Flatten intel_edp_panel_vdd_on() ville.syrjala
@ 2014-08-19  7:30   ` Jani Nikula
  2014-08-19 10:49     ` Ville Syrjälä
  0 siblings, 1 reply; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:30 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Less pointless indentation is always nice. There will be a bit more
> code in this function once the power sequencer locking is fixed.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

This could be earlier in the series, right?

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 0fb510c..7ae9a9a 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1221,11 +1221,14 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  
>  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
> -	if (is_edp(intel_dp)) {
> -		bool vdd = edp_panel_vdd_on(intel_dp);
> +	bool vdd;
>  
> -		WARN(!vdd, "eDP VDD already requested on\n");
> -	}
> +	if (!is_edp(intel_dp))
> +		return;
> +
> +	vdd = edp_panel_vdd_on(intel_dp);
> +
> +	WARN(!vdd, "eDP VDD already requested on\n");
>  }
>  
>  static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers
  2014-08-18 19:16 ` [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers ville.syrjala
@ 2014-08-19  7:33   ` Jani Nikula
  2014-08-19 10:57     ` Ville Syrjälä
  2014-09-02 14:02   ` Imre Deak
  1 sibling, 1 reply; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:33 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> On VLV/CHV the panel power sequencer may need to be "kicked" a bit to
> lock onto the new port, and that needs to happen before any aux
> transfers are attempted if we want the aux transfers to actaully
> succeed. So turn on panel power (part of the "kick") before aux
> transfers (DPMS_ON + link training).
>
> This also matches the documented modeset sequence better for pch
> platforms. The documentation doesn't explicitly state anything about the
> DPMS or link training DPCD writes, but the panel power on step is
> always listed before link training is mentioned.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4952783..28bc652 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2275,10 +2275,10 @@ static void intel_enable_dp(struct intel_encoder *encoder)
>  		return;
>  
>  	intel_edp_panel_vdd_on(intel_dp);
> -	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> -	intel_dp_start_link_train(intel_dp);
>  	intel_edp_panel_on(intel_dp);
>  	intel_edp_panel_vdd_off(intel_dp, true);
> +	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> +	intel_dp_start_link_train(intel_dp);

Please dig into the git history in this area. I fear this may
regress. We've juggled this too many times...

BR,
Jani.

>  	intel_dp_complete_link_train(intel_dp);
>  	intel_dp_stop_link_train(intel_dp);
>  }
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
  2014-08-18 19:16 ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() ville.syrjala
@ 2014-08-19  7:36   ` Jani Nikula
  2014-08-19 10:39     ` Ville Syrjälä
  0 siblings, 1 reply; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:36 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> If we force vdd off warn if someone is still using it. With this
> change the delayed vdd off work needs to check want_panel_vdd
> itself to make sure it doesn't try to turn vdd off when someone
> is using it.

I think this calls for a prep cleanup patch to check and fix the uses of
edp_panel_vdd_off(intel_dp, true)
vs. edp_panel_vdd_off_sync(intel_dp). In particular, why are there
direct calls to the latter all over the place? Seems wrong.

BR,
Jani.


>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index e6b4d4d..0fb510c 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1241,7 +1241,9 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
>  
>  	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
>  
> -	if (intel_dp->want_panel_vdd || !edp_have_panel_vdd(intel_dp))
> +	WARN_ON(intel_dp->want_panel_vdd);
> +
> +	if (!edp_have_panel_vdd(intel_dp))
>  		return;
>  
>  	DRM_DEBUG_KMS("Turning eDP VDD off\n");
> @@ -1273,7 +1275,8 @@ static void edp_panel_vdd_work(struct work_struct *__work)
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  
>  	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -	edp_panel_vdd_off_sync(intel_dp);
> +	if (!intel_dp->want_panel_vdd)
> +		edp_panel_vdd_off_sync(intel_dp);
>  	drm_modeset_unlock(&dev->mode_config.connection_mutex);
>  }
>  
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (13 preceding siblings ...)
  2014-08-18 19:16 ` [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms ville.syrjala
@ 2014-08-19  7:45 ` Jani Nikula
  2014-08-26  9:37   ` Daniel Vetter
  2014-08-19  8:08 ` Jani Nikula
  15 siblings, 1 reply; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  7:45 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> While wrestling with the VLV/CHV panel power sequencer I noticed the locking
> in our edp vdd code was rather broken. This series aims to fix that by
> introducing a power seqeuencer mutex. I was already thinking about using the
> aux.hw_mutex for this since it's already locked around the aux ->transfer()
> function, but the VLV/CHV multiple power sequencer issue requires a single
> lock instead of per-port.
>
> At the end of the series there's a bit of reordering of the DP port
> enable/disable sequences to make subsequent power sequencer kick patches
> easier. The last patch fixes the wait_pipe_off() timeouts on my ILK.
> Strictly speaking it shouldn't be part of this series, but I couldn't
> really test this on my ILK without suffering tons of warnings so I
> included it here anyway.

This is what I'd like to happen here:

1) Patches [1] from me and [2] from Clinton get reviewed and merged
first, through -fixes.

2) The rest of the patches in my series after [1] get reviewed and
merged, through dinq.

3) The first part of this series, up to the locking bits, mostly
reviewed now, get refreshed on top the above, should not conflict much,
and we can start merging them while...

4) The second part of this series, from about the locking on, get
reviewed and merged.

I want this order to make backporting steps 1 and 2 as painless as
possible. Please help review them, and I'll follow through with this
series.

BR,
Jani.



[1] http://mid.gmane.org/e7a47b50ed0f25cafdc26711fc09561ea8af3b81.1407849872.git.jani.nikula@intel.com
[2] http://mid.gmane.org/1408394915-21882-1-git-send-email-clinton.a.taylor@intel.com



>
> Ville Syrjälä (14):
>   drm/i915: Parametrize PANEL_PORT_SELECT_VLV
>   drm/i915: Reorganize vlv eDP reboot notifier
>   drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst()
>   drm/i915: Rename edp vdd funcs for consistency
>   drm/i915: Add a note explaining vdd on/off handling in
>     intel_dp_aux_ch()
>   drm/i915: Replace big nested if block with early return
>   drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
>   drm/i915: Flatten intel_edp_panel_vdd_on()
>   drm/i915: Fix edp vdd locking
>   drm/i915: Track which port is using which pipe's power sequencer
>   drm/i915: Be more careful when picking the initial power sequencer
>     pipe
>   drm/i915: Turn on panel power before doing aux transfers
>   drm/i915: Enable DP port earlier
>   drm/i915: Move DP port disable to post_disable for pch platforms
>
>  drivers/gpu/drm/i915/i915_drv.h      |   3 +
>  drivers/gpu/drm/i915/i915_reg.h      |   3 +-
>  drivers/gpu/drm/i915/intel_display.c |   2 +
>  drivers/gpu/drm/i915/intel_dp.c      | 619 +++++++++++++++++++++++++----------
>  drivers/gpu/drm/i915/intel_drv.h     |   6 +
>  5 files changed, 463 insertions(+), 170 deletions(-)
>
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick
  2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
                   ` (14 preceding siblings ...)
  2014-08-19  7:45 ` [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick Jani Nikula
@ 2014-08-19  8:08 ` Jani Nikula
  2014-08-19 10:46   ` Ville Syrjälä
  15 siblings, 1 reply; 63+ messages in thread
From: Jani Nikula @ 2014-08-19  8:08 UTC (permalink / raw)
  To: ville.syrjala, intel-gfx

On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> While wrestling with the VLV/CHV panel power sequencer I noticed the locking
> in our edp vdd code was rather broken. This series aims to fix that by
> introducing a power seqeuencer mutex. I was already thinking about using the
> aux.hw_mutex for this since it's already locked around the aux ->transfer()
> function, but the VLV/CHV multiple power sequencer issue requires a single
> lock instead of per-port.

For extra kicks, see i915_save_display() and i915_restore_display(). Why
are we doing this to ourselves?

BR,
Jani.



>
> At the end of the series there's a bit of reordering of the DP port
> enable/disable sequences to make subsequent power sequencer kick patches
> easier. The last patch fixes the wait_pipe_off() timeouts on my ILK.
> Strictly speaking it shouldn't be part of this series, but I couldn't
> really test this on my ILK without suffering tons of warnings so I
> included it here anyway.
>
> Ville Syrjälä (14):
>   drm/i915: Parametrize PANEL_PORT_SELECT_VLV
>   drm/i915: Reorganize vlv eDP reboot notifier
>   drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst()
>   drm/i915: Rename edp vdd funcs for consistency
>   drm/i915: Add a note explaining vdd on/off handling in
>     intel_dp_aux_ch()
>   drm/i915: Replace big nested if block with early return
>   drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
>   drm/i915: Flatten intel_edp_panel_vdd_on()
>   drm/i915: Fix edp vdd locking
>   drm/i915: Track which port is using which pipe's power sequencer
>   drm/i915: Be more careful when picking the initial power sequencer
>     pipe
>   drm/i915: Turn on panel power before doing aux transfers
>   drm/i915: Enable DP port earlier
>   drm/i915: Move DP port disable to post_disable for pch platforms
>
>  drivers/gpu/drm/i915/i915_drv.h      |   3 +
>  drivers/gpu/drm/i915/i915_reg.h      |   3 +-
>  drivers/gpu/drm/i915/intel_display.c |   2 +
>  drivers/gpu/drm/i915/intel_dp.c      | 619 +++++++++++++++++++++++++----------
>  drivers/gpu/drm/i915/intel_drv.h     |   6 +
>  5 files changed, 463 insertions(+), 170 deletions(-)
>
> -- 
> 1.8.5.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* [PATCH v2 04/14] drm/i915: Rename edp vdd funcs for consistency
  2014-08-19  7:20   ` Jani Nikula
@ 2014-08-19 10:24     ` ville.syrjala
  0 siblings, 0 replies; 63+ messages in thread
From: ville.syrjala @ 2014-08-19 10:24 UTC (permalink / raw)
  To: intel-gfx

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

edp_* are now the lower level functions and intel_edp_* the higher level
ones. One should use them in pairs.

v2: Don't return void (Jani)

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 28d0183..dbaac22 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -111,7 +111,7 @@ static struct intel_dp *intel_attached_dp(struct drm_connector *connector)
 }
 
 static void intel_dp_link_down(struct intel_dp *intel_dp);
-static bool _edp_panel_vdd_on(struct intel_dp *intel_dp);
+static bool edp_panel_vdd_on(struct intel_dp *intel_dp);
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
 
 int
@@ -533,7 +533,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
 	bool vdd;
 
-	vdd = _edp_panel_vdd_on(intel_dp);
+	vdd = edp_panel_vdd_on(intel_dp);
 
 	/* dp aux is extremely sensitive to irq latency, hence request the
 	 * lowest possible wakeup latency and so prevent the cpu from going into
@@ -1165,7 +1165,7 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	return control;
 }
 
-static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
+static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
@@ -1216,7 +1216,7 @@ static bool _edp_panel_vdd_on(struct intel_dp *intel_dp)
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	if (is_edp(intel_dp)) {
-		bool vdd = _edp_panel_vdd_on(intel_dp);
+		bool vdd = edp_panel_vdd_on(intel_dp);
 
 		WARN(!vdd, "eDP VDD already requested on\n");
 	}
@@ -1299,6 +1299,11 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 		edp_panel_vdd_schedule_off(intel_dp);
 }
 
+static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+{
+	edp_panel_vdd_off(intel_dp, sync);
+}
+
 void intel_edp_panel_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -2102,7 +2107,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
 	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
 	intel_dp_start_link_train(intel_dp);
 	intel_edp_panel_on(intel_dp);
-	edp_panel_vdd_off(intel_dp, true);
+	intel_edp_panel_vdd_off(intel_dp, true);
 	intel_dp_complete_link_train(intel_dp);
 	intel_dp_stop_link_train(intel_dp);
 }
@@ -3405,7 +3410,7 @@ intel_dp_probe_oui(struct intel_dp *intel_dp)
 		DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
 			      buf[0], buf[1], buf[2]);
 
-	edp_panel_vdd_off(intel_dp, false);
+	intel_edp_panel_vdd_off(intel_dp, false);
 }
 
 static bool
@@ -3429,7 +3434,7 @@ intel_dp_probe_mst(struct intel_dp *intel_dp)
 			intel_dp->is_mst = false;
 		}
 	}
-	edp_panel_vdd_off(intel_dp, false);
+	intel_edp_panel_vdd_off(intel_dp, false);
 
 	drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
 	return intel_dp->is_mst;
@@ -4527,7 +4532,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	/* Cache DPCD and EDID for edp. */
 	intel_edp_panel_vdd_on(intel_dp);
 	has_dpcd = intel_dp_get_dpcd(intel_dp);
-	edp_panel_vdd_off(intel_dp, false);
+	intel_edp_panel_vdd_off(intel_dp, false);
 
 	if (has_dpcd) {
 		if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
-- 
1.8.5.5

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

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

* Re: [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
  2014-08-19  7:36   ` Jani Nikula
@ 2014-08-19 10:39     ` Ville Syrjälä
  2014-08-19 13:37       ` Jani Nikula
  0 siblings, 1 reply; 63+ messages in thread
From: Ville Syrjälä @ 2014-08-19 10:39 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 10:36:52AM +0300, Jani Nikula wrote:
> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > If we force vdd off warn if someone is still using it. With this
> > change the delayed vdd off work needs to check want_panel_vdd
> > itself to make sure it doesn't try to turn vdd off when someone
> > is using it.
> 
> I think this calls for a prep cleanup patch to check and fix the uses of
> edp_panel_vdd_off(intel_dp, true)
> vs. edp_panel_vdd_off_sync(intel_dp). In particular, why are there
> direct calls to the latter all over the place? Seems wrong.

edp_panel_vdd_off() should always be paired with a edp_panel_vdd_on().
If we were to call edp_panel_vdd_off() without the correct pairing we
would get a warning due to want_panel_vdd==false, whereas
edp_panel_vdd_off_sync() will now warn when want_panel_vdd==true.
The direct calls to edp_panel_vdd_off_sync() are in places where we
should not have want_panel_vdd==true (eg. system suspend) but we
just want to force vdd off even if the delayed off work has alrady
been scheduled.

> 
> BR,
> Jani.
> 
> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 7 +++++--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index e6b4d4d..0fb510c 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1241,7 +1241,9 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> >  
> >  	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> >  
> > -	if (intel_dp->want_panel_vdd || !edp_have_panel_vdd(intel_dp))
> > +	WARN_ON(intel_dp->want_panel_vdd);
> > +
> > +	if (!edp_have_panel_vdd(intel_dp))
> >  		return;
> >  
> >  	DRM_DEBUG_KMS("Turning eDP VDD off\n");
> > @@ -1273,7 +1275,8 @@ static void edp_panel_vdd_work(struct work_struct *__work)
> >  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> >  
> >  	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> > -	edp_panel_vdd_off_sync(intel_dp);
> > +	if (!intel_dp->want_panel_vdd)
> > +		edp_panel_vdd_off_sync(intel_dp);
> >  	drm_modeset_unlock(&dev->mode_config.connection_mutex);
> >  }
> >  
> > -- 
> > 1.8.5.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick
  2014-08-19  8:08 ` Jani Nikula
@ 2014-08-19 10:46   ` Ville Syrjälä
  2014-08-26  9:35     ` Daniel Vetter
  0 siblings, 1 reply; 63+ messages in thread
From: Ville Syrjälä @ 2014-08-19 10:46 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 11:08:33AM +0300, Jani Nikula wrote:
> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > While wrestling with the VLV/CHV panel power sequencer I noticed the locking
> > in our edp vdd code was rather broken. This series aims to fix that by
> > introducing a power seqeuencer mutex. I was already thinking about using the
> > aux.hw_mutex for this since it's already locked around the aux ->transfer()
> > function, but the VLV/CHV multiple power sequencer issue requires a single
> > lock instead of per-port.
> 
> For extra kicks, see i915_save_display() and i915_restore_display(). Why
> are we doing this to ourselves?

Yeah, crap all around. I suppose someone needs to frob the lvds code
a bit before we can kill the power sequencer stuff from those two
functions.

> 
> BR,
> Jani.
> 
> 
> 
> >
> > At the end of the series there's a bit of reordering of the DP port
> > enable/disable sequences to make subsequent power sequencer kick patches
> > easier. The last patch fixes the wait_pipe_off() timeouts on my ILK.
> > Strictly speaking it shouldn't be part of this series, but I couldn't
> > really test this on my ILK without suffering tons of warnings so I
> > included it here anyway.
> >
> > Ville Syrjälä (14):
> >   drm/i915: Parametrize PANEL_PORT_SELECT_VLV
> >   drm/i915: Reorganize vlv eDP reboot notifier
> >   drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst()
> >   drm/i915: Rename edp vdd funcs for consistency
> >   drm/i915: Add a note explaining vdd on/off handling in
> >     intel_dp_aux_ch()
> >   drm/i915: Replace big nested if block with early return
> >   drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
> >   drm/i915: Flatten intel_edp_panel_vdd_on()
> >   drm/i915: Fix edp vdd locking
> >   drm/i915: Track which port is using which pipe's power sequencer
> >   drm/i915: Be more careful when picking the initial power sequencer
> >     pipe
> >   drm/i915: Turn on panel power before doing aux transfers
> >   drm/i915: Enable DP port earlier
> >   drm/i915: Move DP port disable to post_disable for pch platforms
> >
> >  drivers/gpu/drm/i915/i915_drv.h      |   3 +
> >  drivers/gpu/drm/i915/i915_reg.h      |   3 +-
> >  drivers/gpu/drm/i915/intel_display.c |   2 +
> >  drivers/gpu/drm/i915/intel_dp.c      | 619 +++++++++++++++++++++++++----------
> >  drivers/gpu/drm/i915/intel_drv.h     |   6 +
> >  5 files changed, 463 insertions(+), 170 deletions(-)
> >
> > -- 
> > 1.8.5.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH 08/14] drm/i915: Flatten intel_edp_panel_vdd_on()
  2014-08-19  7:30   ` Jani Nikula
@ 2014-08-19 10:49     ` Ville Syrjälä
  0 siblings, 0 replies; 63+ messages in thread
From: Ville Syrjälä @ 2014-08-19 10:49 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 10:30:25AM +0300, Jani Nikula wrote:
> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Less pointless indentation is always nice. There will be a bit more
> > code in this function once the power sequencer locking is fixed.
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> This could be earlier in the series, right?

Yeah doens't really matter. Or could even be squashed with the locking
patch.

> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 11 +++++++----
> >  1 file changed, 7 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 0fb510c..7ae9a9a 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -1221,11 +1221,14 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
> >  
> >  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
> >  {
> > -	if (is_edp(intel_dp)) {
> > -		bool vdd = edp_panel_vdd_on(intel_dp);
> > +	bool vdd;
> >  
> > -		WARN(!vdd, "eDP VDD already requested on\n");
> > -	}
> > +	if (!is_edp(intel_dp))
> > +		return;
> > +
> > +	vdd = edp_panel_vdd_on(intel_dp);
> > +
> > +	WARN(!vdd, "eDP VDD already requested on\n");
> >  }
> >  
> >  static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> > -- 
> > 1.8.5.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers
  2014-08-19  7:33   ` Jani Nikula
@ 2014-08-19 10:57     ` Ville Syrjälä
  2014-08-26 12:41       ` Daniel Vetter
  0 siblings, 1 reply; 63+ messages in thread
From: Ville Syrjälä @ 2014-08-19 10:57 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 10:33:15AM +0300, Jani Nikula wrote:
> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > On VLV/CHV the panel power sequencer may need to be "kicked" a bit to
> > lock onto the new port, and that needs to happen before any aux
> > transfers are attempted if we want the aux transfers to actaully
> > succeed. So turn on panel power (part of the "kick") before aux
> > transfers (DPMS_ON + link training).
> >
> > This also matches the documented modeset sequence better for pch
> > platforms. The documentation doesn't explicitly state anything about the
> > DPMS or link training DPCD writes, but the panel power on step is
> > always listed before link training is mentioned.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 4952783..28bc652 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -2275,10 +2275,10 @@ static void intel_enable_dp(struct intel_encoder *encoder)
> >  		return;
> >  
> >  	intel_edp_panel_vdd_on(intel_dp);
> > -	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> > -	intel_dp_start_link_train(intel_dp);
> >  	intel_edp_panel_on(intel_dp);
> >  	intel_edp_panel_vdd_off(intel_dp, true);
> > +	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> > +	intel_dp_start_link_train(intel_dp);
> 
> Please dig into the git history in this area. I fear this may
> regress. We've juggled this too many times...

I did. But I couldn't spot much solid analysis of the problems in the
earlier patches/reverts. It's mostly been guesswork AFAICS. Most of it
seems to be back and forth with the force vdd on/off vs. panel power on,
but this patch doesn't change that order.

Also:
a) we need this patch on VLV/CHV at the very least
b) this agrees with the bspec modeset sequence for pch platforms better
c) my ILK with CPU eDP seems happy with the new order

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
  2014-08-19 10:39     ` Ville Syrjälä
@ 2014-08-19 13:37       ` Jani Nikula
  2014-08-19 17:47         ` [PATCH 15/14] drm/i915: Add comments explaining the vdd on/off functions ville.syrjala
  2014-08-26  9:21         ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() Daniel Vetter
  0 siblings, 2 replies; 63+ messages in thread
From: Jani Nikula @ 2014-08-19 13:37 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, 19 Aug 2014, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> On Tue, Aug 19, 2014 at 10:36:52AM +0300, Jani Nikula wrote:
>> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > If we force vdd off warn if someone is still using it. With this
>> > change the delayed vdd off work needs to check want_panel_vdd
>> > itself to make sure it doesn't try to turn vdd off when someone
>> > is using it.
>> 
>> I think this calls for a prep cleanup patch to check and fix the uses of
>> edp_panel_vdd_off(intel_dp, true)
>> vs. edp_panel_vdd_off_sync(intel_dp). In particular, why are there
>> direct calls to the latter all over the place? Seems wrong.
>
> edp_panel_vdd_off() should always be paired with a edp_panel_vdd_on().
> If we were to call edp_panel_vdd_off() without the correct pairing we
> would get a warning due to want_panel_vdd==false, whereas
> edp_panel_vdd_off_sync() will now warn when want_panel_vdd==true.
> The direct calls to edp_panel_vdd_off_sync() are in places where we
> should not have want_panel_vdd==true (eg. system suspend) but we
> just want to force vdd off even if the delayed off work has alrady
> been scheduled.

Okay, care to add some of that as brief documentation comments for the
functions in question, as follow-up? IMO detailed kernel-docs here won't
be read by anyone and will just get stale.

BR,
Jani.

>
>> 
>> BR,
>> Jani.
>> 
>> 
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/intel_dp.c | 7 +++++--
>> >  1 file changed, 5 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> > index e6b4d4d..0fb510c 100644
>> > --- a/drivers/gpu/drm/i915/intel_dp.c
>> > +++ b/drivers/gpu/drm/i915/intel_dp.c
>> > @@ -1241,7 +1241,9 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
>> >  
>> >  	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
>> >  
>> > -	if (intel_dp->want_panel_vdd || !edp_have_panel_vdd(intel_dp))
>> > +	WARN_ON(intel_dp->want_panel_vdd);
>> > +
>> > +	if (!edp_have_panel_vdd(intel_dp))
>> >  		return;
>> >  
>> >  	DRM_DEBUG_KMS("Turning eDP VDD off\n");
>> > @@ -1273,7 +1275,8 @@ static void edp_panel_vdd_work(struct work_struct *__work)
>> >  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>> >  
>> >  	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
>> > -	edp_panel_vdd_off_sync(intel_dp);
>> > +	if (!intel_dp->want_panel_vdd)
>> > +		edp_panel_vdd_off_sync(intel_dp);
>> >  	drm_modeset_unlock(&dev->mode_config.connection_mutex);
>> >  }
>> >  
>> > -- 
>> > 1.8.5.5
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>> 
>> -- 
>> Jani Nikula, Intel Open Source Technology Center
>
> -- 
> Ville Syrjälä
> Intel OTC

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

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

* [PATCH v2 09/14] drm/i915: Fix edp vdd locking
  2014-08-18 19:16 ` [PATCH 09/14] drm/i915: Fix edp vdd locking ville.syrjala
@ 2014-08-19 17:32   ` ville.syrjala
  2014-09-02 13:07     ` Imre Deak
  0 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-19 17:32 UTC (permalink / raw)
  To: intel-gfx

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

Introduce a new mutex (pps_mutex) to protect the power sequencer
state. For now this state includes want_panel_vdd as well as the
power sequencer registers.

We need a single mutex (as opposed to per port) because later on we
will need to deal with VLV/CHV which have multiple power sequencer
which can be reassigned to different ports.

v2: Add the locking to intel_dp_encoder_suspend too (Imre)

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |  3 ++
 drivers/gpu/drm/i915/intel_display.c |  2 +
 drivers/gpu/drm/i915/intel_dp.c      | 99 ++++++++++++++++++++++++++++++++----
 3 files changed, 93 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6fbd316..c5faefb 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1501,6 +1501,9 @@ struct drm_i915_private {
 	/* LVDS info */
 	bool no_aux_handshake;
 
+	/* protects panel power sequencer state */
+	struct mutex pps_mutex;
+
 	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0b327eb..ff86729 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12437,6 +12437,8 @@ static void intel_init_display(struct drm_device *dev)
 	}
 
 	intel_panel_init_backlight_funcs(dev);
+
+	mutex_init(&dev_priv->pps_mutex);
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 9efa6bf..446df28 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -300,6 +300,8 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 	enum port port = intel_dig_port->port;
 	enum pipe pipe;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	/* modeset should have pipe */
 	if (crtc)
 		return to_intel_crtc(crtc)->pipe;
@@ -352,6 +354,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
 		return 0;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	pipe = vlv_power_sequencer_pipe(intel_dp);
 
 	pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
@@ -364,6 +368,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
 	msleep(intel_dp->panel_power_cycle_delay);
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
 	return 0;
 }
 
@@ -372,6 +378,8 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
 }
 
@@ -383,6 +391,8 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	enum intel_display_power_domain power_domain;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	return intel_display_power_enabled(dev_priv, power_domain) &&
 	       (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
@@ -533,6 +543,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
 	bool vdd;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	/*
 	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
 	 * In such cases we want to leave VDD enabled and it's up to upper layers
@@ -648,6 +660,8 @@ out:
 	if (vdd)
 		edp_panel_vdd_off(intel_dp, false);
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
 	return ret;
 }
 
@@ -1102,6 +1116,8 @@ static void wait_panel_status(struct intel_dp *intel_dp,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp_stat_reg, pp_ctrl_reg;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	pp_stat_reg = _pp_stat_reg(intel_dp);
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
@@ -1165,6 +1181,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 control;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	control = I915_READ(_pp_ctrl_reg(intel_dp));
 	control &= ~PANEL_UNLOCK_MASK;
 	control |= PANEL_UNLOCK_REGS;
@@ -1182,6 +1200,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 	u32 pp_stat_reg, pp_ctrl_reg;
 	bool need_to_disable = !intel_dp->want_panel_vdd;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (!is_edp(intel_dp))
 		return false;
 
@@ -1221,12 +1241,16 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
 	bool vdd;
 
 	if (!is_edp(intel_dp))
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
 	vdd = edp_panel_vdd_on(intel_dp);
+	mutex_unlock(&dev_priv->pps_mutex);
 
 	WARN(!vdd, "eDP VDD already requested on\n");
 }
@@ -1242,7 +1266,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 	u32 pp;
 	u32 pp_stat_reg, pp_ctrl_reg;
 
-	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	WARN_ON(intel_dp->want_panel_vdd);
 
@@ -1275,12 +1299,13 @@ static void edp_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
 						 struct intel_dp, panel_vdd_work);
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
 
-	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	mutex_lock(&dev_priv->pps_mutex);
 	if (!intel_dp->want_panel_vdd)
 		edp_panel_vdd_off_sync(intel_dp);
-	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
@@ -1298,6 +1323,11 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
 
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (!is_edp(intel_dp))
 		return;
 
@@ -1313,7 +1343,15 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
 static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
+
+	if (!is_edp(intel_dp))
+		return;
+
+	mutex_lock(&dev_priv->pps_mutex);
 	edp_panel_vdd_off(intel_dp, sync);
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_panel_on(struct intel_dp *intel_dp)
@@ -1328,9 +1366,11 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power on\n");
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	if (edp_have_panel_power(intel_dp)) {
 		DRM_DEBUG_KMS("eDP power already on\n");
-		return;
+		goto out;
 	}
 
 	wait_panel_power_cycle(intel_dp);
@@ -1359,6 +1399,9 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 		I915_WRITE(pp_ctrl_reg, pp);
 		POSTING_READ(pp_ctrl_reg);
 	}
+
+ out:
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
@@ -1376,6 +1419,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
 
 	pp = ironlake_get_pp_control(intel_dp);
@@ -1397,6 +1442,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 	/* We got a reference when we enabled the VDD. */
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	intel_display_power_put(dev_priv, power_domain);
+
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1421,6 +1468,9 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
 	 * allowing it to appear.
 	 */
 	wait_backlight_on(intel_dp);
+
+	mutex_lock(&dev_priv->pps_mutex);
+
 	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_BLC_ENABLE;
 
@@ -1428,6 +1478,8 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
+
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_backlight_off(struct intel_dp *intel_dp)
@@ -1440,6 +1492,8 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
 	if (!is_edp(intel_dp))
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	DRM_DEBUG_KMS("\n");
 	pp = ironlake_get_pp_control(intel_dp);
 	pp &= ~EDP_BLC_ENABLE;
@@ -1448,8 +1502,10 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
-	intel_dp->last_backlight_off = jiffies;
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
+	intel_dp->last_backlight_off = jiffies;
 	edp_wait_backlight_off(intel_dp);
 
 	intel_panel_disable_backlight(intel_dp->attached_connector);
@@ -2182,9 +2238,11 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 
 	if (is_edp(intel_dp)) {
 		/* init power sequencer on this pipe and port */
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
 							      &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_enable_dp(encoder);
@@ -2284,9 +2342,11 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 
 	if (is_edp(intel_dp)) {
 		/* init power sequencer on this pipe and port */
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
 							      &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_enable_dp(encoder);
@@ -4027,15 +4087,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	drm_dp_aux_unregister(&intel_dp->aux);
 	intel_dp_mst_encoder_cleanup(intel_dig_port);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+		mutex_lock(&dev_priv->pps_mutex);
 		edp_panel_vdd_off_sync(intel_dp);
-		drm_modeset_unlock(&dev->mode_config.connection_mutex);
+		mutex_unlock(&dev_priv->pps_mutex);
 		if (intel_dp->edp_notifier.notifier_call) {
 			unregister_reboot_notifier(&intel_dp->edp_notifier);
 			intel_dp->edp_notifier.notifier_call = NULL;
@@ -4047,11 +4108,15 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (!is_edp(intel_dp))
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
 	edp_panel_vdd_off_sync(intel_dp);
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 static void intel_dp_encoder_reset(struct drm_encoder *encoder)
@@ -4232,6 +4297,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 	u32 pp_on, pp_off, pp_div, pp;
 	int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (HAS_PCH_SPLIT(dev)) {
 		pp_ctrl_reg = PCH_PP_CONTROL;
 		pp_on_reg = PCH_PP_ON_DELAYS;
@@ -4333,6 +4400,8 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 	int pp_on_reg, pp_off_reg, pp_div_reg;
 	enum port port = dp_to_dig_port(intel_dp)->port;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (HAS_PCH_SPLIT(dev)) {
 		pp_on_reg = PCH_PP_ON_DELAYS;
 		pp_off_reg = PCH_PP_OFF_DELAYS;
@@ -4525,9 +4594,11 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	intel_dp = enc_to_intel_dp(&intel_encoder->base);
 	if (!edp_have_panel_vdd(intel_dp))
-		return;
+		goto out;
 	/*
 	 * The VDD bit needs a power domain reference, so if the bit is
 	 * already enabled when we boot or resume, grab this reference and
@@ -4539,6 +4610,8 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 	intel_display_power_get(dev_priv, power_domain);
 
 	edp_panel_vdd_schedule_off(intel_dp);
+ out:
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
@@ -4580,7 +4653,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 
 	/* We now know it's not a ghost, init power sequence regs. */
+	mutex_lock(&dev_priv->pps_mutex);
 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
+	mutex_unlock(&dev_priv->pps_mutex);
 
 	mutex_lock(&dev->mode_config.mutex);
 	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
@@ -4712,8 +4787,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	}
 
 	if (is_edp(intel_dp)) {
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_timestamps(intel_dp);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_dp_aux_init(intel_dp, intel_connector);
@@ -4729,9 +4806,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		drm_dp_aux_unregister(&intel_dp->aux);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-			drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+			mutex_lock(&dev_priv->pps_mutex);
 			edp_panel_vdd_off_sync(intel_dp);
-			drm_modeset_unlock(&dev->mode_config.connection_mutex);
+			mutex_unlock(&dev_priv->pps_mutex);
 		}
 		drm_connector_unregister(connector);
 		drm_connector_cleanup(connector);
-- 
1.8.5.5

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

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

* [PATCH 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off
  2014-08-18 19:16 ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer ville.syrjala
@ 2014-08-19 17:45   ` ville.syrjala
  2014-08-22 14:21     ` [PATCH v2 " ville.syrjala
  2014-09-01 11:19   ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer Antti Koskipää
  2014-09-04 11:54   ` [PATCH v2 " ville.syrjala
  2 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-19 17:45 UTC (permalink / raw)
  To: intel-gfx

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

The power sequencer loses its state when the disp2d power well is down.
Clear the dev_priv->pps_pipe tracking so that the power sequencer state
gets reinitialized the next time it's needed.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
Might be this should be squashed with
'[PATCH] drm/i915: Track which port is using which pipe's power sequencer'
to avoid having a regression in between. But I left if as a separate patch
for clarity.

Also maybe it would be cleaner to track this pipe power seqeuencer<->port
relationship the other way around? So something like this:
 /* the current port for each power seqeuencer */
 enum port pps_ports[2];


 drivers/gpu/drm/i915/intel_dp.c  | 23 +++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 drivers/gpu/drm/i915/intel_pm.c  |  2 ++
 3 files changed, 26 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d6fe1a2..3389c89 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -389,6 +389,29 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 						      &power_seq);
 }
 
+void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_encoder *encoder;
+
+	if (WARN_ON(!IS_VALLEYVIEW(dev)))
+		return;
+
+	mutex_lock(&dev_priv->pps_mutex);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		struct intel_dp *intel_dp;
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		intel_dp = enc_to_intel_dp(&encoder->base);
+		intel_dp->pps_pipe = INVALID_PIPE;
+	}
+
+	mutex_unlock(&dev_priv->pps_mutex);
+}
+
 static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 849a447..32627ae 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -943,6 +943,7 @@ void intel_dp_mst_suspend(struct drm_device *dev);
 void intel_dp_mst_resume(struct drm_device *dev);
 int intel_dp_max_link_bw(struct intel_dp *intel_dp);
 void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
+void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
 /* intel_dp_mst.c */
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
 void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 39dd066..d5ffda9 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -6328,6 +6328,8 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	vlv_set_power_well(dev_priv, power_well, false);
+
+	vlv_power_sequencer_reset(dev_priv);
 }
 
 static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
-- 
1.8.5.5

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

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

* [PATCH 15/14] drm/i915: Add comments explaining the vdd on/off functions
  2014-08-19 13:37       ` Jani Nikula
@ 2014-08-19 17:47         ` ville.syrjala
  2014-09-03 11:52           ` Imre Deak
  2014-08-26  9:21         ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() Daniel Vetter
  1 sibling, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-19 17:47 UTC (permalink / raw)
  To: intel-gfx

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

Jani wanted some comments to explain why we call certain vdd on/off
functions in certain places.

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

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1067082..1233a10 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1315,6 +1315,7 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	return control;
 }
 
+/* should be paired with edp_panel_vdd_off() */
 static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1365,6 +1366,7 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 	return need_to_disable;
 }
 
+/* should be paired with intel_edp_panel_vdd_off() */
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv =
@@ -1447,6 +1449,7 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
 	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
 }
 
+/* should be paired with edp_panel_vdd_on() */
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
 	struct drm_i915_private *dev_priv =
@@ -1467,6 +1470,7 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 		edp_panel_vdd_schedule_off(intel_dp);
 }
 
+/* should be paired with intel_edp_panel_vdd_on() */
 static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
 	struct drm_i915_private *dev_priv =
@@ -4307,6 +4311,10 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+		/*
+		 * vdd might still be enabled do to the delayed vdd off.
+		 * Make sure vdd is actually turned off here.
+		 */
 		mutex_lock(&dev_priv->pps_mutex);
 		edp_panel_vdd_off_sync(intel_dp);
 		mutex_unlock(&dev_priv->pps_mutex);
@@ -4327,6 +4335,10 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 	if (!is_edp(intel_dp))
 		return;
 
+	/*
+	 * vdd might still be enabled do to the delayed vdd off.
+	 * Make sure vdd is actually turned off here.
+	 */
 	mutex_lock(&dev_priv->pps_mutex);
 	edp_panel_vdd_off_sync(intel_dp);
 	mutex_unlock(&dev_priv->pps_mutex);
@@ -5025,6 +5037,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		drm_dp_aux_unregister(&intel_dp->aux);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+			/*
+			 * vdd might still be enabled do to the delayed vdd off.
+			 * Make sure vdd is actually turned off here.
+			 */
 			mutex_lock(&dev_priv->pps_mutex);
 			edp_panel_vdd_off_sync(intel_dp);
 			mutex_unlock(&dev_priv->pps_mutex);
-- 
1.8.5.5

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

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

* [PATCH v2 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off
  2014-08-19 17:45   ` [PATCH 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off ville.syrjala
@ 2014-08-22 14:21     ` ville.syrjala
  2014-09-02 13:47       ` Imre Deak
  0 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-08-22 14:21 UTC (permalink / raw)
  To: intel-gfx

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

The power sequencer loses its state when the disp2d power well is down.
Clear the dev_priv->pps_pipe tracking so that the power sequencer state
gets reinitialized the next time it's needed.

v2: Fix the pps_mutex vs. power_domain mutex deadlock by taking power
    domain reference first

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
Imre noticed my previouys attempt was utter garbage. Let's try again. Again maybe
we want to squash with 10/14 or at least move the edp_pps_{lock,unlock}() introduction
there to avoid churn.

The alternative of trying to plumb all the power domain calls out from under
pps_mutex seemed a bit too nasty to me, so I opted for this approach instead.

 drivers/gpu/drm/i915/intel_dp.c  | 157 +++++++++++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_drv.h |   1 +
 drivers/gpu/drm/i915/intel_pm.c  |   2 +
 3 files changed, 106 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d6fe1a2..3468315 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -389,6 +389,67 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 						      &power_seq);
 }
 
+void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_encoder *encoder;
+
+	if (WARN_ON(!IS_VALLEYVIEW(dev)))
+		return;
+
+	/*
+	 * We can't grab pps_mutex here due to deadlock with power_domain
+	 * mutex when power_domain functions are called while holding pps_mutex.
+	 * That also means that in order to use pps_pipe the code needs to
+	 * hold both a power domain reference and pps_mutex, and the power domain
+	 * reference get/put must be done while _not_ holding pps_mutex.
+	 * edp_pps_{lock,unlock}() do these steps in the correct order, so one
+	 * should use them always.
+	 */
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		struct intel_dp *intel_dp;
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		intel_dp = enc_to_intel_dp(&encoder->base);
+		intel_dp->pps_pipe = INVALID_PIPE;
+	}
+}
+
+static void edp_pps_lock(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &intel_dig_port->base;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
+
+	/*
+	 * See vlv_power_sequencer_reset() why we need
+	 * a power domain reference here.
+	 */
+	power_domain = intel_display_port_power_domain(encoder);
+	intel_display_power_get(dev_priv, power_domain);
+
+	mutex_lock(&dev_priv->pps_mutex);
+}
+
+static void edp_pps_unlock(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &intel_dig_port->base;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
+
+	mutex_unlock(&dev_priv->pps_mutex);
+
+	power_domain = intel_display_port_power_domain(encoder);
+	intel_display_power_put(dev_priv, power_domain);
+}
+
 static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -425,7 +486,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
 		return 0;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 
 	pipe = vlv_power_sequencer_pipe(intel_dp);
 
@@ -439,7 +500,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
 	msleep(intel_dp->panel_power_cycle_delay);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 
 	return 0;
 }
@@ -458,17 +519,13 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct intel_encoder *intel_encoder = &intel_dig_port->base;
-	enum intel_display_power_domain power_domain;
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	power_domain = intel_display_port_power_domain(intel_encoder);
-	return intel_display_power_enabled(dev_priv, power_domain) &&
-	       (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
+	return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
 }
 
+
 static void
 intel_dp_check_edp(struct intel_dp *intel_dp)
 {
@@ -614,7 +671,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
 	bool vdd;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 
 	/*
 	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
@@ -731,7 +788,7 @@ out:
 	if (vdd)
 		edp_panel_vdd_off(intel_dp, false);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 
 	return ret;
 }
@@ -1312,16 +1369,14 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
-	struct drm_i915_private *dev_priv =
-		intel_dp_to_dev(intel_dp)->dev_private;
 	bool vdd;
 
 	if (!is_edp(intel_dp))
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 	vdd = edp_panel_vdd_on(intel_dp);
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 
 	WARN(!vdd, "eDP VDD already requested on\n");
 }
@@ -1370,13 +1425,11 @@ static void edp_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
 						 struct intel_dp, panel_vdd_work);
-	struct drm_i915_private *dev_priv =
-		intel_dp_to_dev(intel_dp)->dev_private;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 	if (!intel_dp->want_panel_vdd)
 		edp_panel_vdd_off_sync(intel_dp);
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 }
 
 static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
@@ -1414,15 +1467,12 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
 static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
-	struct drm_i915_private *dev_priv =
-		intel_dp_to_dev(intel_dp)->dev_private;
-
 	if (!is_edp(intel_dp))
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 	edp_panel_vdd_off(intel_dp, sync);
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 }
 
 void intel_edp_panel_on(struct intel_dp *intel_dp)
@@ -1437,7 +1487,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power on\n");
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 
 	if (edp_have_panel_power(intel_dp)) {
 		DRM_DEBUG_KMS("eDP power already on\n");
@@ -1472,7 +1522,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 	}
 
  out:
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 }
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
@@ -1490,7 +1540,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 
 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
 
@@ -1514,7 +1564,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	intel_display_power_put(dev_priv, power_domain);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 }
 
 void intel_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1540,7 +1590,7 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
 	 */
 	wait_backlight_on(intel_dp);
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 
 	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_BLC_ENABLE;
@@ -1550,7 +1600,7 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 }
 
 void intel_edp_backlight_off(struct intel_dp *intel_dp)
@@ -1563,7 +1613,7 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
 	if (!is_edp(intel_dp))
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 
 	DRM_DEBUG_KMS("\n");
 	pp = ironlake_get_pp_control(intel_dp);
@@ -1574,7 +1624,7 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 
 	intel_dp->last_backlight_off = jiffies;
 	edp_wait_backlight_off(intel_dp);
@@ -2290,18 +2340,19 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		struct intel_dp *intel_dp;
+		enum port port;
 
 		if (encoder->type != INTEL_OUTPUT_EDP)
 			continue;
 
 		intel_dp = enc_to_intel_dp(&encoder->base);
+		port = dp_to_dig_port(intel_dp)->port;
 
 		if (intel_dp->pps_pipe != pipe)
 			continue;
 
 		DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
-			      pipe_name(pipe),
-			      port_name(dp_to_dig_port(intel_dp)->port));
+			      pipe_name(pipe), port_name(port));
 
 		/* make sure vdd is off before we steal it */
 		edp_panel_vdd_off_sync(intel_dp);
@@ -2377,9 +2428,9 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		mutex_lock(&dev_priv->pps_mutex);
+		edp_pps_lock(intel_dp);
 		vlv_init_panel_power_sequencer(intel_dp);
-		mutex_unlock(&dev_priv->pps_mutex);
+		edp_pps_unlock(intel_dp);
 	}
 
 	intel_enable_dp(encoder);
@@ -2477,9 +2528,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		mutex_lock(&dev_priv->pps_mutex);
+		edp_pps_lock(intel_dp);
 		vlv_init_panel_power_sequencer(intel_dp);
-		mutex_unlock(&dev_priv->pps_mutex);
+		edp_pps_unlock(intel_dp);
 	}
 
 	intel_enable_dp(encoder);
@@ -4219,17 +4270,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	drm_dp_aux_unregister(&intel_dp->aux);
 	intel_dp_mst_encoder_cleanup(intel_dig_port);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-		mutex_lock(&dev_priv->pps_mutex);
+		edp_pps_lock(intel_dp);
 		edp_panel_vdd_off_sync(intel_dp);
-		mutex_unlock(&dev_priv->pps_mutex);
+		edp_pps_unlock(intel_dp);
+
 		if (intel_dp->edp_notifier.notifier_call) {
 			unregister_reboot_notifier(&intel_dp->edp_notifier);
 			intel_dp->edp_notifier.notifier_call = NULL;
@@ -4241,15 +4291,13 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (!is_edp(intel_dp))
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 	edp_panel_vdd_off_sync(intel_dp);
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 }
 
 static void intel_dp_encoder_reset(struct drm_encoder *encoder)
@@ -4727,9 +4775,10 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
-
 	intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+	edp_pps_lock(intel_dp);
+
 	if (!edp_have_panel_vdd(intel_dp))
 		goto out;
 	/*
@@ -4744,7 +4793,7 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 
 	edp_panel_vdd_schedule_off(intel_dp);
  out:
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 }
 
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
@@ -4786,9 +4835,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 
 	/* We now know it's not a ghost, init power sequence regs. */
-	mutex_lock(&dev_priv->pps_mutex);
+	edp_pps_lock(intel_dp);
 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
-	mutex_unlock(&dev_priv->pps_mutex);
+	edp_pps_unlock(intel_dp);
 
 	mutex_lock(&dev->mode_config.mutex);
 	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
@@ -4922,14 +4971,14 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	}
 
 	if (is_edp(intel_dp)) {
-		mutex_lock(&dev_priv->pps_mutex);
+		edp_pps_lock(intel_dp);
 		if (IS_VALLEYVIEW(dev)) {
 			vlv_initial_power_sequencer_setup(intel_dp);
 		} else {
 			intel_dp_init_panel_power_timestamps(intel_dp);
 			intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 		}
-		mutex_unlock(&dev_priv->pps_mutex);
+		edp_pps_unlock(intel_dp);
 	}
 
 	intel_dp_aux_init(intel_dp, intel_connector);
@@ -4945,9 +4994,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		drm_dp_aux_unregister(&intel_dp->aux);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-			mutex_lock(&dev_priv->pps_mutex);
+			edp_pps_lock(intel_dp);
 			edp_panel_vdd_off_sync(intel_dp);
-			mutex_unlock(&dev_priv->pps_mutex);
+			edp_pps_unlock(intel_dp);
 		}
 		drm_connector_unregister(connector);
 		drm_connector_cleanup(connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 849a447..32627ae 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -943,6 +943,7 @@ void intel_dp_mst_suspend(struct drm_device *dev);
 void intel_dp_mst_resume(struct drm_device *dev);
 int intel_dp_max_link_bw(struct intel_dp *intel_dp);
 void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
+void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
 /* intel_dp_mst.c */
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
 void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 39dd066..d5ffda9 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -6328,6 +6328,8 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	vlv_set_power_well(dev_priv, power_well, false);
+
+	vlv_power_sequencer_reset(dev_priv);
 }
 
 static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
-- 
1.8.5.5

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

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

* Re: [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
  2014-08-19 13:37       ` Jani Nikula
  2014-08-19 17:47         ` [PATCH 15/14] drm/i915: Add comments explaining the vdd on/off functions ville.syrjala
@ 2014-08-26  9:21         ` Daniel Vetter
  1 sibling, 0 replies; 63+ messages in thread
From: Daniel Vetter @ 2014-08-26  9:21 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 04:37:03PM +0300, Jani Nikula wrote:
> On Tue, 19 Aug 2014, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > On Tue, Aug 19, 2014 at 10:36:52AM +0300, Jani Nikula wrote:
> >> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >
> >> > If we force vdd off warn if someone is still using it. With this
> >> > change the delayed vdd off work needs to check want_panel_vdd
> >> > itself to make sure it doesn't try to turn vdd off when someone
> >> > is using it.
> >> 
> >> I think this calls for a prep cleanup patch to check and fix the uses of
> >> edp_panel_vdd_off(intel_dp, true)
> >> vs. edp_panel_vdd_off_sync(intel_dp). In particular, why are there
> >> direct calls to the latter all over the place? Seems wrong.
> >
> > edp_panel_vdd_off() should always be paired with a edp_panel_vdd_on().
> > If we were to call edp_panel_vdd_off() without the correct pairing we
> > would get a warning due to want_panel_vdd==false, whereas
> > edp_panel_vdd_off_sync() will now warn when want_panel_vdd==true.
> > The direct calls to edp_panel_vdd_off_sync() are in places where we
> > should not have want_panel_vdd==true (eg. system suspend) but we
> > just want to force vdd off even if the delayed off work has alrady
> > been scheduled.
> 
> Okay, care to add some of that as brief documentation comments for the
> functions in question, as follow-up? IMO detailed kernel-docs here won't
> be read by anyone and will just get stale.

Hm, imo a wrappe for vdd_off_sync or would be clearer than piles of
comments. Or maybe just vdd_sync, akin to all the work/time _sync
functions. Our system suspend/resume code is splattered with such
functions, so the code pattern should be clear with just that.

Perhaps as a follow-up patch on top of all of this?
-Daniel

> 
> BR,
> Jani.
> 
> >
> >> 
> >> BR,
> >> Jani.
> >> 
> >> 
> >> >
> >> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> > ---
> >> >  drivers/gpu/drm/i915/intel_dp.c | 7 +++++--
> >> >  1 file changed, 5 insertions(+), 2 deletions(-)
> >> >
> >> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> >> > index e6b4d4d..0fb510c 100644
> >> > --- a/drivers/gpu/drm/i915/intel_dp.c
> >> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> >> > @@ -1241,7 +1241,9 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> >> >  
> >> >  	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> >> >  
> >> > -	if (intel_dp->want_panel_vdd || !edp_have_panel_vdd(intel_dp))
> >> > +	WARN_ON(intel_dp->want_panel_vdd);
> >> > +
> >> > +	if (!edp_have_panel_vdd(intel_dp))
> >> >  		return;
> >> >  
> >> >  	DRM_DEBUG_KMS("Turning eDP VDD off\n");
> >> > @@ -1273,7 +1275,8 @@ static void edp_panel_vdd_work(struct work_struct *__work)
> >> >  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> >> >  
> >> >  	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> >> > -	edp_panel_vdd_off_sync(intel_dp);
> >> > +	if (!intel_dp->want_panel_vdd)
> >> > +		edp_panel_vdd_off_sync(intel_dp);
> >> >  	drm_modeset_unlock(&dev->mode_config.connection_mutex);
> >> >  }
> >> >  
> >> > -- 
> >> > 1.8.5.5
> >> >
> >> > _______________________________________________
> >> > Intel-gfx mailing list
> >> > Intel-gfx@lists.freedesktop.org
> >> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> >> 
> >> -- 
> >> Jani Nikula, Intel Open Source Technology Center
> >
> > -- 
> > Ville Syrjälä
> > Intel OTC
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick
  2014-08-19 10:46   ` Ville Syrjälä
@ 2014-08-26  9:35     ` Daniel Vetter
  0 siblings, 0 replies; 63+ messages in thread
From: Daniel Vetter @ 2014-08-26  9:35 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 01:46:58PM +0300, Ville Syrjälä wrote:
> On Tue, Aug 19, 2014 at 11:08:33AM +0300, Jani Nikula wrote:
> > On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > > While wrestling with the VLV/CHV panel power sequencer I noticed the locking
> > > in our edp vdd code was rather broken. This series aims to fix that by
> > > introducing a power seqeuencer mutex. I was already thinking about using the
> > > aux.hw_mutex for this since it's already locked around the aux ->transfer()
> > > function, but the VLV/CHV multiple power sequencer issue requires a single
> > > lock instead of per-port.
> > 
> > For extra kicks, see i915_save_display() and i915_restore_display(). Why
> > are we doing this to ourselves?
> 
> Yeah, crap all around. I suppose someone needs to frob the lvds code
> a bit before we can kill the power sequencer stuff from those two
> functions.

I think with Jani's reworked backlight code we can ditch most of them for
kms. For the panel power sequencer I guess we just need to hook up a
->reset function to lvds/edp.

That would also have the benefit of us being able to ditch the lvds
restore crap.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick
  2014-08-19  7:45 ` [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick Jani Nikula
@ 2014-08-26  9:37   ` Daniel Vetter
  0 siblings, 0 replies; 63+ messages in thread
From: Daniel Vetter @ 2014-08-26  9:37 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 10:45:20AM +0300, Jani Nikula wrote:
> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > While wrestling with the VLV/CHV panel power sequencer I noticed the locking
> > in our edp vdd code was rather broken. This series aims to fix that by
> > introducing a power seqeuencer mutex. I was already thinking about using the
> > aux.hw_mutex for this since it's already locked around the aux ->transfer()
> > function, but the VLV/CHV multiple power sequencer issue requires a single
> > lock instead of per-port.
> >
> > At the end of the series there's a bit of reordering of the DP port
> > enable/disable sequences to make subsequent power sequencer kick patches
> > easier. The last patch fixes the wait_pipe_off() timeouts on my ILK.
> > Strictly speaking it shouldn't be part of this series, but I couldn't
> > really test this on my ILK without suffering tons of warnings so I
> > included it here anyway.
> 
> This is what I'd like to happen here:
> 
> 1) Patches [1] from me and [2] from Clinton get reviewed and merged
> first, through -fixes.
> 
> 2) The rest of the patches in my series after [1] get reviewed and
> merged, through dinq.
> 
> 3) The first part of this series, up to the locking bits, mostly
> reviewed now, get refreshed on top the above, should not conflict much,
> and we can start merging them while...

I've just merged them all to dinq. I guess you could simply cherry-pick
the -fixes material to, that's imo saner than backmerges here. I think.
-Daniel

> 
> 4) The second part of this series, from about the locking on, get
> reviewed and merged.
> 
> I want this order to make backporting steps 1 and 2 as painless as
> possible. Please help review them, and I'll follow through with this
> series.
> 
> BR,
> Jani.
> 
> 
> 
> [1] http://mid.gmane.org/e7a47b50ed0f25cafdc26711fc09561ea8af3b81.1407849872.git.jani.nikula@intel.com
> [2] http://mid.gmane.org/1408394915-21882-1-git-send-email-clinton.a.taylor@intel.com
> 
> 
> 
> >
> > Ville Syrjälä (14):
> >   drm/i915: Parametrize PANEL_PORT_SELECT_VLV
> >   drm/i915: Reorganize vlv eDP reboot notifier
> >   drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst()
> >   drm/i915: Rename edp vdd funcs for consistency
> >   drm/i915: Add a note explaining vdd on/off handling in
> >     intel_dp_aux_ch()
> >   drm/i915: Replace big nested if block with early return
> >   drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync()
> >   drm/i915: Flatten intel_edp_panel_vdd_on()
> >   drm/i915: Fix edp vdd locking
> >   drm/i915: Track which port is using which pipe's power sequencer
> >   drm/i915: Be more careful when picking the initial power sequencer
> >     pipe
> >   drm/i915: Turn on panel power before doing aux transfers
> >   drm/i915: Enable DP port earlier
> >   drm/i915: Move DP port disable to post_disable for pch platforms
> >
> >  drivers/gpu/drm/i915/i915_drv.h      |   3 +
> >  drivers/gpu/drm/i915/i915_reg.h      |   3 +-
> >  drivers/gpu/drm/i915/intel_display.c |   2 +
> >  drivers/gpu/drm/i915/intel_dp.c      | 619 +++++++++++++++++++++++++----------
> >  drivers/gpu/drm/i915/intel_drv.h     |   6 +
> >  5 files changed, 463 insertions(+), 170 deletions(-)
> >
> > -- 
> > 1.8.5.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms
  2014-08-18 19:16 ` [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms ville.syrjala
@ 2014-08-26  9:43   ` Daniel Vetter
  2014-09-03 11:20   ` Imre Deak
  1 sibling, 0 replies; 63+ messages in thread
From: Daniel Vetter @ 2014-08-26  9:43 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Mon, Aug 18, 2014 at 10:16:09PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We need to turn the DP port off after the pipe, otherwise the pipe won't
> turn off properly on certain pch platforms at least (happens on my ILK for
> example).  This also matches the BSpec modeset sequence better. We still
> don't match the spec exactly though (eg. audio disable should happen
> much earlier), but at last this eliminates the nasty
> wait_for_pipe_off() timeouts.
> 
> We already did the port disable after the pipe for VLV/CHV and for CPU
> eDP.
> 
> For g4x leave the port disable where it is since that matches the
> modeset sequence in the documentation and I don't have a suitable
> machine to test if the other order would work.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

We have a pile of bug reports on this topic:

https://bugs.freedesktop.org/show_bug.cgi?id=67462
https://bugs.freedesktop.org/show_bug.cgi?id=54687
https://bugzilla.kernel.org/show_bug.cgi?id=52061
https://bugzilla.kernel.org/show_bug.cgi?id=52061

Can you please run them by these reports and collect tested-bys? If it
checks out it's imo good to go.
-Daniel

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 16 +++++++---------
>  1 file changed, 7 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 12925be..915d4ec 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2194,7 +2194,6 @@ void intel_edp_psr_init(struct drm_device *dev)
>  static void intel_disable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> -	enum port port = dp_to_dig_port(intel_dp)->port;
>  	struct drm_device *dev = encoder->base.dev;
>  
>  	/* Make sure the panel is off before trying to change the mode. But also
> @@ -2204,21 +2203,19 @@ static void intel_disable_dp(struct intel_encoder *encoder)
>  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
>  	intel_edp_panel_off(intel_dp);
>  
> -	/* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */
> -	if (!(port == PORT_A || IS_VALLEYVIEW(dev)))
> +	/* disable the port before the pipe on g4x */
> +	if (INTEL_INFO(dev)->gen < 5)
>  		intel_dp_link_down(intel_dp);
>  }
>  
> -static void g4x_post_disable_dp(struct intel_encoder *encoder)
> +static void ilk_post_disable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>  	enum port port = dp_to_dig_port(intel_dp)->port;
>  
> -	if (port != PORT_A)
> -		return;
> -
>  	intel_dp_link_down(intel_dp);
> -	ironlake_edp_pll_off(intel_dp);
> +	if (port == PORT_A)
> +		ironlake_edp_pll_off(intel_dp);
>  }
>  
>  static void vlv_post_disable_dp(struct intel_encoder *encoder)
> @@ -5044,7 +5041,8 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
>  	} else {
>  		intel_encoder->pre_enable = g4x_pre_enable_dp;
>  		intel_encoder->enable = g4x_enable_dp;
> -		intel_encoder->post_disable = g4x_post_disable_dp;
> +		if (INTEL_INFO(dev)->gen >= 5)
> +			intel_encoder->post_disable = ilk_post_disable_dp;
>  	}
>  
>  	intel_dig_port->port = port;
> -- 
> 1.8.5.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers
  2014-08-19 10:57     ` Ville Syrjälä
@ 2014-08-26 12:41       ` Daniel Vetter
  0 siblings, 0 replies; 63+ messages in thread
From: Daniel Vetter @ 2014-08-26 12:41 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 01:57:57PM +0300, Ville Syrjälä wrote:
> On Tue, Aug 19, 2014 at 10:33:15AM +0300, Jani Nikula wrote:
> > On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >
> > > On VLV/CHV the panel power sequencer may need to be "kicked" a bit to
> > > lock onto the new port, and that needs to happen before any aux
> > > transfers are attempted if we want the aux transfers to actaully
> > > succeed. So turn on panel power (part of the "kick") before aux
> > > transfers (DPMS_ON + link training).
> > >
> > > This also matches the documented modeset sequence better for pch
> > > platforms. The documentation doesn't explicitly state anything about the
> > > DPMS or link training DPCD writes, but the panel power on step is
> > > always listed before link training is mentioned.
> > >
> > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > ---
> > >  drivers/gpu/drm/i915/intel_dp.c | 4 ++--
> > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > > index 4952783..28bc652 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > > @@ -2275,10 +2275,10 @@ static void intel_enable_dp(struct intel_encoder *encoder)
> > >  		return;
> > >  
> > >  	intel_edp_panel_vdd_on(intel_dp);
> > > -	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> > > -	intel_dp_start_link_train(intel_dp);
> > >  	intel_edp_panel_on(intel_dp);
> > >  	intel_edp_panel_vdd_off(intel_dp, true);
> > > +	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> > > +	intel_dp_start_link_train(intel_dp);
> > 
> > Please dig into the git history in this area. I fear this may
> > regress. We've juggled this too many times...
> 
> I did. But I couldn't spot much solid analysis of the problems in the
> earlier patches/reverts. It's mostly been guesswork AFAICS. Most of it
> seems to be back and forth with the force vdd on/off vs. panel power on,
> but this patch doesn't change that order.
> 
> Also:
> a) we need this patch on VLV/CHV at the very least
> b) this agrees with the bspec modeset sequence for pch platforms better
> c) my ILK with CPU eDP seems happy with the new order

There have been bug reports about ivb/snb cpu edp panels not lighting up
iirc. Especially when the bios didn't light up the panel already (e.g.
when an external screen is plugged in). Might be worth a try to haggle
this patch to those bugs. But I seem to have a hard time finding them
right now :(
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-19  7:00   ` Jani Nikula
@ 2014-08-26 12:58     ` Ville Syrjälä
  2014-08-26 13:21       ` Jani Nikula
  0 siblings, 1 reply; 63+ messages in thread
From: Ville Syrjälä @ 2014-08-26 12:58 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 19, 2014 at 10:00:55AM +0300, Jani Nikula wrote:
> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
> > and flatten the rest of the function.
> 
> Please imagine adding another platform there, and realize this just adds
> unnecessary churn.

I'd just add another reboot notifier then. Frankly I don't understand
the current one either. Why does it need to set the delay to max for
instance? And does this mean that the PANEL_POWER_RESET bit doesn't
actually work as advertised in the docs?

> 
> BR,
> Jani.
> 
> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_dp.c | 24 ++++++++++++------------
> >  1 file changed, 12 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> > index 43dd226..a9ed2a6 100644
> > --- a/drivers/gpu/drm/i915/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/intel_dp.c
> > @@ -347,22 +347,22 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	u32 pp_div;
> >  	u32 pp_ctrl_reg, pp_div_reg;
> > -	enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
> > +	enum pipe pipe;
> >  
> > -	if (!is_edp(intel_dp) || code != SYS_RESTART)
> > +	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
> >  		return 0;
> >  
> > -	if (IS_VALLEYVIEW(dev)) {
> > -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> > -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> > -		pp_div = I915_READ(pp_div_reg);
> > -		pp_div &= PP_REFERENCE_DIVIDER_MASK;
> > +	pipe = vlv_power_sequencer_pipe(intel_dp);
> >  
> > -		/* 0x1F write to PP_DIV_REG sets max cycle delay */
> > -		I915_WRITE(pp_div_reg, pp_div | 0x1F);
> > -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> > -		msleep(intel_dp->panel_power_cycle_delay);
> > -	}
> > +	pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> > +	pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
> > +	pp_div = I915_READ(pp_div_reg);
> > +	pp_div &= PP_REFERENCE_DIVIDER_MASK;
> > +
> > +	/* 0x1F write to PP_DIV_REG sets max cycle delay */
> > +	I915_WRITE(pp_div_reg, pp_div | 0x1F);
> > +	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
> > +	msleep(intel_dp->panel_power_cycle_delay);
> >  
> >  	return 0;
> >  }
> > -- 
> > 1.8.5.5
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> -- 
> Jani Nikula, Intel Open Source Technology Center

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-26 12:58     ` Ville Syrjälä
@ 2014-08-26 13:21       ` Jani Nikula
  2014-08-26 13:30         ` Ville Syrjälä
  2014-08-26 13:36         ` Daniel Vetter
  0 siblings, 2 replies; 63+ messages in thread
From: Jani Nikula @ 2014-08-26 13:21 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Tue, 26 Aug 2014, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> On Tue, Aug 19, 2014 at 10:00:55AM +0300, Jani Nikula wrote:
>> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
>> > and flatten the rest of the function.
>> 
>> Please imagine adding another platform there, and realize this just adds
>> unnecessary churn.
>
> I'd just add another reboot notifier then.

Fair enough; it should be vlv_edp_notify_handler then. (No, don't send a
patch to change that! ;)

> Frankly I don't understand the current one either. Why does it need to
> set the delay to max for instance? And does this mean that the
> PANEL_POWER_RESET bit doesn't actually work as advertised in the docs?

*shrug* experimental evidence?

commit 01527b3127997ef6370d5ad4fa25d96847fbf12a
Author: Clint Taylor <clinton.a.taylor@intel.com>
Date:   Mon Jul 7 13:01:46 2014 -0700

    drm/i915/vlv: T12 eDP panel timing enforcement during reboot
    
    The panel power sequencer on vlv doesn't appear to accept changes to its
    T12 power down duration during warm reboots. This change forces a delay
    for warm reboots to the T12 panel timing as defined in the VBT table for
    the connected panel.


>
>> 
>> BR,
>> Jani.
>> 
>> 
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/intel_dp.c | 24 ++++++++++++------------
>> >  1 file changed, 12 insertions(+), 12 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
>> > index 43dd226..a9ed2a6 100644
>> > --- a/drivers/gpu/drm/i915/intel_dp.c
>> > +++ b/drivers/gpu/drm/i915/intel_dp.c
>> > @@ -347,22 +347,22 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>> >  	struct drm_i915_private *dev_priv = dev->dev_private;
>> >  	u32 pp_div;
>> >  	u32 pp_ctrl_reg, pp_div_reg;
>> > -	enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
>> > +	enum pipe pipe;
>> >  
>> > -	if (!is_edp(intel_dp) || code != SYS_RESTART)
>> > +	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
>> >  		return 0;
>> >  
>> > -	if (IS_VALLEYVIEW(dev)) {
>> > -		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
>> > -		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
>> > -		pp_div = I915_READ(pp_div_reg);
>> > -		pp_div &= PP_REFERENCE_DIVIDER_MASK;
>> > +	pipe = vlv_power_sequencer_pipe(intel_dp);
>> >  
>> > -		/* 0x1F write to PP_DIV_REG sets max cycle delay */
>> > -		I915_WRITE(pp_div_reg, pp_div | 0x1F);
>> > -		I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
>> > -		msleep(intel_dp->panel_power_cycle_delay);
>> > -	}
>> > +	pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
>> > +	pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
>> > +	pp_div = I915_READ(pp_div_reg);
>> > +	pp_div &= PP_REFERENCE_DIVIDER_MASK;
>> > +
>> > +	/* 0x1F write to PP_DIV_REG sets max cycle delay */
>> > +	I915_WRITE(pp_div_reg, pp_div | 0x1F);
>> > +	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
>> > +	msleep(intel_dp->panel_power_cycle_delay);
>> >  
>> >  	return 0;
>> >  }
>> > -- 
>> > 1.8.5.5
>> >
>> > _______________________________________________
>> > Intel-gfx mailing list
>> > Intel-gfx@lists.freedesktop.org
>> > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>> 
>> -- 
>> Jani Nikula, Intel Open Source Technology Center
>
> -- 
> Ville Syrjälä
> Intel OTC

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

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-26 13:21       ` Jani Nikula
@ 2014-08-26 13:30         ` Ville Syrjälä
  2014-08-26 13:36         ` Daniel Vetter
  1 sibling, 0 replies; 63+ messages in thread
From: Ville Syrjälä @ 2014-08-26 13:30 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 26, 2014 at 04:21:00PM +0300, Jani Nikula wrote:
> On Tue, 26 Aug 2014, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > On Tue, Aug 19, 2014 at 10:00:55AM +0300, Jani Nikula wrote:
> >> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >
> >> > Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
> >> > and flatten the rest of the function.
> >> 
> >> Please imagine adding another platform there, and realize this just adds
> >> unnecessary churn.
> >
> > I'd just add another reboot notifier then.
> 
> Fair enough; it should be vlv_edp_notify_handler then. (No, don't send a
> patch to change that! ;)
> 
> > Frankly I don't understand the current one either. Why does it need to
> > set the delay to max for instance? And does this mean that the
> > PANEL_POWER_RESET bit doesn't actually work as advertised in the docs?
> 
> *shrug* experimental evidence?
> 
> commit 01527b3127997ef6370d5ad4fa25d96847fbf12a
> Author: Clint Taylor <clinton.a.taylor@intel.com>
> Date:   Mon Jul 7 13:01:46 2014 -0700
> 
>     drm/i915/vlv: T12 eDP panel timing enforcement during reboot
>     
>     The panel power sequencer on vlv doesn't appear to accept changes to its
>     T12 power down duration during warm reboots. This change forces a delay
>     for warm reboots to the T12 panel timing as defined in the VBT table for
>     the connected panel.

That explanation doesn't really make it any more clear to me. But if the
reboot notifier helps someone somehow I can live with it.

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-26 13:21       ` Jani Nikula
  2014-08-26 13:30         ` Ville Syrjälä
@ 2014-08-26 13:36         ` Daniel Vetter
  2014-08-26 14:06           ` Ville Syrjälä
  1 sibling, 1 reply; 63+ messages in thread
From: Daniel Vetter @ 2014-08-26 13:36 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Tue, Aug 26, 2014 at 04:21:00PM +0300, Jani Nikula wrote:
> On Tue, 26 Aug 2014, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > On Tue, Aug 19, 2014 at 10:00:55AM +0300, Jani Nikula wrote:
> >> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >
> >> > Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
> >> > and flatten the rest of the function.
> >> 
> >> Please imagine adding another platform there, and realize this just adds
> >> unnecessary churn.
> >
> > I'd just add another reboot notifier then.
> 
> Fair enough; it should be vlv_edp_notify_handler then. (No, don't send a
> patch to change that! ;)
> 
> > Frankly I don't understand the current one either. Why does it need to
> > set the delay to max for instance? And does this mean that the
> > PANEL_POWER_RESET bit doesn't actually work as advertised in the docs?
> 
> *shrug* experimental evidence?
> 
> commit 01527b3127997ef6370d5ad4fa25d96847fbf12a
> Author: Clint Taylor <clinton.a.taylor@intel.com>
> Date:   Mon Jul 7 13:01:46 2014 -0700
> 
>     drm/i915/vlv: T12 eDP panel timing enforcement during reboot
>     
>     The panel power sequencer on vlv doesn't appear to accept changes to its
>     T12 power down duration during warm reboots. This change forces a delay
>     for warm reboots to the T12 panel timing as defined in the VBT table for
>     the connected panel.

So if I remember this piece of lore correctly in the past the pp was
pessimistic, and enforced this delay on resume/boot-up, assuming you've
shut down _right_ before the machine was lit up again. Apparently people
where unhappy with that enforced delay and it was ditched on vlv, but then
it broke panels if you actually managed to reboot quickly enough.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-26 13:36         ` Daniel Vetter
@ 2014-08-26 14:06           ` Ville Syrjälä
  2014-09-04 17:47             ` Clint Taylor
  0 siblings, 1 reply; 63+ messages in thread
From: Ville Syrjälä @ 2014-08-26 14:06 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: intel-gfx

On Tue, Aug 26, 2014 at 03:36:07PM +0200, Daniel Vetter wrote:
> On Tue, Aug 26, 2014 at 04:21:00PM +0300, Jani Nikula wrote:
> > On Tue, 26 Aug 2014, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > > On Tue, Aug 19, 2014 at 10:00:55AM +0300, Jani Nikula wrote:
> > >> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> > >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > >> >
> > >> > Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
> > >> > and flatten the rest of the function.
> > >> 
> > >> Please imagine adding another platform there, and realize this just adds
> > >> unnecessary churn.
> > >
> > > I'd just add another reboot notifier then.
> > 
> > Fair enough; it should be vlv_edp_notify_handler then. (No, don't send a
> > patch to change that! ;)
> > 
> > > Frankly I don't understand the current one either. Why does it need to
> > > set the delay to max for instance? And does this mean that the
> > > PANEL_POWER_RESET bit doesn't actually work as advertised in the docs?
> > 
> > *shrug* experimental evidence?
> > 
> > commit 01527b3127997ef6370d5ad4fa25d96847fbf12a
> > Author: Clint Taylor <clinton.a.taylor@intel.com>
> > Date:   Mon Jul 7 13:01:46 2014 -0700
> > 
> >     drm/i915/vlv: T12 eDP panel timing enforcement during reboot
> >     
> >     The panel power sequencer on vlv doesn't appear to accept changes to its
> >     T12 power down duration during warm reboots. This change forces a delay
> >     for warm reboots to the T12 panel timing as defined in the VBT table for
> >     the connected panel.
> 
> So if I remember this piece of lore correctly in the past the pp was
> pessimistic, and enforced this delay on resume/boot-up, assuming you've
> shut down _right_ before the machine was lit up again. Apparently people
> where unhappy with that enforced delay and it was ditched on vlv, but then
> it broke panels if you actually managed to reboot quickly enough.

IIRC the way the reset bit is documented the hardware itself is supposed
to initiate the power off cycle when it gets some reset notification and
it should enforce the timing before allowing the panel power to be
re-enabled. Although it does seem that it would also reset the
"power cycle delay" so it would maybe only enforce some default delay in
that case (300ms based on the documented default value of 0x4). So if the
panel requires more than the 300ms then I understand the msleep() here.
I guess use of the VDD force bit just after reset might also require that
we do the power down + wait before reset. So that part does make sense
to me, but I still don't understand the "power cycle delay"=0x1f part.

-- 
Ville Syrjälä
Intel OTC

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

* Re: [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer
  2014-08-18 19:16 ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer ville.syrjala
  2014-08-19 17:45   ` [PATCH 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off ville.syrjala
@ 2014-09-01 11:19   ` Antti Koskipää
  2014-09-04 11:54   ` [PATCH v2 " ville.syrjala
  2 siblings, 0 replies; 63+ messages in thread
From: Antti Koskipää @ 2014-09-01 11:19 UTC (permalink / raw)
  To: intel-gfx

Reviewed-by: Antti Koskipaa <antti.koskipaa@linux.intel.com>

-- 
- Antti

On 08/18/2014 10:16 PM, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> VLV/CHV have a per-pipe panel power sequencer which locks onto the
> port once used. We need to keep track wich power sequencers are
> locked to which ports.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c  | 185 ++++++++++++++++++++++++++++++++++-----
>  drivers/gpu/drm/i915/intel_drv.h |   6 ++
>  2 files changed, 168 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 556e4de..4614e6e 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -294,28 +294,99 @@ static enum pipe
>  vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  {
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	enum port port = intel_dig_port->port;
> -	enum pipe pipe;
> +	struct intel_encoder *encoder;
> +	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
> +	struct edp_power_seq power_seq;
>  
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
> -	/* modeset should have pipe */
> -	if (crtc)
> -		return to_intel_crtc(crtc)->pipe;
> +	if (intel_dp->pps_pipe != INVALID_PIPE)
> +		return intel_dp->pps_pipe;
> +
> +	/*
> +	 * We don't have power sequencer currently.
> +	 * Pick one that's not used by other ports.
> +	 */
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
> +		struct intel_dp *tmp;
> +
> +		if (encoder->type != INTEL_OUTPUT_EDP)
> +			continue;
> +
> +		tmp = enc_to_intel_dp(&encoder->base);
> +
> +		if (tmp->pps_pipe != INVALID_PIPE)
> +			pipes &= ~(1 << tmp->pps_pipe);
> +	}
> +
> +	/*
> +	 * Didn't find one. This should not happen since there
> +	 * are two power sequencers and up to two eDP ports.
> +	 */
> +	if (WARN_ON(pipes == 0))
> +		return PIPE_A;
> +
> +	intel_dp->pps_pipe = ffs(pipes) - 1;
> +
> +	DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n",
> +		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
> +
> +	/* init power sequencer on this pipe and port */
> +	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> +	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
> +						      &power_seq);
> +
> +	return intel_dp->pps_pipe;
> +}
> +
> +static enum pipe
> +vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
> +				 enum port port)
> +{
> +	enum pipe pipe;
>  
> -	/* init time, try to find a pipe with this port selected */
>  	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
>  		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
>  			PANEL_PORT_SELECT_MASK;
> -		if (port_sel == PANEL_PORT_SELECT_VLV(port))
> -			return pipe;
> +
> +		if (port_sel != PANEL_PORT_SELECT_VLV(port))
> +			continue;
> +
> +		return pipe;
> +	}
> +
> +	return INVALID_PIPE;
> +}
> +
> +static void
> +vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
> +{
> +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +	struct drm_device *dev = intel_dig_port->base.base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct edp_power_seq power_seq;
> +	enum port port = intel_dig_port->port;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* try to find a pipe with this port selected */
> +	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port);
> +
> +	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
> +	if (intel_dp->pps_pipe == INVALID_PIPE) {
> +		DRM_DEBUG_KMS("no initial power sequencer for port %c\n",
> +			      port_name(port));
> +		return;
>  	}
>  
> -	/* shrug */
> -	return PIPE_A;
> +	DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n",
> +		      port_name(port), pipe_name(intel_dp->pps_pipe));
> +
> +	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> +	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
> +						      &power_seq);
>  }
>  
>  static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
> @@ -2209,6 +2280,76 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder)
>  	}
>  }
>  
> +static void vlv_steal_power_sequencer(struct drm_device *dev,
> +				      enum pipe pipe)
> +{
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_encoder *encoder;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
> +		struct intel_dp *intel_dp;
> +
> +		if (encoder->type != INTEL_OUTPUT_EDP)
> +			continue;
> +
> +		intel_dp = enc_to_intel_dp(&encoder->base);
> +
> +		if (intel_dp->pps_pipe != pipe)
> +			continue;
> +
> +		DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
> +			      pipe_name(pipe),
> +			      port_name(dp_to_dig_port(intel_dp)->port));
> +
> +		/* make sure vdd is off before we steal it */
> +		edp_panel_vdd_off_sync(intel_dp);
> +
> +		intel_dp->pps_pipe = INVALID_PIPE;
> +	}
> +}
> +
> +static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
> +{
> +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +	struct intel_encoder *encoder = &intel_dig_port->base;
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
> +	struct edp_power_seq power_seq;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (intel_dp->pps_pipe == crtc->pipe)
> +		return;
> +
> +	/*
> +	 * If another power sequencer was being used on this
> +	 * port previously make sure to turn off vdd there while
> +	 * we still have control of it.
> +	 */
> +	if (intel_dp->pps_pipe != INVALID_PIPE)
> +		edp_panel_vdd_off_sync(intel_dp);
> +
> +	/*
> +	 * We may be stealing the power
> +	 * sequencer from another port.
> +	 */
> +	vlv_steal_power_sequencer(dev, crtc->pipe);
> +
> +	/* now it's all ours */
> +	intel_dp->pps_pipe = crtc->pipe;
> +
> +	DRM_DEBUG_KMS("initializing pipe %c power sequencer for port %c\n",
> +		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
> +
> +	/* init power sequencer on this pipe and port */
> +	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> +	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
> +						      &power_seq);
> +}
> +
>  static void vlv_pre_enable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> @@ -2218,7 +2359,6 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
>  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
>  	enum dpio_channel port = vlv_dport_to_channel(dport);
>  	int pipe = intel_crtc->pipe;
> -	struct edp_power_seq power_seq;
>  	u32 val;
>  
>  	mutex_lock(&dev_priv->dpio_lock);
> @@ -2237,11 +2377,8 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
>  	mutex_unlock(&dev_priv->dpio_lock);
>  
>  	if (is_edp(intel_dp)) {
> -		/* init power sequencer on this pipe and port */
>  		mutex_lock(&dev_priv->pps_mutex);
> -		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> -		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
> -							      &power_seq);
> +		vlv_init_panel_power_sequencer(intel_dp);
>  		mutex_unlock(&dev_priv->pps_mutex);
>  	}
>  
> @@ -2286,7 +2423,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>  	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 edp_power_seq power_seq;
>  	struct intel_crtc *intel_crtc =
>  		to_intel_crtc(encoder->base.crtc);
>  	enum dpio_channel ch = vlv_dport_to_channel(dport);
> @@ -2341,11 +2477,8 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>  	mutex_unlock(&dev_priv->dpio_lock);
>  
>  	if (is_edp(intel_dp)) {
> -		/* init power sequencer on this pipe and port */
>  		mutex_lock(&dev_priv->pps_mutex);
> -		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> -		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
> -							      &power_seq);
> +		vlv_init_panel_power_sequencer(intel_dp);
>  		mutex_unlock(&dev_priv->pps_mutex);
>  	}
>  
> @@ -4691,6 +4824,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  	struct edp_power_seq power_seq = { 0 };
>  	int type;
>  
> +	intel_dp->pps_pipe = INVALID_PIPE;
> +
>  	/* intel_dp vfuncs */
>  	if (IS_VALLEYVIEW(dev))
>  		intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
> @@ -4762,8 +4897,12 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  
>  	if (is_edp(intel_dp)) {
>  		mutex_lock(&dev_priv->pps_mutex);
> -		intel_dp_init_panel_power_timestamps(intel_dp);
> -		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> +		if (IS_VALLEYVIEW(dev)) {
> +			vlv_initial_power_sequencer_setup(intel_dp);
> +		} else {
> +			intel_dp_init_panel_power_timestamps(intel_dp);
> +			intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> +		}
>  		mutex_unlock(&dev_priv->pps_mutex);
>  	}
>  
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index ad4e69b..d36299b 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -560,6 +560,12 @@ struct intel_dp {
>  
>  	struct notifier_block edp_notifier;
>  
> +	/*
> +	 * Pipe whose power sequencer is currently locked into
> +	 * this port. Only relevant on VLV/CHV.
> +	 */
> +	enum pipe pps_pipe;
> +
>  	bool use_tps3;
>  	bool can_mst; /* this port supports mst */
>  	bool is_mst;
> 

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

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

* Re: [PATCH v2 09/14] drm/i915: Fix edp vdd locking
  2014-08-19 17:32   ` [PATCH v2 " ville.syrjala
@ 2014-09-02 13:07     ` Imre Deak
  2014-09-04 11:53       ` [PATCH v3 " ville.syrjala
  0 siblings, 1 reply; 63+ messages in thread
From: Imre Deak @ 2014-09-02 13:07 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx


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

On Tue, 2014-08-19 at 20:32 +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Introduce a new mutex (pps_mutex) to protect the power sequencer
> state. For now this state includes want_panel_vdd as well as the
> power sequencer registers.
> 
> We need a single mutex (as opposed to per port) because later on we
> will need to deal with VLV/CHV which have multiple power sequencer
> which can be reassigned to different ports.
> 
> v2: Add the locking to intel_dp_encoder_suspend too (Imre)
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h      |  3 ++
>  drivers/gpu/drm/i915/intel_display.c |  2 +
>  drivers/gpu/drm/i915/intel_dp.c      | 99 ++++++++++++++++++++++++++++++++----
>  3 files changed, 93 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 6fbd316..c5faefb 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1501,6 +1501,9 @@ struct drm_i915_private {
>  	/* LVDS info */
>  	bool no_aux_handshake;
>  
> +	/* protects panel power sequencer state */
> +	struct mutex pps_mutex;
> +
>  	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
>  	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
>  	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 0b327eb..ff86729 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -12437,6 +12437,8 @@ static void intel_init_display(struct drm_device *dev)
>  	}
>  
>  	intel_panel_init_backlight_funcs(dev);
> +
> +	mutex_init(&dev_priv->pps_mutex);
>  }
>  
>  /*
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 9efa6bf..446df28 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -300,6 +300,8 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  	enum port port = intel_dig_port->port;
>  	enum pipe pipe;
>  
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	/* modeset should have pipe */
>  	if (crtc)
>  		return to_intel_crtc(crtc)->pipe;
> @@ -352,6 +354,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>  	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
>  		return 0;
>  
> +	mutex_lock(&dev_priv->pps_mutex);
> +

This needs rebasing since 02/14 wasn't applied.

>  	pipe = vlv_power_sequencer_pipe(intel_dp);
>  
>  	pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
> @@ -364,6 +368,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>  	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
>  	msleep(intel_dp->panel_power_cycle_delay);
>  
> +	mutex_unlock(&dev_priv->pps_mutex);
> +
>  	return 0;
>  }
>  
> @@ -372,6 +378,8 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
>  }
>  
> @@ -383,6 +391,8 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
>  	struct intel_encoder *intel_encoder = &intel_dig_port->base;
>  	enum intel_display_power_domain power_domain;
>  
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	power_domain = intel_display_port_power_domain(intel_encoder);
>  	return intel_display_power_enabled(dev_priv, power_domain) &&
>  	       (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
> @@ -533,6 +543,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
>  	bool has_aux_irq = HAS_AUX_IRQ(dev);
>  	bool vdd;
>  
> +	mutex_lock(&dev_priv->pps_mutex);
> +
>  	/*
>  	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
>  	 * In such cases we want to leave VDD enabled and it's up to upper layers
> @@ -648,6 +660,8 @@ out:
>  	if (vdd)
>  		edp_panel_vdd_off(intel_dp, false);
>  
> +	mutex_unlock(&dev_priv->pps_mutex);
> +
>  	return ret;
>  }
>  
> @@ -1102,6 +1116,8 @@ static void wait_panel_status(struct intel_dp *intel_dp,
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u32 pp_stat_reg, pp_ctrl_reg;
>  
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	pp_stat_reg = _pp_stat_reg(intel_dp);
>  	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
>  
> @@ -1165,6 +1181,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	u32 control;
>  
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	control = I915_READ(_pp_ctrl_reg(intel_dp));
>  	control &= ~PANEL_UNLOCK_MASK;
>  	control |= PANEL_UNLOCK_REGS;
> @@ -1182,6 +1200,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  	u32 pp_stat_reg, pp_ctrl_reg;
>  	bool need_to_disable = !intel_dp->want_panel_vdd;
>  
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	if (!is_edp(intel_dp))
>  		return false;
>  
> @@ -1221,12 +1241,16 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  
>  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
> +	struct drm_i915_private *dev_priv =
> +		intel_dp_to_dev(intel_dp)->dev_private;
>  	bool vdd;
>  
>  	if (!is_edp(intel_dp))
>  		return;
>  
> +	mutex_lock(&dev_priv->pps_mutex);
>  	vdd = edp_panel_vdd_on(intel_dp);
> +	mutex_unlock(&dev_priv->pps_mutex);
>  
>  	WARN(!vdd, "eDP VDD already requested on\n");
>  }
> @@ -1242,7 +1266,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
>  	u32 pp;
>  	u32 pp_stat_reg, pp_ctrl_reg;
>  
> -	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> +	lockdep_assert_held(&dev_priv->pps_mutex);
>  
>  	WARN_ON(intel_dp->want_panel_vdd);
>  
> @@ -1275,12 +1299,13 @@ static void edp_panel_vdd_work(struct work_struct *__work)
>  {
>  	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
>  						 struct intel_dp, panel_vdd_work);
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +	struct drm_i915_private *dev_priv =
> +		intel_dp_to_dev(intel_dp)->dev_private;
>  
> -	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> +	mutex_lock(&dev_priv->pps_mutex);
>  	if (!intel_dp->want_panel_vdd)
>  		edp_panel_vdd_off_sync(intel_dp);
> -	drm_modeset_unlock(&dev->mode_config.connection_mutex);
> +	mutex_unlock(&dev_priv->pps_mutex);
>  }
>  
>  static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
> @@ -1298,6 +1323,11 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
>  
>  static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  {
> +	struct drm_i915_private *dev_priv =
> +		intel_dp_to_dev(intel_dp)->dev_private;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	if (!is_edp(intel_dp))
>  		return;
>  
> @@ -1313,7 +1343,15 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  
>  static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  {
> +	struct drm_i915_private *dev_priv =
> +		intel_dp_to_dev(intel_dp)->dev_private;
> +
> +	if (!is_edp(intel_dp))
> +		return;
> +
> +	mutex_lock(&dev_priv->pps_mutex);
>  	edp_panel_vdd_off(intel_dp, sync);
> +	mutex_unlock(&dev_priv->pps_mutex);
>  }
>  
>  void intel_edp_panel_on(struct intel_dp *intel_dp)
> @@ -1328,9 +1366,11 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
>  
>  	DRM_DEBUG_KMS("Turn eDP power on\n");
>  
> +	mutex_lock(&dev_priv->pps_mutex);
> +
>  	if (edp_have_panel_power(intel_dp)) {
>  		DRM_DEBUG_KMS("eDP power already on\n");
> -		return;
> +		goto out;
>  	}
>  
>  	wait_panel_power_cycle(intel_dp);
> @@ -1359,6 +1399,9 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
>  		I915_WRITE(pp_ctrl_reg, pp);
>  		POSTING_READ(pp_ctrl_reg);
>  	}
> +
> + out:
> +	mutex_unlock(&dev_priv->pps_mutex);
>  }
>  
>  void intel_edp_panel_off(struct intel_dp *intel_dp)
> @@ -1376,6 +1419,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
>  
>  	DRM_DEBUG_KMS("Turn eDP power off\n");
>  
> +	mutex_lock(&dev_priv->pps_mutex);
> +
>  	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
>  
>  	pp = ironlake_get_pp_control(intel_dp);
> @@ -1397,6 +1442,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
>  	/* We got a reference when we enabled the VDD. */
>  	power_domain = intel_display_port_power_domain(intel_encoder);
>  	intel_display_power_put(dev_priv, power_domain);
> +
> +	mutex_unlock(&dev_priv->pps_mutex);
>  }
>  
>  void intel_edp_backlight_on(struct intel_dp *intel_dp)
> @@ -1421,6 +1468,9 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
>  	 * allowing it to appear.
>  	 */
>  	wait_backlight_on(intel_dp);
> +
> +	mutex_lock(&dev_priv->pps_mutex);
> +
>  	pp = ironlake_get_pp_control(intel_dp);
>  	pp |= EDP_BLC_ENABLE;
>  
> @@ -1428,6 +1478,8 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
>  
>  	I915_WRITE(pp_ctrl_reg, pp);
>  	POSTING_READ(pp_ctrl_reg);
> +
> +	mutex_unlock(&dev_priv->pps_mutex);
>  }
>  
>  void intel_edp_backlight_off(struct intel_dp *intel_dp)
> @@ -1440,6 +1492,8 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
>  	if (!is_edp(intel_dp))
>  		return;
>  
> +	mutex_lock(&dev_priv->pps_mutex);
> +
>  	DRM_DEBUG_KMS("\n");
>  	pp = ironlake_get_pp_control(intel_dp);
>  	pp &= ~EDP_BLC_ENABLE;
> @@ -1448,8 +1502,10 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
>  
>  	I915_WRITE(pp_ctrl_reg, pp);
>  	POSTING_READ(pp_ctrl_reg);
> -	intel_dp->last_backlight_off = jiffies;
>  
> +	mutex_unlock(&dev_priv->pps_mutex);
> +
> +	intel_dp->last_backlight_off = jiffies;
>  	edp_wait_backlight_off(intel_dp);
>  
>  	intel_panel_disable_backlight(intel_dp->attached_connector);

These need to be rebased on the latest backlight changes, moving the
locking into _intel_edp_backlight_on/off() and adding it to
intel_edp_backlight_power().

With the above things rebased the patch looks ok to me:
Reviewed-by: Imre Deak <imre.deak@intel.com>

> @@ -2182,9 +2238,11 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
>  
>  	if (is_edp(intel_dp)) {
>  		/* init power sequencer on this pipe and port */
> +		mutex_lock(&dev_priv->pps_mutex);
>  		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
>  		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
>  							      &power_seq);
> +		mutex_unlock(&dev_priv->pps_mutex);
>  	}
>  
>  	intel_enable_dp(encoder);
> @@ -2284,9 +2342,11 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>  
>  	if (is_edp(intel_dp)) {
>  		/* init power sequencer on this pipe and port */
> +		mutex_lock(&dev_priv->pps_mutex);
>  		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
>  		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
>  							      &power_seq);
> +		mutex_unlock(&dev_priv->pps_mutex);
>  	}
>  
>  	intel_enable_dp(encoder);
> @@ -4027,15 +4087,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
>  	struct intel_dp *intel_dp = &intel_dig_port->dp;
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  
>  	drm_dp_aux_unregister(&intel_dp->aux);
>  	intel_dp_mst_encoder_cleanup(intel_dig_port);
>  	drm_encoder_cleanup(encoder);
>  	if (is_edp(intel_dp)) {
>  		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> +		mutex_lock(&dev_priv->pps_mutex);
>  		edp_panel_vdd_off_sync(intel_dp);
> -		drm_modeset_unlock(&dev->mode_config.connection_mutex);
> +		mutex_unlock(&dev_priv->pps_mutex);
>  		if (intel_dp->edp_notifier.notifier_call) {
>  			unregister_reboot_notifier(&intel_dp->edp_notifier);
>  			intel_dp->edp_notifier.notifier_call = NULL;
> @@ -4047,11 +4108,15 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
> +	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +	struct drm_i915_private *dev_priv = dev->dev_private;
>  
>  	if (!is_edp(intel_dp))
>  		return;
>  
> +	mutex_lock(&dev_priv->pps_mutex);
>  	edp_panel_vdd_off_sync(intel_dp);
> +	mutex_unlock(&dev_priv->pps_mutex);
>  }
>  
>  static void intel_dp_encoder_reset(struct drm_encoder *encoder)
> @@ -4232,6 +4297,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
>  	u32 pp_on, pp_off, pp_div, pp;
>  	int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
>  
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	if (HAS_PCH_SPLIT(dev)) {
>  		pp_ctrl_reg = PCH_PP_CONTROL;
>  		pp_on_reg = PCH_PP_ON_DELAYS;
> @@ -4333,6 +4400,8 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
>  	int pp_on_reg, pp_off_reg, pp_div_reg;
>  	enum port port = dp_to_dig_port(intel_dp)->port;
>  
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
>  	if (HAS_PCH_SPLIT(dev)) {
>  		pp_on_reg = PCH_PP_ON_DELAYS;
>  		pp_off_reg = PCH_PP_OFF_DELAYS;
> @@ -4525,9 +4594,11 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
>  	if (intel_encoder->type != INTEL_OUTPUT_EDP)
>  		return;
>  
> +	mutex_lock(&dev_priv->pps_mutex);
> +
>  	intel_dp = enc_to_intel_dp(&intel_encoder->base);
>  	if (!edp_have_panel_vdd(intel_dp))
> -		return;
> +		goto out;
>  	/*
>  	 * The VDD bit needs a power domain reference, so if the bit is
>  	 * already enabled when we boot or resume, grab this reference and
> @@ -4539,6 +4610,8 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
>  	intel_display_power_get(dev_priv, power_domain);
>  
>  	edp_panel_vdd_schedule_off(intel_dp);
> + out:
> +	mutex_unlock(&dev_priv->pps_mutex);
>  }
>  
>  static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> @@ -4580,7 +4653,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	}
>  
>  	/* We now know it's not a ghost, init power sequence regs. */
> +	mutex_lock(&dev_priv->pps_mutex);
>  	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
> +	mutex_unlock(&dev_priv->pps_mutex);
>  
>  	mutex_lock(&dev->mode_config.mutex);
>  	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
> @@ -4712,8 +4787,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  	}
>  
>  	if (is_edp(intel_dp)) {
> +		mutex_lock(&dev_priv->pps_mutex);
>  		intel_dp_init_panel_power_timestamps(intel_dp);
>  		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
> +		mutex_unlock(&dev_priv->pps_mutex);
>  	}
>  
>  	intel_dp_aux_init(intel_dp, intel_connector);
> @@ -4729,9 +4806,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  		drm_dp_aux_unregister(&intel_dp->aux);
>  		if (is_edp(intel_dp)) {
>  			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -			drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> +			mutex_lock(&dev_priv->pps_mutex);
>  			edp_panel_vdd_off_sync(intel_dp);
> -			drm_modeset_unlock(&dev->mode_config.connection_mutex);
> +			mutex_unlock(&dev_priv->pps_mutex);
>  		}
>  		drm_connector_unregister(connector);
>  		drm_connector_cleanup(connector);


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

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

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

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

* Re: [PATCH v2 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off
  2014-08-22 14:21     ` [PATCH v2 " ville.syrjala
@ 2014-09-02 13:47       ` Imre Deak
  2014-09-04 11:54         ` [PATCH v3 " ville.syrjala
  0 siblings, 1 reply; 63+ messages in thread
From: Imre Deak @ 2014-09-02 13:47 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx


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

On Fri, 2014-08-22 at 17:21 +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> The power sequencer loses its state when the disp2d power well is down.
> Clear the dev_priv->pps_pipe tracking so that the power sequencer state
> gets reinitialized the next time it's needed.
> 
> v2: Fix the pps_mutex vs. power_domain mutex deadlock by taking power
>     domain reference first
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> Imre noticed my previouys attempt was utter garbage. Let's try again. Again maybe
> we want to squash with 10/14 or at least move the edp_pps_{lock,unlock}() introduction
> there to avoid churn.
> 
> The alternative of trying to plumb all the power domain calls out from under
> pps_mutex seemed a bit too nasty to me, so I opted for this approach instead.
> 
>  drivers/gpu/drm/i915/intel_dp.c  | 157 +++++++++++++++++++++++++--------------
>  drivers/gpu/drm/i915/intel_drv.h |   1 +
>  drivers/gpu/drm/i915/intel_pm.c  |   2 +
>  3 files changed, 106 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index d6fe1a2..3468315 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -389,6 +389,67 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
>  						      &power_seq);
>  }
>  
> +void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
> +{
> +	struct drm_device *dev = dev_priv->dev;
> +	struct intel_encoder *encoder;
> +
> +	if (WARN_ON(!IS_VALLEYVIEW(dev)))
> +		return;
> +
> +	/*
> +	 * We can't grab pps_mutex here due to deadlock with power_domain
> +	 * mutex when power_domain functions are called while holding pps_mutex.
> +	 * That also means that in order to use pps_pipe the code needs to
> +	 * hold both a power domain reference and pps_mutex, and the power domain
> +	 * reference get/put must be done while _not_ holding pps_mutex.
> +	 * edp_pps_{lock,unlock}() do these steps in the correct order, so one
> +	 * should use them always.
> +	 */
> +
> +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
> +		struct intel_dp *intel_dp;
> +
> +		if (encoder->type != INTEL_OUTPUT_EDP)
> +			continue;
> +
> +		intel_dp = enc_to_intel_dp(&encoder->base);
> +		intel_dp->pps_pipe = INVALID_PIPE;
> +	}
> +}
> +
> +static void edp_pps_lock(struct intel_dp *intel_dp)
> +{
> +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +	struct intel_encoder *encoder = &intel_dig_port->base;
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	enum intel_display_power_domain power_domain;
> +
> +	/*
> +	 * See vlv_power_sequencer_reset() why we need
> +	 * a power domain reference here.
> +	 */
> +	power_domain = intel_display_port_power_domain(encoder);
> +	intel_display_power_get(dev_priv, power_domain);
> +
> +	mutex_lock(&dev_priv->pps_mutex);
> +}
> +
> +static void edp_pps_unlock(struct intel_dp *intel_dp)
> +{
> +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +	struct intel_encoder *encoder = &intel_dig_port->base;
> +	struct drm_device *dev = encoder->base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	enum intel_display_power_domain power_domain;
> +
> +	mutex_unlock(&dev_priv->pps_mutex);
> +
> +	power_domain = intel_display_port_power_domain(encoder);
> +	intel_display_power_put(dev_priv, power_domain);
> +}
> +
>  static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
>  {
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -425,7 +486,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>  	if (!IS_VALLEYVIEW(dev) || !is_edp(intel_dp) || code != SYS_RESTART)
>  		return 0;
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  
>  	pipe = vlv_power_sequencer_pipe(intel_dp);
>  
> @@ -439,7 +500,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
>  	I915_WRITE(pp_ctrl_reg, PANEL_UNLOCK_REGS | PANEL_POWER_OFF);
>  	msleep(intel_dp->panel_power_cycle_delay);
>  
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  
>  	return 0;
>  }
> @@ -458,17 +519,13 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
>  {
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> -	struct intel_encoder *intel_encoder = &intel_dig_port->base;
> -	enum intel_display_power_domain power_domain;
>  
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
> -	power_domain = intel_display_port_power_domain(intel_encoder);
> -	return intel_display_power_enabled(dev_priv, power_domain) &&
> -	       (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
> +	return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
>  }
>  
> +

Redundant w/s change.

>  static void
>  intel_dp_check_edp(struct intel_dp *intel_dp)
>  {
> @@ -614,7 +671,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
>  	bool has_aux_irq = HAS_AUX_IRQ(dev);
>  	bool vdd;
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  
>  	/*
>  	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
> @@ -731,7 +788,7 @@ out:
>  	if (vdd)
>  		edp_panel_vdd_off(intel_dp, false);
>  
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  
>  	return ret;
>  }
> @@ -1312,16 +1369,14 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  
>  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
> -	struct drm_i915_private *dev_priv =
> -		intel_dp_to_dev(intel_dp)->dev_private;
>  	bool vdd;
>  
>  	if (!is_edp(intel_dp))
>  		return;
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  	vdd = edp_panel_vdd_on(intel_dp);
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  
>  	WARN(!vdd, "eDP VDD already requested on\n");
>  }
> @@ -1370,13 +1425,11 @@ static void edp_panel_vdd_work(struct work_struct *__work)
>  {
>  	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
>  						 struct intel_dp, panel_vdd_work);
> -	struct drm_i915_private *dev_priv =
> -		intel_dp_to_dev(intel_dp)->dev_private;
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  	if (!intel_dp->want_panel_vdd)
>  		edp_panel_vdd_off_sync(intel_dp);
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  }
>  
>  static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
> @@ -1414,15 +1467,12 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  
>  static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  {
> -	struct drm_i915_private *dev_priv =
> -		intel_dp_to_dev(intel_dp)->dev_private;
> -
>  	if (!is_edp(intel_dp))
>  		return;
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  	edp_panel_vdd_off(intel_dp, sync);
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  }
>  
>  void intel_edp_panel_on(struct intel_dp *intel_dp)
> @@ -1437,7 +1487,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
>  
>  	DRM_DEBUG_KMS("Turn eDP power on\n");
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  
>  	if (edp_have_panel_power(intel_dp)) {
>  		DRM_DEBUG_KMS("eDP power already on\n");
> @@ -1472,7 +1522,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
>  	}
>  
>   out:
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  }
>  
>  void intel_edp_panel_off(struct intel_dp *intel_dp)
> @@ -1490,7 +1540,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
>  
>  	DRM_DEBUG_KMS("Turn eDP power off\n");
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  
>  	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
>  
> @@ -1514,7 +1564,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
>  	power_domain = intel_display_port_power_domain(intel_encoder);
>  	intel_display_power_put(dev_priv, power_domain);
>  
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  }
>  
>  void intel_edp_backlight_on(struct intel_dp *intel_dp)
> @@ -1540,7 +1590,7 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
>  	 */
>  	wait_backlight_on(intel_dp);
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  
>  	pp = ironlake_get_pp_control(intel_dp);
>  	pp |= EDP_BLC_ENABLE;
> @@ -1550,7 +1600,7 @@ void intel_edp_backlight_on(struct intel_dp *intel_dp)
>  	I915_WRITE(pp_ctrl_reg, pp);
>  	POSTING_READ(pp_ctrl_reg);
>  
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  }
>  
>  void intel_edp_backlight_off(struct intel_dp *intel_dp)
> @@ -1563,7 +1613,7 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
>  	if (!is_edp(intel_dp))
>  		return;
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  
>  	DRM_DEBUG_KMS("\n");
>  	pp = ironlake_get_pp_control(intel_dp);
> @@ -1574,7 +1624,7 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
>  	I915_WRITE(pp_ctrl_reg, pp);
>  	POSTING_READ(pp_ctrl_reg);
>  
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  
>  	intel_dp->last_backlight_off = jiffies;
>  	edp_wait_backlight_off(intel_dp);

As in 9/14 the changes in the backlight functions and in
edp_notifier_handler() need to be rebased, with that this patch looks
ok:
Reviewed-by: Imre Deak <imre.deak@intel.com>

> @@ -2290,18 +2340,19 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
>  
>  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
>  		struct intel_dp *intel_dp;
> +		enum port port;
>  
>  		if (encoder->type != INTEL_OUTPUT_EDP)
>  			continue;
>  
>  		intel_dp = enc_to_intel_dp(&encoder->base);
> +		port = dp_to_dig_port(intel_dp)->port;
>  
>  		if (intel_dp->pps_pipe != pipe)
>  			continue;
>  
>  		DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
> -			      pipe_name(pipe),
> -			      port_name(dp_to_dig_port(intel_dp)->port));
> +			      pipe_name(pipe), port_name(port));
>  
>  		/* make sure vdd is off before we steal it */
>  		edp_panel_vdd_off_sync(intel_dp);
> @@ -2377,9 +2428,9 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
>  	mutex_unlock(&dev_priv->dpio_lock);
>  
>  	if (is_edp(intel_dp)) {
> -		mutex_lock(&dev_priv->pps_mutex);
> +		edp_pps_lock(intel_dp);
>  		vlv_init_panel_power_sequencer(intel_dp);
> -		mutex_unlock(&dev_priv->pps_mutex);
> +		edp_pps_unlock(intel_dp);
>  	}
>  
>  	intel_enable_dp(encoder);
> @@ -2477,9 +2528,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
>  	mutex_unlock(&dev_priv->dpio_lock);
>  
>  	if (is_edp(intel_dp)) {
> -		mutex_lock(&dev_priv->pps_mutex);
> +		edp_pps_lock(intel_dp);
>  		vlv_init_panel_power_sequencer(intel_dp);
> -		mutex_unlock(&dev_priv->pps_mutex);
> +		edp_pps_unlock(intel_dp);
>  	}
>  
>  	intel_enable_dp(encoder);
> @@ -4219,17 +4270,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  {
>  	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
>  	struct intel_dp *intel_dp = &intel_dig_port->dp;
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  
>  	drm_dp_aux_unregister(&intel_dp->aux);
>  	intel_dp_mst_encoder_cleanup(intel_dig_port);
>  	drm_encoder_cleanup(encoder);
>  	if (is_edp(intel_dp)) {
>  		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -		mutex_lock(&dev_priv->pps_mutex);
> +		edp_pps_lock(intel_dp);
>  		edp_panel_vdd_off_sync(intel_dp);
> -		mutex_unlock(&dev_priv->pps_mutex);
> +		edp_pps_unlock(intel_dp);
> +
>  		if (intel_dp->edp_notifier.notifier_call) {
>  			unregister_reboot_notifier(&intel_dp->edp_notifier);
>  			intel_dp->edp_notifier.notifier_call = NULL;
> @@ -4241,15 +4291,13 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
> -	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> -	struct drm_i915_private *dev_priv = dev->dev_private;
>  
>  	if (!is_edp(intel_dp))
>  		return;
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  	edp_panel_vdd_off_sync(intel_dp);
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  }
>  
>  static void intel_dp_encoder_reset(struct drm_encoder *encoder)
> @@ -4727,9 +4775,10 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
>  	if (intel_encoder->type != INTEL_OUTPUT_EDP)
>  		return;
>  
> -	mutex_lock(&dev_priv->pps_mutex);
> -
>  	intel_dp = enc_to_intel_dp(&intel_encoder->base);
> +
> +	edp_pps_lock(intel_dp);
> +
>  	if (!edp_have_panel_vdd(intel_dp))
>  		goto out;
>  	/*
> @@ -4744,7 +4793,7 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
>  
>  	edp_panel_vdd_schedule_off(intel_dp);
>   out:
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  }
>  
>  static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> @@ -4786,9 +4835,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	}
>  
>  	/* We now know it's not a ghost, init power sequence regs. */
> -	mutex_lock(&dev_priv->pps_mutex);
> +	edp_pps_lock(intel_dp);
>  	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
> -	mutex_unlock(&dev_priv->pps_mutex);
> +	edp_pps_unlock(intel_dp);
>  
>  	mutex_lock(&dev->mode_config.mutex);
>  	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
> @@ -4922,14 +4971,14 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  	}
>  
>  	if (is_edp(intel_dp)) {
> -		mutex_lock(&dev_priv->pps_mutex);
> +		edp_pps_lock(intel_dp);
>  		if (IS_VALLEYVIEW(dev)) {
>  			vlv_initial_power_sequencer_setup(intel_dp);
>  		} else {
>  			intel_dp_init_panel_power_timestamps(intel_dp);
>  			intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
>  		}
> -		mutex_unlock(&dev_priv->pps_mutex);
> +		edp_pps_unlock(intel_dp);
>  	}
>  
>  	intel_dp_aux_init(intel_dp, intel_connector);
> @@ -4945,9 +4994,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  		drm_dp_aux_unregister(&intel_dp->aux);
>  		if (is_edp(intel_dp)) {
>  			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -			mutex_lock(&dev_priv->pps_mutex);
> +			edp_pps_lock(intel_dp);
>  			edp_panel_vdd_off_sync(intel_dp);
> -			mutex_unlock(&dev_priv->pps_mutex);
> +			edp_pps_unlock(intel_dp);
>  		}
>  		drm_connector_unregister(connector);
>  		drm_connector_cleanup(connector);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 849a447..32627ae 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -943,6 +943,7 @@ void intel_dp_mst_suspend(struct drm_device *dev);
>  void intel_dp_mst_resume(struct drm_device *dev);
>  int intel_dp_max_link_bw(struct intel_dp *intel_dp);
>  void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
> +void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
>  /* intel_dp_mst.c */
>  int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
>  void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
> diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> index 39dd066..d5ffda9 100644
> --- a/drivers/gpu/drm/i915/intel_pm.c
> +++ b/drivers/gpu/drm/i915/intel_pm.c
> @@ -6328,6 +6328,8 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
>  	spin_unlock_irq(&dev_priv->irq_lock);
>  
>  	vlv_set_power_well(dev_priv, power_well, false);
> +
> +	vlv_power_sequencer_reset(dev_priv);
>  }
>  
>  static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,


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

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

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

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

* Re: [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe
  2014-08-18 19:16 ` [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe ville.syrjala
@ 2014-09-02 13:52   ` Imre Deak
  2014-09-04 12:59   ` Daniel Vetter
  1 sibling, 0 replies; 63+ messages in thread
From: Imre Deak @ 2014-09-02 13:52 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx


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

On Mon, 2014-08-18 at 22:16 +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Try to make sure we find the power sequencer that the BIOS used
> by first looking for one which has the panel power enabled, then
> fall back to one with VDD force bit enabled, and finally look at
> just the port select bits. This should make us pick the correct
> power sequencer when the BIOS has already enabled the panel.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 36 ++++++++++++++++++++++++++++++++++--
>  1 file changed, 34 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4614e6e..4952783 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -341,9 +341,31 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  	return intel_dp->pps_pipe;
>  }
>  
> +typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
> +			       enum pipe pipe);
> +
> +static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
> +			       enum pipe pipe)
> +{
> +	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
> +}
> +
> +static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
> +				enum pipe pipe)
> +{
> +	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> +}
> +
> +static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> +			 enum pipe pipe)
> +{
> +	return true;
> +}
> +
>  static enum pipe
>  vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
> -				 enum port port)
> +				 enum port port,
> +				 vlv_pipe_check pipe_check)
>  {
>  	enum pipe pipe;
>  
> @@ -354,6 +376,9 @@ vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
>  		if (port_sel != PANEL_PORT_SELECT_VLV(port))
>  			continue;
>  
> +		if (!pipe_check(dev_priv, pipe))
> +			continue;
> +
>  		return pipe;
>  	}
>  
> @@ -372,7 +397,14 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
>  	/* try to find a pipe with this port selected */
> -	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port);
> +	/* first pick one where the panel is on */
> +	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_has_pp_on);
> +	/* didn't find one? pick one where vdd is on */
> +	if (intel_dp->pps_pipe == INVALID_PIPE)
> +		intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_has_vdd_on);
> +	/* didn't find one? pick one with just the correct port */
> +	if (intel_dp->pps_pipe == INVALID_PIPE)
> +		intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_any);
>  
>  	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
>  	if (intel_dp->pps_pipe == INVALID_PIPE) {


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

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

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

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

* Re: [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers
  2014-08-18 19:16 ` [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers ville.syrjala
  2014-08-19  7:33   ` Jani Nikula
@ 2014-09-02 14:02   ` Imre Deak
  1 sibling, 0 replies; 63+ messages in thread
From: Imre Deak @ 2014-09-02 14:02 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx


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

On Mon, 2014-08-18 at 22:16 +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> On VLV/CHV the panel power sequencer may need to be "kicked" a bit to
> lock onto the new port, and that needs to happen before any aux
> transfers are attempted if we want the aux transfers to actaully
> succeed. So turn on panel power (part of the "kick") before aux
> transfers (DPMS_ON + link training).
> 
> This also matches the documented modeset sequence better for pch
> platforms. The documentation doesn't explicitly state anything about the
> DPMS or link training DPCD writes, but the panel power on step is
> always listed before link training is mentioned.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Jani had the same change in:
https://bugs.freedesktop.org/show_bug.cgi?id=70117

which solved link training issues, so we could add a reference to that
bug and ask the reporters to retest. The patch looks ok:
Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4952783..28bc652 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2275,10 +2275,10 @@ static void intel_enable_dp(struct intel_encoder *encoder)
>  		return;
>  
>  	intel_edp_panel_vdd_on(intel_dp);
> -	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> -	intel_dp_start_link_train(intel_dp);
>  	intel_edp_panel_on(intel_dp);
>  	intel_edp_panel_vdd_off(intel_dp, true);
> +	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
> +	intel_dp_start_link_train(intel_dp);
>  	intel_dp_complete_link_train(intel_dp);
>  	intel_dp_stop_link_train(intel_dp);
>  }


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

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

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

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

* Re: [PATCH 13/14] drm/i915: Enable DP port earlier
  2014-08-18 19:16 ` [PATCH 13/14] drm/i915: Enable DP port earlier ville.syrjala
@ 2014-09-03 11:02   ` Imre Deak
  0 siblings, 0 replies; 63+ messages in thread
From: Imre Deak @ 2014-09-03 11:02 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx


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

On Mon, 2014-08-18 at 22:16 +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Bspec says we should enable the DP port before enabling panel power,
> and that the port must be enabled with training pattern 1. Do so.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 172 +++++++++++++++++++++++-----------------
>  1 file changed, 100 insertions(+), 72 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 28bc652..12925be 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2264,6 +2264,104 @@ static void chv_post_disable_dp(struct intel_encoder *encoder)
>  	mutex_unlock(&dev_priv->dpio_lock);
>  }
>  
> +static void
> +_intel_dp_set_link_train(struct intel_dp *intel_dp,
> +			 uint32_t *DP,
> +			 uint8_t dp_train_pat)
> +{
> +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
> +	struct drm_device *dev = intel_dig_port->base.base.dev;
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +	enum port port = intel_dig_port->port;
> +
> +	if (HAS_DDI(dev)) {
> +		uint32_t temp = I915_READ(DP_TP_CTL(port));
> +
> +		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
> +			temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
> +		else
> +			temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
> +
> +		temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
> +		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
> +		case DP_TRAINING_PATTERN_DISABLE:
> +			temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
> +
> +			break;
> +		case DP_TRAINING_PATTERN_1:
> +			temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
> +			break;
> +		case DP_TRAINING_PATTERN_2:
> +			temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
> +			break;
> +		case DP_TRAINING_PATTERN_3:
> +			temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
> +			break;
> +		}
> +		I915_WRITE(DP_TP_CTL(port), temp);
> +
> +	} else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
> +		*DP &= ~DP_LINK_TRAIN_MASK_CPT;
> +
> +		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
> +		case DP_TRAINING_PATTERN_DISABLE:
> +			*DP |= DP_LINK_TRAIN_OFF_CPT;
> +			break;
> +		case DP_TRAINING_PATTERN_1:
> +			*DP |= DP_LINK_TRAIN_PAT_1_CPT;
> +			break;
> +		case DP_TRAINING_PATTERN_2:
> +			*DP |= DP_LINK_TRAIN_PAT_2_CPT;
> +			break;
> +		case DP_TRAINING_PATTERN_3:
> +			DRM_ERROR("DP training pattern 3 not supported\n");
> +			*DP |= DP_LINK_TRAIN_PAT_2_CPT;
> +			break;
> +		}
> +
> +	} else {
> +		if (IS_CHERRYVIEW(dev))
> +			*DP &= ~DP_LINK_TRAIN_MASK_CHV;
> +		else
> +			*DP &= ~DP_LINK_TRAIN_MASK;
> +
> +		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
> +		case DP_TRAINING_PATTERN_DISABLE:
> +			*DP |= DP_LINK_TRAIN_OFF;
> +			break;
> +		case DP_TRAINING_PATTERN_1:
> +			*DP |= DP_LINK_TRAIN_PAT_1;
> +			break;
> +		case DP_TRAINING_PATTERN_2:
> +			*DP |= DP_LINK_TRAIN_PAT_2;
> +			break;
> +		case DP_TRAINING_PATTERN_3:
> +			if (IS_CHERRYVIEW(dev)) {
> +				*DP |= DP_LINK_TRAIN_PAT_3_CHV;
> +			} else {
> +				DRM_ERROR("DP training pattern 3 not supported\n");
> +				*DP |= DP_LINK_TRAIN_PAT_2;
> +			}
> +			break;
> +		}
> +	}
> +}
> +
> +static void intel_dp_enable_port(struct intel_dp *intel_dp)
> +{
> +	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> +	struct drm_i915_private *dev_priv = dev->dev_private;
> +
> +	intel_dp->DP |= DP_PORT_EN;
> +
> +	/* enable with pattern 1 (as per spec) */
> +	_intel_dp_set_link_train(intel_dp, &intel_dp->DP,
> +				 DP_TRAINING_PATTERN_1);
> +
> +	I915_WRITE(intel_dp->output_reg, intel_dp->DP);
> +	POSTING_READ(intel_dp->output_reg);
> +}
> +
>  static void intel_enable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> @@ -2274,6 +2372,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
>  	if (WARN_ON(dp_reg & DP_PORT_EN))
>  		return;
>  
> +	intel_dp_enable_port(intel_dp);
>  	intel_edp_panel_vdd_on(intel_dp);
>  	intel_edp_panel_on(intel_dp);
>  	intel_edp_panel_vdd_off(intel_dp, true);
> @@ -3174,81 +3273,10 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
>  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
>  	struct drm_device *dev = intel_dig_port->base.base.dev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
> -	enum port port = intel_dig_port->port;
>  	uint8_t buf[sizeof(intel_dp->train_set) + 1];
>  	int ret, len;
>  
> -	if (HAS_DDI(dev)) {
> -		uint32_t temp = I915_READ(DP_TP_CTL(port));
> -
> -		if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE)
> -			temp |= DP_TP_CTL_SCRAMBLE_DISABLE;
> -		else
> -			temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE;
> -
> -		temp &= ~DP_TP_CTL_LINK_TRAIN_MASK;
> -		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
> -		case DP_TRAINING_PATTERN_DISABLE:
> -			temp |= DP_TP_CTL_LINK_TRAIN_NORMAL;
> -
> -			break;
> -		case DP_TRAINING_PATTERN_1:
> -			temp |= DP_TP_CTL_LINK_TRAIN_PAT1;
> -			break;
> -		case DP_TRAINING_PATTERN_2:
> -			temp |= DP_TP_CTL_LINK_TRAIN_PAT2;
> -			break;
> -		case DP_TRAINING_PATTERN_3:
> -			temp |= DP_TP_CTL_LINK_TRAIN_PAT3;
> -			break;
> -		}
> -		I915_WRITE(DP_TP_CTL(port), temp);
> -
> -	} else if (HAS_PCH_CPT(dev) && (IS_GEN7(dev) || port != PORT_A)) {
> -		*DP &= ~DP_LINK_TRAIN_MASK_CPT;
> -
> -		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
> -		case DP_TRAINING_PATTERN_DISABLE:
> -			*DP |= DP_LINK_TRAIN_OFF_CPT;
> -			break;
> -		case DP_TRAINING_PATTERN_1:
> -			*DP |= DP_LINK_TRAIN_PAT_1_CPT;
> -			break;
> -		case DP_TRAINING_PATTERN_2:
> -			*DP |= DP_LINK_TRAIN_PAT_2_CPT;
> -			break;
> -		case DP_TRAINING_PATTERN_3:
> -			DRM_ERROR("DP training pattern 3 not supported\n");
> -			*DP |= DP_LINK_TRAIN_PAT_2_CPT;
> -			break;
> -		}
> -
> -	} else {
> -		if (IS_CHERRYVIEW(dev))
> -			*DP &= ~DP_LINK_TRAIN_MASK_CHV;
> -		else
> -			*DP &= ~DP_LINK_TRAIN_MASK;
> -
> -		switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) {
> -		case DP_TRAINING_PATTERN_DISABLE:
> -			*DP |= DP_LINK_TRAIN_OFF;
> -			break;
> -		case DP_TRAINING_PATTERN_1:
> -			*DP |= DP_LINK_TRAIN_PAT_1;
> -			break;
> -		case DP_TRAINING_PATTERN_2:
> -			*DP |= DP_LINK_TRAIN_PAT_2;
> -			break;
> -		case DP_TRAINING_PATTERN_3:
> -			if (IS_CHERRYVIEW(dev)) {
> -				*DP |= DP_LINK_TRAIN_PAT_3_CHV;
> -			} else {
> -				DRM_ERROR("DP training pattern 3 not supported\n");
> -				*DP |= DP_LINK_TRAIN_PAT_2;
> -			}
> -			break;
> -		}
> -	}
> +	_intel_dp_set_link_train(intel_dp, DP, dp_train_pat);
>  
>  	I915_WRITE(intel_dp->output_reg, *DP);
>  	POSTING_READ(intel_dp->output_reg);


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

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

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

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

* Re: [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms
  2014-08-18 19:16 ` [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms ville.syrjala
  2014-08-26  9:43   ` Daniel Vetter
@ 2014-09-03 11:20   ` Imre Deak
  1 sibling, 0 replies; 63+ messages in thread
From: Imre Deak @ 2014-09-03 11:20 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx


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

On Mon, 2014-08-18 at 22:16 +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> We need to turn the DP port off after the pipe, otherwise the pipe won't
> turn off properly on certain pch platforms at least (happens on my ILK for
> example).  This also matches the BSpec modeset sequence better. We still
> don't match the spec exactly though (eg. audio disable should happen
> much earlier), but at last this eliminates the nasty
> wait_for_pipe_off() timeouts.
> 
> We already did the port disable after the pipe for VLV/CHV and for CPU
> eDP.
> 
> For g4x leave the port disable where it is since that matches the
> modeset sequence in the documentation and I don't have a suitable
> machine to test if the other order would work.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Imre Deak <imre.deak@intel.com>

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 16 +++++++---------
>  1 file changed, 7 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 12925be..915d4ec 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -2194,7 +2194,6 @@ void intel_edp_psr_init(struct drm_device *dev)
>  static void intel_disable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
> -	enum port port = dp_to_dig_port(intel_dp)->port;
>  	struct drm_device *dev = encoder->base.dev;
>  
>  	/* Make sure the panel is off before trying to change the mode. But also
> @@ -2204,21 +2203,19 @@ static void intel_disable_dp(struct intel_encoder *encoder)
>  	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
>  	intel_edp_panel_off(intel_dp);
>  
> -	/* cpu edp my only be disable _after_ the cpu pipe/plane is disabled. */
> -	if (!(port == PORT_A || IS_VALLEYVIEW(dev)))
> +	/* disable the port before the pipe on g4x */
> +	if (INTEL_INFO(dev)->gen < 5)
>  		intel_dp_link_down(intel_dp);
>  }
>  
> -static void g4x_post_disable_dp(struct intel_encoder *encoder)
> +static void ilk_post_disable_dp(struct intel_encoder *encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
>  	enum port port = dp_to_dig_port(intel_dp)->port;
>  
> -	if (port != PORT_A)
> -		return;
> -
>  	intel_dp_link_down(intel_dp);
> -	ironlake_edp_pll_off(intel_dp);
> +	if (port == PORT_A)
> +		ironlake_edp_pll_off(intel_dp);
>  }
>  
>  static void vlv_post_disable_dp(struct intel_encoder *encoder)
> @@ -5044,7 +5041,8 @@ intel_dp_init(struct drm_device *dev, int output_reg, enum port port)
>  	} else {
>  		intel_encoder->pre_enable = g4x_pre_enable_dp;
>  		intel_encoder->enable = g4x_enable_dp;
> -		intel_encoder->post_disable = g4x_post_disable_dp;
> +		if (INTEL_INFO(dev)->gen >= 5)
> +			intel_encoder->post_disable = ilk_post_disable_dp;
>  	}
>  
>  	intel_dig_port->port = port;


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

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

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

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

* Re: [PATCH 15/14] drm/i915: Add comments explaining the vdd on/off functions
  2014-08-19 17:47         ` [PATCH 15/14] drm/i915: Add comments explaining the vdd on/off functions ville.syrjala
@ 2014-09-03 11:52           ` Imre Deak
  2014-09-04 11:55             ` [PATCH v2 " ville.syrjala
  0 siblings, 1 reply; 63+ messages in thread
From: Imre Deak @ 2014-09-03 11:52 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx


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

On Tue, 2014-08-19 at 20:47 +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Jani wanted some comments to explain why we call certain vdd on/off
> functions in certain places.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 1067082..1233a10 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1315,6 +1315,7 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
>  	return control;
>  }
>  
> +/* should be paired with edp_panel_vdd_off() */

It would be useful to clarify here the purpose of the edp_ vs.
intel_edp_* versions. Iiuc you need to hold pps_lock around the whole
edp_panel_vdd_on/off() sequence and these can be nested within an
intel_edp_panel_vdd_on/off() sequence. Otoh, you can't nest
intel_edp_panel_vdd_on() calls.

>  static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -1365,6 +1366,7 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  	return need_to_disable;
>  }
>  
> +/* should be paired with intel_edp_panel_vdd_off() */
>  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv =
> @@ -1447,6 +1449,7 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
>  	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
>  }
>  
> +/* should be paired with edp_panel_vdd_on() */
>  static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  {
>  	struct drm_i915_private *dev_priv =
> @@ -1467,6 +1470,7 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  		edp_panel_vdd_schedule_off(intel_dp);
>  }
>  
> +/* should be paired with intel_edp_panel_vdd_on() */
>  static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  {
>  	struct drm_i915_private *dev_priv =
> @@ -4307,6 +4311,10 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  	drm_encoder_cleanup(encoder);
>  	if (is_edp(intel_dp)) {
>  		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +		/*
> +		 * vdd might still be enabled do to the delayed vdd off.

s/do/due/

> +		 * Make sure vdd is actually turned off here.
> +		 */
>  		mutex_lock(&dev_priv->pps_mutex);
>  		edp_panel_vdd_off_sync(intel_dp);
>  		mutex_unlock(&dev_priv->pps_mutex);
> @@ -4327,6 +4335,10 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>  	if (!is_edp(intel_dp))
>  		return;
>  
> +	/*
> +	 * vdd might still be enabled do to the delayed vdd off.
> +	 * Make sure vdd is actually turned off here.
> +	 */
>  	mutex_lock(&dev_priv->pps_mutex);
>  	edp_panel_vdd_off_sync(intel_dp);
>  	mutex_unlock(&dev_priv->pps_mutex);
> @@ -5025,6 +5037,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  		drm_dp_aux_unregister(&intel_dp->aux);
>  		if (is_edp(intel_dp)) {
>  			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +			/*
> +			 * vdd might still be enabled do to the delayed vdd off.
> +			 * Make sure vdd is actually turned off here.
> +			 */
>  			mutex_lock(&dev_priv->pps_mutex);
>  			edp_panel_vdd_off_sync(intel_dp);
>  			mutex_unlock(&dev_priv->pps_mutex);

edp_panel_vdd_off_sync() could also use a clarification similar to the
the rest of the API.

With or without the above changes:
Reviewed-by: Imre Deak <imre.deak@intel.com>



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

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

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

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

* [PATCH v3 09/14] drm/i915: Fix edp vdd locking
  2014-09-02 13:07     ` Imre Deak
@ 2014-09-04 11:53       ` ville.syrjala
  0 siblings, 0 replies; 63+ messages in thread
From: ville.syrjala @ 2014-09-04 11:53 UTC (permalink / raw)
  To: intel-gfx

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

Introduce a new mutex (pps_mutex) to protect the power sequencer
state. For now this state includes want_panel_vdd as well as the
power sequencer registers.

We need a single mutex (as opposed to per port) because later on we
will need to deal with VLV/CHV which have multiple power sequencer
which can be reassigned to different ports.

v2: Add the locking to intel_dp_encoder_suspend too (Imre)
v3: Take care intel_edp_backlight_power() and
    _intel_edp_backlight_on/off(), deal with reboot notifier
    vlv_power_sequencer_pipe() call (Imre)

Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h      |   3 +
 drivers/gpu/drm/i915/intel_display.c |   2 +
 drivers/gpu/drm/i915/intel_dp.c      | 112 +++++++++++++++++++++++++++++++----
 3 files changed, 104 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e845a81..5706b8a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1528,6 +1528,9 @@ struct drm_i915_private {
 	/* LVDS info */
 	bool no_aux_handshake;
 
+	/* protects panel power sequencer state */
+	struct mutex pps_mutex;
+
 	struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
 	int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
 	int num_fence_regs; /* 8 on pre-965, 16 otherwise */
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 22d3902..965eb3c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12593,6 +12593,8 @@ static void intel_init_display(struct drm_device *dev)
 	}
 
 	intel_panel_init_backlight_funcs(dev);
+
+	mutex_init(&dev_priv->pps_mutex);
 }
 
 /*
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index f79473b..487bcb9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -300,6 +300,8 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 	enum port port = intel_dig_port->port;
 	enum pipe pipe;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	/* modeset should have pipe */
 	if (crtc)
 		return to_intel_crtc(crtc)->pipe;
@@ -347,12 +349,15 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp_div;
 	u32 pp_ctrl_reg, pp_div_reg;
-	enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
 
 	if (!is_edp(intel_dp) || code != SYS_RESTART)
 		return 0;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	if (IS_VALLEYVIEW(dev)) {
+		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
+
 		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
 		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
 		pp_div = I915_READ(pp_div_reg);
@@ -364,6 +369,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 		msleep(intel_dp->panel_power_cycle_delay);
 	}
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
 	return 0;
 }
 
@@ -372,6 +379,8 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	return (I915_READ(_pp_stat_reg(intel_dp)) & PP_ON) != 0;
 }
 
@@ -383,6 +392,8 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 	struct intel_encoder *intel_encoder = &intel_dig_port->base;
 	enum intel_display_power_domain power_domain;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	return intel_display_power_enabled(dev_priv, power_domain) &&
 	       (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
@@ -533,6 +544,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
 	bool vdd;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	/*
 	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
 	 * In such cases we want to leave VDD enabled and it's up to upper layers
@@ -648,6 +661,8 @@ out:
 	if (vdd)
 		edp_panel_vdd_off(intel_dp, false);
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
 	return ret;
 }
 
@@ -1102,6 +1117,8 @@ static void wait_panel_status(struct intel_dp *intel_dp,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 pp_stat_reg, pp_ctrl_reg;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	pp_stat_reg = _pp_stat_reg(intel_dp);
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
@@ -1165,6 +1182,8 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 control;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	control = I915_READ(_pp_ctrl_reg(intel_dp));
 	control &= ~PANEL_UNLOCK_MASK;
 	control |= PANEL_UNLOCK_REGS;
@@ -1182,6 +1201,8 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 	u32 pp_stat_reg, pp_ctrl_reg;
 	bool need_to_disable = !intel_dp->want_panel_vdd;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (!is_edp(intel_dp))
 		return false;
 
@@ -1221,12 +1242,16 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
 	bool vdd;
 
 	if (!is_edp(intel_dp))
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
 	vdd = edp_panel_vdd_on(intel_dp);
+	mutex_unlock(&dev_priv->pps_mutex);
 
 	WARN(!vdd, "eDP VDD already requested on\n");
 }
@@ -1242,7 +1267,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
 	u32 pp;
 	u32 pp_stat_reg, pp_ctrl_reg;
 
-	WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
+	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	WARN_ON(intel_dp->want_panel_vdd);
 
@@ -1275,12 +1300,13 @@ static void edp_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
 						 struct intel_dp, panel_vdd_work);
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
 
-	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+	mutex_lock(&dev_priv->pps_mutex);
 	if (!intel_dp->want_panel_vdd)
 		edp_panel_vdd_off_sync(intel_dp);
-	drm_modeset_unlock(&dev->mode_config.connection_mutex);
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
@@ -1298,6 +1324,11 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
 
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (!is_edp(intel_dp))
 		return;
 
@@ -1313,7 +1344,15 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
 static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
+	struct drm_i915_private *dev_priv =
+		intel_dp_to_dev(intel_dp)->dev_private;
+
+	if (!is_edp(intel_dp))
+		return;
+
+	mutex_lock(&dev_priv->pps_mutex);
 	edp_panel_vdd_off(intel_dp, sync);
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_panel_on(struct intel_dp *intel_dp)
@@ -1328,9 +1367,11 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power on\n");
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	if (edp_have_panel_power(intel_dp)) {
 		DRM_DEBUG_KMS("eDP power already on\n");
-		return;
+		goto out;
 	}
 
 	wait_panel_power_cycle(intel_dp);
@@ -1359,6 +1400,9 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 		I915_WRITE(pp_ctrl_reg, pp);
 		POSTING_READ(pp_ctrl_reg);
 	}
+
+ out:
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
@@ -1376,6 +1420,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
 
 	pp = ironlake_get_pp_control(intel_dp);
@@ -1397,6 +1443,8 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 	/* We got a reference when we enabled the VDD. */
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	intel_display_power_put(dev_priv, power_domain);
+
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 /* Enable backlight in the panel power control. */
@@ -1415,6 +1463,9 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 	 * allowing it to appear.
 	 */
 	wait_backlight_on(intel_dp);
+
+	mutex_lock(&dev_priv->pps_mutex);
+
 	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_BLC_ENABLE;
 
@@ -1422,6 +1473,8 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
+
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 /* Enable backlight PWM and backlight PP control. */
@@ -1444,6 +1497,11 @@ static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
 	u32 pp;
 	u32 pp_ctrl_reg;
 
+	if (!is_edp(intel_dp))
+		return;
+
+	mutex_lock(&dev_priv->pps_mutex);
+
 	pp = ironlake_get_pp_control(intel_dp);
 	pp &= ~EDP_BLC_ENABLE;
 
@@ -1451,8 +1509,10 @@ static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
 
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
-	intel_dp->last_backlight_off = jiffies;
 
+	mutex_unlock(&dev_priv->pps_mutex);
+
+	intel_dp->last_backlight_off = jiffies;
 	edp_wait_backlight_off(intel_dp);
 }
 
@@ -1475,8 +1535,13 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
 static void intel_edp_backlight_power(struct intel_connector *connector,
 				      bool enable)
 {
+	struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
 	struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
-	bool is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
+	bool is_enabled;
+
+	mutex_lock(&dev_priv->pps_mutex);
+	is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
+	mutex_unlock(&dev_priv->pps_mutex);
 
 	if (is_enabled == enable)
 		return;
@@ -2219,9 +2284,11 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 
 	if (is_edp(intel_dp)) {
 		/* init power sequencer on this pipe and port */
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
 							      &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_enable_dp(encoder);
@@ -2312,9 +2379,11 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 
 	if (is_edp(intel_dp)) {
 		/* init power sequencer on this pipe and port */
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
 							      &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_enable_dp(encoder);
@@ -4077,15 +4146,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	drm_dp_aux_unregister(&intel_dp->aux);
 	intel_dp_mst_encoder_cleanup(intel_dig_port);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-		drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+		mutex_lock(&dev_priv->pps_mutex);
 		edp_panel_vdd_off_sync(intel_dp);
-		drm_modeset_unlock(&dev->mode_config.connection_mutex);
+		mutex_unlock(&dev_priv->pps_mutex);
 		if (intel_dp->edp_notifier.notifier_call) {
 			unregister_reboot_notifier(&intel_dp->edp_notifier);
 			intel_dp->edp_notifier.notifier_call = NULL;
@@ -4097,11 +4167,15 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
+	struct drm_device *dev = intel_dp_to_dev(intel_dp);
+	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (!is_edp(intel_dp))
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
 	edp_panel_vdd_off_sync(intel_dp);
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 static void intel_dp_encoder_reset(struct drm_encoder *encoder)
@@ -4289,6 +4363,8 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
 	u32 pp_on, pp_off, pp_div, pp;
 	int pp_ctrl_reg, pp_on_reg, pp_off_reg, pp_div_reg;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (HAS_PCH_SPLIT(dev)) {
 		pp_ctrl_reg = PCH_PP_CONTROL;
 		pp_on_reg = PCH_PP_ON_DELAYS;
@@ -4390,6 +4466,8 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 	int pp_on_reg, pp_off_reg, pp_div_reg;
 	enum port port = dp_to_dig_port(intel_dp)->port;
 
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
 	if (HAS_PCH_SPLIT(dev)) {
 		pp_on_reg = PCH_PP_ON_DELAYS;
 		pp_off_reg = PCH_PP_OFF_DELAYS;
@@ -4582,9 +4660,11 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		return;
 
+	mutex_lock(&dev_priv->pps_mutex);
+
 	intel_dp = enc_to_intel_dp(&intel_encoder->base);
 	if (!edp_have_panel_vdd(intel_dp))
-		return;
+		goto out;
 	/*
 	 * The VDD bit needs a power domain reference, so if the bit is
 	 * already enabled when we boot or resume, grab this reference and
@@ -4596,6 +4676,8 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 	intel_display_power_get(dev_priv, power_domain);
 
 	edp_panel_vdd_schedule_off(intel_dp);
+ out:
+	mutex_unlock(&dev_priv->pps_mutex);
 }
 
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
@@ -4637,7 +4719,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 
 	/* We now know it's not a ghost, init power sequence regs. */
+	mutex_lock(&dev_priv->pps_mutex);
 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
+	mutex_unlock(&dev_priv->pps_mutex);
 
 	mutex_lock(&dev->mode_config.mutex);
 	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
@@ -4770,8 +4854,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	}
 
 	if (is_edp(intel_dp)) {
+		mutex_lock(&dev_priv->pps_mutex);
 		intel_dp_init_panel_power_timestamps(intel_dp);
 		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
 	intel_dp_aux_init(intel_dp, intel_connector);
@@ -4787,9 +4873,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		drm_dp_aux_unregister(&intel_dp->aux);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-			drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+			mutex_lock(&dev_priv->pps_mutex);
 			edp_panel_vdd_off_sync(intel_dp);
-			drm_modeset_unlock(&dev->mode_config.connection_mutex);
+			mutex_unlock(&dev_priv->pps_mutex);
 		}
 		drm_connector_unregister(connector);
 		drm_connector_cleanup(connector);
-- 
1.8.5.5

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

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

* [PATCH v2 10/14] drm/i915: Track which port is using which pipe's power sequencer
  2014-08-18 19:16 ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer ville.syrjala
  2014-08-19 17:45   ` [PATCH 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off ville.syrjala
  2014-09-01 11:19   ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer Antti Koskipää
@ 2014-09-04 11:54   ` ville.syrjala
  2 siblings, 0 replies; 63+ messages in thread
From: ville.syrjala @ 2014-09-04 11:54 UTC (permalink / raw)
  To: intel-gfx

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

VLV/CHV have a per-pipe panel power sequencer which locks onto the
port once used. We need to keep track wich power sequencers are
locked to which ports.

v2: remove spurious whitespace change, rebase due to backlight changes (Imre)

Reviewed-by: Antti Koskipaa <antti.koskipaa@linux.intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 187 ++++++++++++++++++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_drv.h |   6 ++
 2 files changed, 169 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 487bcb9..0dd0abd 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -294,28 +294,99 @@ static enum pipe
 vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct drm_crtc *crtc = intel_dig_port->base.base.crtc;
 	struct drm_device *dev = intel_dig_port->base.base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	enum port port = intel_dig_port->port;
-	enum pipe pipe;
+	struct intel_encoder *encoder;
+	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
+	struct edp_power_seq power_seq;
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	/* modeset should have pipe */
-	if (crtc)
-		return to_intel_crtc(crtc)->pipe;
+	if (intel_dp->pps_pipe != INVALID_PIPE)
+		return intel_dp->pps_pipe;
+
+	/*
+	 * We don't have power sequencer currently.
+	 * Pick one that's not used by other ports.
+	 */
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		struct intel_dp *tmp;
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		tmp = enc_to_intel_dp(&encoder->base);
+
+		if (tmp->pps_pipe != INVALID_PIPE)
+			pipes &= ~(1 << tmp->pps_pipe);
+	}
+
+	/*
+	 * Didn't find one. This should not happen since there
+	 * are two power sequencers and up to two eDP ports.
+	 */
+	if (WARN_ON(pipes == 0))
+		return PIPE_A;
+
+	intel_dp->pps_pipe = ffs(pipes) - 1;
+
+	DRM_DEBUG_KMS("picked pipe %c power sequencer for port %c\n",
+		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
+
+	/* init power sequencer on this pipe and port */
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
+
+	return intel_dp->pps_pipe;
+}
+
+static enum pipe
+vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
+				 enum port port)
+{
+	enum pipe pipe;
 
-	/* init time, try to find a pipe with this port selected */
 	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
 		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
 			PANEL_PORT_SELECT_MASK;
-		if (port_sel == PANEL_PORT_SELECT_VLV(port))
-			return pipe;
+
+		if (port_sel != PANEL_PORT_SELECT_VLV(port))
+			continue;
+
+		return pipe;
 	}
 
-	/* shrug */
-	return PIPE_A;
+	return INVALID_PIPE;
+}
+
+static void
+vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct drm_device *dev = intel_dig_port->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct edp_power_seq power_seq;
+	enum port port = intel_dig_port->port;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	/* try to find a pipe with this port selected */
+	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port);
+
+	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
+	if (intel_dp->pps_pipe == INVALID_PIPE) {
+		DRM_DEBUG_KMS("no initial power sequencer for port %c\n",
+			      port_name(port));
+		return;
+	}
+
+	DRM_DEBUG_KMS("initial power sequencer for port %c: pipe %c\n",
+		      port_name(port), pipe_name(intel_dp->pps_pipe));
+
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
 }
 
 static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
@@ -2255,6 +2326,76 @@ static void g4x_pre_enable_dp(struct intel_encoder *encoder)
 	}
 }
 
+static void vlv_steal_power_sequencer(struct drm_device *dev,
+				      enum pipe pipe)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_encoder *encoder;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		struct intel_dp *intel_dp;
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		intel_dp = enc_to_intel_dp(&encoder->base);
+
+		if (intel_dp->pps_pipe != pipe)
+			continue;
+
+		DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
+			      pipe_name(pipe),
+			      port_name(dp_to_dig_port(intel_dp)->port));
+
+		/* make sure vdd is off before we steal it */
+		edp_panel_vdd_off_sync(intel_dp);
+
+		intel_dp->pps_pipe = INVALID_PIPE;
+	}
+}
+
+static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &intel_dig_port->base;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+	struct edp_power_seq power_seq;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if (intel_dp->pps_pipe == crtc->pipe)
+		return;
+
+	/*
+	 * If another power sequencer was being used on this
+	 * port previously make sure to turn off vdd there while
+	 * we still have control of it.
+	 */
+	if (intel_dp->pps_pipe != INVALID_PIPE)
+		edp_panel_vdd_off_sync(intel_dp);
+
+	/*
+	 * We may be stealing the power
+	 * sequencer from another port.
+	 */
+	vlv_steal_power_sequencer(dev, crtc->pipe);
+
+	/* now it's all ours */
+	intel_dp->pps_pipe = crtc->pipe;
+
+	DRM_DEBUG_KMS("initializing pipe %c power sequencer for port %c\n",
+		      pipe_name(intel_dp->pps_pipe), port_name(intel_dig_port->port));
+
+	/* init power sequencer on this pipe and port */
+	intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+						      &power_seq);
+}
+
 static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
@@ -2264,7 +2405,6 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
 	enum dpio_channel port = vlv_dport_to_channel(dport);
 	int pipe = intel_crtc->pipe;
-	struct edp_power_seq power_seq;
 	u32 val;
 
 	mutex_lock(&dev_priv->dpio_lock);
@@ -2283,11 +2423,8 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		/* init power sequencer on this pipe and port */
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-							      &power_seq);
+		vlv_init_panel_power_sequencer(intel_dp);
 		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
@@ -2332,7 +2469,6 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	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 edp_power_seq power_seq;
 	struct intel_crtc *intel_crtc =
 		to_intel_crtc(encoder->base.crtc);
 	enum dpio_channel ch = vlv_dport_to_channel(dport);
@@ -2378,11 +2514,8 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		/* init power sequencer on this pipe and port */
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
-							      &power_seq);
+		vlv_init_panel_power_sequencer(intel_dp);
 		mutex_unlock(&dev_priv->pps_mutex);
 	}
 
@@ -4784,6 +4917,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	struct edp_power_seq power_seq = { 0 };
 	int type;
 
+	intel_dp->pps_pipe = INVALID_PIPE;
+
 	/* intel_dp vfuncs */
 	if (IS_VALLEYVIEW(dev))
 		intel_dp->get_aux_clock_divider = vlv_get_aux_clock_divider;
@@ -4855,10 +4990,14 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 
 	if (is_edp(intel_dp)) {
 		mutex_lock(&dev_priv->pps_mutex);
-		intel_dp_init_panel_power_timestamps(intel_dp);
-		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
-		mutex_unlock(&dev_priv->pps_mutex);
+		if (IS_VALLEYVIEW(dev)) {
+			vlv_initial_power_sequencer_setup(intel_dp);
+		} else {
+			intel_dp_init_panel_power_timestamps(intel_dp);
+			intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
+		}
 	}
+	mutex_unlock(&dev_priv->pps_mutex);
 
 	intel_dp_aux_init(intel_dp, intel_connector);
 
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d727d20..1278b25 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -570,6 +570,12 @@ struct intel_dp {
 
 	struct notifier_block edp_notifier;
 
+	/*
+	 * Pipe whose power sequencer is currently locked into
+	 * this port. Only relevant on VLV/CHV.
+	 */
+	enum pipe pps_pipe;
+
 	bool use_tps3;
 	bool can_mst; /* this port supports mst */
 	bool is_mst;
-- 
1.8.5.5

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

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

* [PATCH v3 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off
  2014-09-02 13:47       ` Imre Deak
@ 2014-09-04 11:54         ` ville.syrjala
  0 siblings, 0 replies; 63+ messages in thread
From: ville.syrjala @ 2014-09-04 11:54 UTC (permalink / raw)
  To: intel-gfx

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

The power sequencer loses its state when the disp2d power well is down.
Clear the dev_priv->pps_pipe tracking so that the power sequencer state
gets reinitialized the next time it's needed.

v2: Fix the pps_mutex vs. power_domain mutex deadlock by taking power
    domain reference first
v3: Rename from edp_pps_(un)lock() to just pps_(un)lock() for the future,
    update due to backlight code changes

Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c  | 161 +++++++++++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_drv.h |   1 +
 drivers/gpu/drm/i915/intel_pm.c  |   2 +
 3 files changed, 107 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 0dd0abd..a83fc19 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -290,6 +290,38 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
 					      struct intel_dp *intel_dp,
 					      struct edp_power_seq *out);
 
+static void pps_lock(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &intel_dig_port->base;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
+
+	/*
+	 * See vlv_power_sequencer_reset() why we need
+	 * a power domain reference here.
+	 */
+	power_domain = intel_display_port_power_domain(encoder);
+	intel_display_power_get(dev_priv, power_domain);
+
+	mutex_lock(&dev_priv->pps_mutex);
+}
+
+static void pps_unlock(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &intel_dig_port->base;
+	struct drm_device *dev = encoder->base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	enum intel_display_power_domain power_domain;
+
+	mutex_unlock(&dev_priv->pps_mutex);
+
+	power_domain = intel_display_port_power_domain(encoder);
+	intel_display_power_put(dev_priv, power_domain);
+}
+
 static enum pipe
 vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 {
@@ -389,6 +421,35 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 						      &power_seq);
 }
 
+void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv)
+{
+	struct drm_device *dev = dev_priv->dev;
+	struct intel_encoder *encoder;
+
+	if (WARN_ON(!IS_VALLEYVIEW(dev)))
+		return;
+
+	/*
+	 * We can't grab pps_mutex here due to deadlock with power_domain
+	 * mutex when power_domain functions are called while holding pps_mutex.
+	 * That also means that in order to use pps_pipe the code needs to
+	 * hold both a power domain reference and pps_mutex, and the power domain
+	 * reference get/put must be done while _not_ holding pps_mutex.
+	 * pps_{lock,unlock}() do these steps in the correct order, so one
+	 * should use them always.
+	 */
+
+	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
+		struct intel_dp *intel_dp;
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		intel_dp = enc_to_intel_dp(&encoder->base);
+		intel_dp->pps_pipe = INVALID_PIPE;
+	}
+}
+
 static u32 _pp_ctrl_reg(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -424,7 +485,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 	if (!is_edp(intel_dp) || code != SYS_RESTART)
 		return 0;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 
 	if (IS_VALLEYVIEW(dev)) {
 		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
@@ -440,7 +501,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
 		msleep(intel_dp->panel_power_cycle_delay);
 	}
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 
 	return 0;
 }
@@ -459,15 +520,10 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	struct intel_encoder *intel_encoder = &intel_dig_port->base;
-	enum intel_display_power_domain power_domain;
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	power_domain = intel_display_port_power_domain(intel_encoder);
-	return intel_display_power_enabled(dev_priv, power_domain) &&
-	       (I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD) != 0;
+	return I915_READ(_pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
 }
 
 static void
@@ -615,7 +671,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,
 	bool has_aux_irq = HAS_AUX_IRQ(dev);
 	bool vdd;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 
 	/*
 	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
@@ -732,7 +788,7 @@ out:
 	if (vdd)
 		edp_panel_vdd_off(intel_dp, false);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 
 	return ret;
 }
@@ -1313,16 +1369,14 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
-	struct drm_i915_private *dev_priv =
-		intel_dp_to_dev(intel_dp)->dev_private;
 	bool vdd;
 
 	if (!is_edp(intel_dp))
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 	vdd = edp_panel_vdd_on(intel_dp);
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 
 	WARN(!vdd, "eDP VDD already requested on\n");
 }
@@ -1371,13 +1425,11 @@ static void edp_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
 						 struct intel_dp, panel_vdd_work);
-	struct drm_i915_private *dev_priv =
-		intel_dp_to_dev(intel_dp)->dev_private;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 	if (!intel_dp->want_panel_vdd)
 		edp_panel_vdd_off_sync(intel_dp);
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 }
 
 static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
@@ -1415,15 +1467,12 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
 static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
-	struct drm_i915_private *dev_priv =
-		intel_dp_to_dev(intel_dp)->dev_private;
-
 	if (!is_edp(intel_dp))
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 	edp_panel_vdd_off(intel_dp, sync);
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 }
 
 void intel_edp_panel_on(struct intel_dp *intel_dp)
@@ -1438,7 +1487,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power on\n");
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 
 	if (edp_have_panel_power(intel_dp)) {
 		DRM_DEBUG_KMS("eDP power already on\n");
@@ -1473,7 +1522,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 	}
 
  out:
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 }
 
 void intel_edp_panel_off(struct intel_dp *intel_dp)
@@ -1491,7 +1540,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 
 	DRM_DEBUG_KMS("Turn eDP power off\n");
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 
 	WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n");
 
@@ -1515,7 +1564,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 	power_domain = intel_display_port_power_domain(intel_encoder);
 	intel_display_power_put(dev_priv, power_domain);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 }
 
 /* Enable backlight in the panel power control. */
@@ -1535,7 +1584,7 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 	 */
 	wait_backlight_on(intel_dp);
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 
 	pp = ironlake_get_pp_control(intel_dp);
 	pp |= EDP_BLC_ENABLE;
@@ -1545,7 +1594,7 @@ static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 }
 
 /* Enable backlight PWM and backlight PP control. */
@@ -1571,7 +1620,7 @@ static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
 	if (!is_edp(intel_dp))
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 
 	pp = ironlake_get_pp_control(intel_dp);
 	pp &= ~EDP_BLC_ENABLE;
@@ -1581,7 +1630,7 @@ static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
 	I915_WRITE(pp_ctrl_reg, pp);
 	POSTING_READ(pp_ctrl_reg);
 
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 
 	intel_dp->last_backlight_off = jiffies;
 	edp_wait_backlight_off(intel_dp);
@@ -1606,13 +1655,12 @@ void intel_edp_backlight_off(struct intel_dp *intel_dp)
 static void intel_edp_backlight_power(struct intel_connector *connector,
 				      bool enable)
 {
-	struct drm_i915_private *dev_priv = connector->base.dev->dev_private;
 	struct intel_dp *intel_dp = intel_attached_dp(&connector->base);
 	bool is_enabled;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 	is_enabled = ironlake_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 
 	if (is_enabled == enable)
 		return;
@@ -2336,18 +2384,19 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.head) {
 		struct intel_dp *intel_dp;
+		enum port port;
 
 		if (encoder->type != INTEL_OUTPUT_EDP)
 			continue;
 
 		intel_dp = enc_to_intel_dp(&encoder->base);
+		port = dp_to_dig_port(intel_dp)->port;
 
 		if (intel_dp->pps_pipe != pipe)
 			continue;
 
 		DRM_DEBUG_KMS("stealing pipe %c power sequencer from port %c\n",
-			      pipe_name(pipe),
-			      port_name(dp_to_dig_port(intel_dp)->port));
+			      pipe_name(pipe), port_name(port));
 
 		/* make sure vdd is off before we steal it */
 		edp_panel_vdd_off_sync(intel_dp);
@@ -2423,9 +2472,9 @@ static void vlv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		mutex_lock(&dev_priv->pps_mutex);
+		pps_lock(intel_dp);
 		vlv_init_panel_power_sequencer(intel_dp);
-		mutex_unlock(&dev_priv->pps_mutex);
+		pps_unlock(intel_dp);
 	}
 
 	intel_enable_dp(encoder);
@@ -2514,9 +2563,9 @@ static void chv_pre_enable_dp(struct intel_encoder *encoder)
 	mutex_unlock(&dev_priv->dpio_lock);
 
 	if (is_edp(intel_dp)) {
-		mutex_lock(&dev_priv->pps_mutex);
+		pps_lock(intel_dp);
 		vlv_init_panel_power_sequencer(intel_dp);
-		mutex_unlock(&dev_priv->pps_mutex);
+		pps_unlock(intel_dp);
 	}
 
 	intel_enable_dp(encoder);
@@ -4278,17 +4327,16 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	drm_dp_aux_unregister(&intel_dp->aux);
 	intel_dp_mst_encoder_cleanup(intel_dig_port);
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-		mutex_lock(&dev_priv->pps_mutex);
+		pps_lock(intel_dp);
 		edp_panel_vdd_off_sync(intel_dp);
-		mutex_unlock(&dev_priv->pps_mutex);
+		pps_unlock(intel_dp);
+
 		if (intel_dp->edp_notifier.notifier_call) {
 			unregister_reboot_notifier(&intel_dp->edp_notifier);
 			intel_dp->edp_notifier.notifier_call = NULL;
@@ -4300,15 +4348,13 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
-	struct drm_device *dev = intel_dp_to_dev(intel_dp);
-	struct drm_i915_private *dev_priv = dev->dev_private;
 
 	if (!is_edp(intel_dp))
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 	edp_panel_vdd_off_sync(intel_dp);
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 }
 
 static void intel_dp_encoder_reset(struct drm_encoder *encoder)
@@ -4793,9 +4839,10 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 	if (intel_encoder->type != INTEL_OUTPUT_EDP)
 		return;
 
-	mutex_lock(&dev_priv->pps_mutex);
-
 	intel_dp = enc_to_intel_dp(&intel_encoder->base);
+
+	pps_lock(intel_dp);
+
 	if (!edp_have_panel_vdd(intel_dp))
 		goto out;
 	/*
@@ -4810,7 +4857,7 @@ void intel_edp_panel_vdd_sanitize(struct intel_encoder *intel_encoder)
 
 	edp_panel_vdd_schedule_off(intel_dp);
  out:
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 }
 
 static bool intel_edp_init_connector(struct intel_dp *intel_dp,
@@ -4852,9 +4899,9 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 
 	/* We now know it's not a ghost, init power sequence regs. */
-	mutex_lock(&dev_priv->pps_mutex);
+	pps_lock(intel_dp);
 	intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, power_seq);
-	mutex_unlock(&dev_priv->pps_mutex);
+	pps_unlock(intel_dp);
 
 	mutex_lock(&dev->mode_config.mutex);
 	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
@@ -4989,15 +5036,15 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 	}
 
 	if (is_edp(intel_dp)) {
-		mutex_lock(&dev_priv->pps_mutex);
+		pps_lock(intel_dp);
 		if (IS_VALLEYVIEW(dev)) {
 			vlv_initial_power_sequencer_setup(intel_dp);
 		} else {
 			intel_dp_init_panel_power_timestamps(intel_dp);
 			intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 		}
+		pps_unlock(intel_dp);
 	}
-	mutex_unlock(&dev_priv->pps_mutex);
 
 	intel_dp_aux_init(intel_dp, intel_connector);
 
@@ -5012,9 +5059,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		drm_dp_aux_unregister(&intel_dp->aux);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-			mutex_lock(&dev_priv->pps_mutex);
+			pps_lock(intel_dp);
 			edp_panel_vdd_off_sync(intel_dp);
-			mutex_unlock(&dev_priv->pps_mutex);
+			pps_unlock(intel_dp);
 		}
 		drm_connector_unregister(connector);
 		drm_connector_cleanup(connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 1278b25..a505bf3 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -946,6 +946,7 @@ void intel_dp_mst_suspend(struct drm_device *dev);
 void intel_dp_mst_resume(struct drm_device *dev);
 int intel_dp_max_link_bw(struct intel_dp *intel_dp);
 void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
+void vlv_power_sequencer_reset(struct drm_i915_private *dev_priv);
 /* intel_dp_mst.c */
 int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
 void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 49af81f..45f71e6 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -6468,6 +6468,8 @@ static void vlv_display_power_well_disable(struct drm_i915_private *dev_priv,
 	spin_unlock_irq(&dev_priv->irq_lock);
 
 	vlv_set_power_well(dev_priv, power_well, false);
+
+	vlv_power_sequencer_reset(dev_priv);
 }
 
 static void vlv_dpio_cmn_power_well_enable(struct drm_i915_private *dev_priv,
-- 
1.8.5.5

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

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

* [PATCH v2 15/14] drm/i915: Add comments explaining the vdd on/off functions
  2014-09-03 11:52           ` Imre Deak
@ 2014-09-04 11:55             ` ville.syrjala
  2014-09-04 13:02               ` Daniel Vetter
  0 siblings, 1 reply; 63+ messages in thread
From: ville.syrjala @ 2014-09-04 11:55 UTC (permalink / raw)
  To: intel-gfx

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

Jani wanted some comments to explain why we call certain vdd on/off
functions in certain places.

v2: Make the comments more thorough (Imre)

Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/intel_dp.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e28610f..d8e868a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1349,6 +1349,11 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
 	return control;
 }
 
+/*
+ * Must be paired with edp_panel_vdd_off().
+ * Must hold pps_mutex around the whole on/off sequence.
+ * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
+ */
 static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1399,6 +1404,13 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 	return need_to_disable;
 }
 
+/*
+ * Must be paired with intel_edp_panel_vdd_off() or
+ * intel_edp_panel_off().
+ * Nested calls to these functions are not allowed since
+ * we drop the lock. Caller must use some higher level
+ * locking to prevent nested calls from other threads.
+ */
 void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
 	bool vdd;
@@ -1477,6 +1489,11 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
 	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
 }
 
+/*
+ * Must be paired with edp_panel_vdd_on().
+ * Must hold pps_mutex around the whole on/off sequence.
+ * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
+ */
 static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
 	struct drm_i915_private *dev_priv =
@@ -1497,6 +1514,12 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 		edp_panel_vdd_schedule_off(intel_dp);
 }
 
+/*
+ * Must be paired with intel_edp_panel_vdd_on().
+ * Nested calls to these functions are not allowed since
+ * we drop the lock. Caller must use some higher level
+ * locking to prevent nested calls from other threads.
+ */
 static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
 	if (!is_edp(intel_dp))
@@ -4390,6 +4413,10 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 	drm_encoder_cleanup(encoder);
 	if (is_edp(intel_dp)) {
 		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+		/*
+		 * vdd might still be enabled do to the delayed vdd off.
+		 * Make sure vdd is actually turned off here.
+		 */
 		pps_lock(intel_dp);
 		edp_panel_vdd_off_sync(intel_dp);
 		pps_unlock(intel_dp);
@@ -4409,6 +4436,10 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 	if (!is_edp(intel_dp))
 		return;
 
+	/*
+	 * vdd might still be enabled do to the delayed vdd off.
+	 * Make sure vdd is actually turned off here.
+	 */
 	pps_lock(intel_dp);
 	edp_panel_vdd_off_sync(intel_dp);
 	pps_unlock(intel_dp);
@@ -5116,6 +5147,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		drm_dp_aux_unregister(&intel_dp->aux);
 		if (is_edp(intel_dp)) {
 			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+			/*
+			 * vdd might still be enabled do to the delayed vdd off.
+			 * Make sure vdd is actually turned off here.
+			 */
 			pps_lock(intel_dp);
 			edp_panel_vdd_off_sync(intel_dp);
 			pps_unlock(intel_dp);
-- 
1.8.5.5

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

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

* Re: [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe
  2014-08-18 19:16 ` [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe ville.syrjala
  2014-09-02 13:52   ` Imre Deak
@ 2014-09-04 12:59   ` Daniel Vetter
  1 sibling, 0 replies; 63+ messages in thread
From: Daniel Vetter @ 2014-09-04 12:59 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Mon, Aug 18, 2014 at 10:16:06PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Try to make sure we find the power sequencer that the BIOS used
> by first looking for one which has the panel power enabled, then
> fall back to one with VDD force bit enabled, and finally look at
> just the port select bits. This should make us pick the correct
> power sequencer when the BIOS has already enabled the panel.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/intel_dp.c | 36 ++++++++++++++++++++++++++++++++++--
>  1 file changed, 34 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 4614e6e..4952783 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -341,9 +341,31 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  	return intel_dp->pps_pipe;
>  }
>  
> +typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
> +			       enum pipe pipe);
> +
> +static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
> +			       enum pipe pipe)
> +{
> +	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
> +}
> +
> +static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
> +				enum pipe pipe)
> +{
> +	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> +}
> +
> +static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> +			 enum pipe pipe)
> +{
> +	return true;
> +}
> +
>  static enum pipe
>  vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,

I've done a s/popwer_sequencer/pps/ here to make the lines fit. Might want
to roll that out in general perhaps, atm there's a mix of power_sequencer
and pps.
-Daniel

> -				 enum port port)
> +				 enum port port,
> +				 vlv_pipe_check pipe_check)
>  {
>  	enum pipe pipe;
>  
> @@ -354,6 +376,9 @@ vlv_initial_power_sequencer_pipe(struct drm_i915_private *dev_priv,
>  		if (port_sel != PANEL_PORT_SELECT_VLV(port))
>  			continue;
>  
> +		if (!pipe_check(dev_priv, pipe))
> +			continue;
> +
>  		return pipe;
>  	}
>  
> @@ -372,7 +397,14 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
>  	/* try to find a pipe with this port selected */
> -	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port);
> +	/* first pick one where the panel is on */
> +	intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_has_pp_on);
> +	/* didn't find one? pick one where vdd is on */
> +	if (intel_dp->pps_pipe == INVALID_PIPE)
> +		intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_has_vdd_on);
> +	/* didn't find one? pick one with just the correct port */
> +	if (intel_dp->pps_pipe == INVALID_PIPE)
> +		intel_dp->pps_pipe = vlv_initial_power_sequencer_pipe(dev_priv, port, vlv_pipe_any);
>  
>  	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
>  	if (intel_dp->pps_pipe == INVALID_PIPE) {
> -- 
> 1.8.5.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH v2 15/14] drm/i915: Add comments explaining the vdd on/off functions
  2014-09-04 11:55             ` [PATCH v2 " ville.syrjala
@ 2014-09-04 13:02               ` Daniel Vetter
  0 siblings, 0 replies; 63+ messages in thread
From: Daniel Vetter @ 2014-09-04 13:02 UTC (permalink / raw)
  To: ville.syrjala; +Cc: intel-gfx

On Thu, Sep 04, 2014 at 02:55:31PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Jani wanted some comments to explain why we call certain vdd on/off
> functions in certain places.
> 
> v2: Make the comments more thorough (Imre)
> 
> Reviewed-by: Imre Deak <imre.deak@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Ok, pulled them all, with two patches slightly frobbed to appease
checkpatch a bit.

Thanks, Daniel

> ---
>  drivers/gpu/drm/i915/intel_dp.c | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index e28610f..d8e868a 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1349,6 +1349,11 @@ static  u32 ironlake_get_pp_control(struct intel_dp *intel_dp)
>  	return control;
>  }
>  
> +/*
> + * Must be paired with edp_panel_vdd_off().
> + * Must hold pps_mutex around the whole on/off sequence.
> + * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> + */
>  static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
>  	struct drm_device *dev = intel_dp_to_dev(intel_dp);
> @@ -1399,6 +1404,13 @@ static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  	return need_to_disable;
>  }
>  
> +/*
> + * Must be paired with intel_edp_panel_vdd_off() or
> + * intel_edp_panel_off().
> + * Nested calls to these functions are not allowed since
> + * we drop the lock. Caller must use some higher level
> + * locking to prevent nested calls from other threads.
> + */
>  void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
>  	bool vdd;
> @@ -1477,6 +1489,11 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
>  	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
>  }
>  
> +/*
> + * Must be paired with edp_panel_vdd_on().
> + * Must hold pps_mutex around the whole on/off sequence.
> + * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> + */
>  static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  {
>  	struct drm_i915_private *dev_priv =
> @@ -1497,6 +1514,12 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  		edp_panel_vdd_schedule_off(intel_dp);
>  }
>  
> +/*
> + * Must be paired with intel_edp_panel_vdd_on().
> + * Nested calls to these functions are not allowed since
> + * we drop the lock. Caller must use some higher level
> + * locking to prevent nested calls from other threads.
> + */
>  static void intel_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  {
>  	if (!is_edp(intel_dp))
> @@ -4390,6 +4413,10 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  	drm_encoder_cleanup(encoder);
>  	if (is_edp(intel_dp)) {
>  		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +		/*
> +		 * vdd might still be enabled do to the delayed vdd off.
> +		 * Make sure vdd is actually turned off here.
> +		 */
>  		pps_lock(intel_dp);
>  		edp_panel_vdd_off_sync(intel_dp);
>  		pps_unlock(intel_dp);
> @@ -4409,6 +4436,10 @@ static void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>  	if (!is_edp(intel_dp))
>  		return;
>  
> +	/*
> +	 * vdd might still be enabled do to the delayed vdd off.
> +	 * Make sure vdd is actually turned off here.
> +	 */
>  	pps_lock(intel_dp);
>  	edp_panel_vdd_off_sync(intel_dp);
>  	pps_unlock(intel_dp);
> @@ -5116,6 +5147,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
>  		drm_dp_aux_unregister(&intel_dp->aux);
>  		if (is_edp(intel_dp)) {
>  			cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +			/*
> +			 * vdd might still be enabled do to the delayed vdd off.
> +			 * Make sure vdd is actually turned off here.
> +			 */
>  			pps_lock(intel_dp);
>  			edp_panel_vdd_off_sync(intel_dp);
>  			pps_unlock(intel_dp);
> -- 
> 1.8.5.5
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

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

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-08-26 14:06           ` Ville Syrjälä
@ 2014-09-04 17:47             ` Clint Taylor
  2014-09-05  8:23               ` Ville Syrjälä
  0 siblings, 1 reply; 63+ messages in thread
From: Clint Taylor @ 2014-09-04 17:47 UTC (permalink / raw)
  To: Ville Syrjälä, Daniel Vetter; +Cc: intel-gfx

On 08/26/2014 07:06 AM, Ville Syrjälä wrote:
> On Tue, Aug 26, 2014 at 03:36:07PM +0200, Daniel Vetter wrote:
>> On Tue, Aug 26, 2014 at 04:21:00PM +0300, Jani Nikula wrote:
>>> On Tue, 26 Aug 2014, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
>>>> On Tue, Aug 19, 2014 at 10:00:55AM +0300, Jani Nikula wrote:
>>>>> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
>>>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>>>>
>>>>>> Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
>>>>>> and flatten the rest of the function.
>>>>>
>>>>> Please imagine adding another platform there, and realize this just adds
>>>>> unnecessary churn.
>>>>
>>>> I'd just add another reboot notifier then.
>>>
>>> Fair enough; it should be vlv_edp_notify_handler then. (No, don't send a
>>> patch to change that! ;)
>>>
>>>> Frankly I don't understand the current one either. Why does it need to
>>>> set the delay to max for instance? And does this mean that the
>>>> PANEL_POWER_RESET bit doesn't actually work as advertised in the docs?
>>>
>>> *shrug* experimental evidence?
>>>
>>> commit 01527b3127997ef6370d5ad4fa25d96847fbf12a
>>> Author: Clint Taylor <clinton.a.taylor@intel.com>
>>> Date:   Mon Jul 7 13:01:46 2014 -0700
>>>
>>>      drm/i915/vlv: T12 eDP panel timing enforcement during reboot
>>>
>>>      The panel power sequencer on vlv doesn't appear to accept changes to its
>>>      T12 power down duration during warm reboots. This change forces a delay
>>>      for warm reboots to the T12 panel timing as defined in the VBT table for
>>>      the connected panel.
>>
>> So if I remember this piece of lore correctly in the past the pp was
>> pessimistic, and enforced this delay on resume/boot-up, assuming you've
>> shut down _right_ before the machine was lit up again. Apparently people
>> where unhappy with that enforced delay and it was ditched on vlv, but then
>> it broke panels if you actually managed to reboot quickly enough.
>
> IIRC the way the reset bit is documented the hardware itself is supposed
> to initiate the power off cycle when it gets some reset notification and
> it should enforce the timing before allowing the panel power to be
> re-enabled. Although it does seem that it would also reset the
> "power cycle delay" so it would maybe only enforce some default delay in
> that case (300ms based on the documented default value of 0x4). So if the
> panel requires more than the 300ms then I understand the msleep() here.
> I guess use of the VDD force bit just after reset might also require that
> we do the power down + wait before reset. So that part does make sense
> to me, but I still don't understand the "power cycle delay"=0x1f part.
>
All eDP panels require at least 500ms according to the eDP 
specifications T12 minimum of 500ms. The panel manufacturer's 
specifications I have seen also have a 500ms minimum. Is the default 
register value of 4 relevant for LVDS?

 From our testing on VLV the PPS starts immediately upon ungate of the 
display block. There is no way to stop or alter this sequence that 
starts with the default value (4) in the register. The panel power will 
assert at the end of the sequence. Without the msleep() adding time a 
quick rebooting platform will not meet the 500ms minimum.

"power cycle delay" of 0x1f was added to prevent LCD_VDD from asserting 
before the reboot actually completes which includes the msleep() time. 
The "power cycle delay" value could be computed based on the T12 time in 
the VBT. Just setting the highest value made sense for simplicity and 
the fact the value is reset to default during the reboot.

The "PANEL_POWER_RESET bit doesn't actually work as advertised" 
statement was probably in error based on my understanding of the PPS at 
the time the patch was made.

Clint

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

* Re: [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier
  2014-09-04 17:47             ` Clint Taylor
@ 2014-09-05  8:23               ` Ville Syrjälä
  0 siblings, 0 replies; 63+ messages in thread
From: Ville Syrjälä @ 2014-09-05  8:23 UTC (permalink / raw)
  To: Clint Taylor; +Cc: intel-gfx

On Thu, Sep 04, 2014 at 10:47:41AM -0700, Clint Taylor wrote:
> On 08/26/2014 07:06 AM, Ville Syrjälä wrote:
> > On Tue, Aug 26, 2014 at 03:36:07PM +0200, Daniel Vetter wrote:
> >> On Tue, Aug 26, 2014 at 04:21:00PM +0300, Jani Nikula wrote:
> >>> On Tue, 26 Aug 2014, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> >>>> On Tue, Aug 19, 2014 at 10:00:55AM +0300, Jani Nikula wrote:
> >>>>> On Mon, 18 Aug 2014, ville.syrjala@linux.intel.com wrote:
> >>>>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >>>>>>
> >>>>>> Move the vlv_power_sequencer_pipe() after the IS_VALLEYVIEW() check
> >>>>>> and flatten the rest of the function.
> >>>>>
> >>>>> Please imagine adding another platform there, and realize this just adds
> >>>>> unnecessary churn.
> >>>>
> >>>> I'd just add another reboot notifier then.
> >>>
> >>> Fair enough; it should be vlv_edp_notify_handler then. (No, don't send a
> >>> patch to change that! ;)
> >>>
> >>>> Frankly I don't understand the current one either. Why does it need to
> >>>> set the delay to max for instance? And does this mean that the
> >>>> PANEL_POWER_RESET bit doesn't actually work as advertised in the docs?
> >>>
> >>> *shrug* experimental evidence?
> >>>
> >>> commit 01527b3127997ef6370d5ad4fa25d96847fbf12a
> >>> Author: Clint Taylor <clinton.a.taylor@intel.com>
> >>> Date:   Mon Jul 7 13:01:46 2014 -0700
> >>>
> >>>      drm/i915/vlv: T12 eDP panel timing enforcement during reboot
> >>>
> >>>      The panel power sequencer on vlv doesn't appear to accept changes to its
> >>>      T12 power down duration during warm reboots. This change forces a delay
> >>>      for warm reboots to the T12 panel timing as defined in the VBT table for
> >>>      the connected panel.
> >>
> >> So if I remember this piece of lore correctly in the past the pp was
> >> pessimistic, and enforced this delay on resume/boot-up, assuming you've
> >> shut down _right_ before the machine was lit up again. Apparently people
> >> where unhappy with that enforced delay and it was ditched on vlv, but then
> >> it broke panels if you actually managed to reboot quickly enough.
> >
> > IIRC the way the reset bit is documented the hardware itself is supposed
> > to initiate the power off cycle when it gets some reset notification and
> > it should enforce the timing before allowing the panel power to be
> > re-enabled. Although it does seem that it would also reset the
> > "power cycle delay" so it would maybe only enforce some default delay in
> > that case (300ms based on the documented default value of 0x4). So if the
> > panel requires more than the 300ms then I understand the msleep() here.
> > I guess use of the VDD force bit just after reset might also require that
> > we do the power down + wait before reset. So that part does make sense
> > to me, but I still don't understand the "power cycle delay"=0x1f part.
> >
> All eDP panels require at least 500ms according to the eDP 
> specifications T12 minimum of 500ms. The panel manufacturer's 
> specifications I have seen also have a 500ms minimum. Is the default 
> register value of 4 relevant for LVDS?

IIRC I saw 400ms mentioned for LVDS somewhere, so I have no idea why
someone made the default 300ms. Not that I actaully verified that the
reset valus is indeed 4 on actual hardware, I just read it from the spec.

>  From our testing on VLV the PPS starts immediately upon ungate of the 
> display block. There is no way to stop or alter this sequence that 
> starts with the default value (4) in the register. The panel power will 
> assert at the end of the sequence. Without the msleep() adding time a 
> quick rebooting platform will not meet the 500ms minimum.

Ok so I guess in theory we could do msleep(whatever-300) and we should
still meet the panel timings, assuming we care to optimize a few hunder
ms here.

> 
> "power cycle delay" of 0x1f was added to prevent LCD_VDD from asserting 
> before the reboot actually completes which includes the msleep() time. 
> The "power cycle delay" value could be computed based on the T12 time in 
> the VBT. Just setting the highest value made sense for simplicity and 
> the fact the value is reset to default during the reboot.

At that point we should have the correct t11_t12 delay programmed into the
register already. Also it shouldn't really matter what we have in there
because of the msleep(). By the time the msleep() is done and we reboot,
the register gets reset to defaul anyway, and it should be OK to enable
VDD again, even immediately rather than after the default 300ms since we
already slept for the entire power cycle delay before rebooting.

> The "PANEL_POWER_RESET bit doesn't actually work as advertised" 
> statement was probably in error based on my understanding of the PPS at 
> the time the patch was made.

OK, so I guess it sort of works then, except since it resets the power cycle
delay to 300ms it waits for less than it should. So yeah seems we do
need the manual sleep to make sure we don't violate the panel timings. I
guess we should then add the reboot notifier for all platforms since
this power sequencer reset behaviour isn't specific to VLV.

-- 
Ville Syrjälä
Intel OTC

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

end of thread, other threads:[~2014-09-05  8:23 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-18 19:15 [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick ville.syrjala
2014-08-18 19:15 ` [PATCH 01/14] drm/i915: Parametrize PANEL_PORT_SELECT_VLV ville.syrjala
2014-08-19  6:58   ` Jani Nikula
2014-08-18 19:15 ` [PATCH 02/14] drm/i915: Reorganize vlv eDP reboot notifier ville.syrjala
2014-08-18 21:28   ` Clint Taylor
2014-08-19  7:00   ` Jani Nikula
2014-08-26 12:58     ` Ville Syrjälä
2014-08-26 13:21       ` Jani Nikula
2014-08-26 13:30         ` Ville Syrjälä
2014-08-26 13:36         ` Daniel Vetter
2014-08-26 14:06           ` Ville Syrjälä
2014-09-04 17:47             ` Clint Taylor
2014-09-05  8:23               ` Ville Syrjälä
2014-08-18 19:15 ` [PATCH 03/14] drm/i915: Use intel_edp_panel_vdd_on() in intel_dp_probe_mst() ville.syrjala
2014-08-19  7:12   ` Jani Nikula
2014-08-18 19:15 ` [PATCH 04/14] drm/i915: Rename edp vdd funcs for consistency ville.syrjala
2014-08-19  7:20   ` Jani Nikula
2014-08-19 10:24     ` [PATCH v2 " ville.syrjala
2014-08-18 19:16 ` [PATCH 05/14] drm/i915: Add a note explaining vdd on/off handling in intel_dp_aux_ch() ville.syrjala
2014-08-19  7:07   ` Jani Nikula
2014-08-18 19:16 ` [PATCH 06/14] drm/i915: Replace big nested if block with early return ville.syrjala
2014-08-19  7:24   ` Jani Nikula
2014-08-18 19:16 ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() ville.syrjala
2014-08-19  7:36   ` Jani Nikula
2014-08-19 10:39     ` Ville Syrjälä
2014-08-19 13:37       ` Jani Nikula
2014-08-19 17:47         ` [PATCH 15/14] drm/i915: Add comments explaining the vdd on/off functions ville.syrjala
2014-09-03 11:52           ` Imre Deak
2014-09-04 11:55             ` [PATCH v2 " ville.syrjala
2014-09-04 13:02               ` Daniel Vetter
2014-08-26  9:21         ` [PATCH 07/14] drm/i915: Warn about want_panel_vdd in edp_panel_vdd_off_sync() Daniel Vetter
2014-08-18 19:16 ` [PATCH 08/14] drm/i915: Flatten intel_edp_panel_vdd_on() ville.syrjala
2014-08-19  7:30   ` Jani Nikula
2014-08-19 10:49     ` Ville Syrjälä
2014-08-18 19:16 ` [PATCH 09/14] drm/i915: Fix edp vdd locking ville.syrjala
2014-08-19 17:32   ` [PATCH v2 " ville.syrjala
2014-09-02 13:07     ` Imre Deak
2014-09-04 11:53       ` [PATCH v3 " ville.syrjala
2014-08-18 19:16 ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer ville.syrjala
2014-08-19 17:45   ` [PATCH 10.1/14] drm/i915: Reset power sequencer pipe tracking when disp2d is off ville.syrjala
2014-08-22 14:21     ` [PATCH v2 " ville.syrjala
2014-09-02 13:47       ` Imre Deak
2014-09-04 11:54         ` [PATCH v3 " ville.syrjala
2014-09-01 11:19   ` [PATCH 10/14] drm/i915: Track which port is using which pipe's power sequencer Antti Koskipää
2014-09-04 11:54   ` [PATCH v2 " ville.syrjala
2014-08-18 19:16 ` [PATCH 11/14] drm/i915: Be more careful when picking the initial power sequencer pipe ville.syrjala
2014-09-02 13:52   ` Imre Deak
2014-09-04 12:59   ` Daniel Vetter
2014-08-18 19:16 ` [PATCH 12/14] drm/i915: Turn on panel power before doing aux transfers ville.syrjala
2014-08-19  7:33   ` Jani Nikula
2014-08-19 10:57     ` Ville Syrjälä
2014-08-26 12:41       ` Daniel Vetter
2014-09-02 14:02   ` Imre Deak
2014-08-18 19:16 ` [PATCH 13/14] drm/i915: Enable DP port earlier ville.syrjala
2014-09-03 11:02   ` Imre Deak
2014-08-18 19:16 ` [PATCH 14/14] drm/i915: Move DP port disable to post_disable for pch platforms ville.syrjala
2014-08-26  9:43   ` Daniel Vetter
2014-09-03 11:20   ` Imre Deak
2014-08-19  7:45 ` [PATCH 00/14] drm/i915: edp vdd locking and prep for power sequencer kick Jani Nikula
2014-08-26  9:37   ` Daniel Vetter
2014-08-19  8:08 ` Jani Nikula
2014-08-19 10:46   ` Ville Syrjälä
2014-08-26  9:35     ` Daniel Vetter

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