[PATCH 7/7] drm/display/dp: Fix MST disable sequences

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The disable sequence after wait for transcoder off was not correctly
implemented.
The MST disable sequence is basically the same for HSW, SKL, ICL and
TGL, with just minor changes on TGL.

So here calling a new MST function to do the MST sequences, most of
the steps just moved from the post disable hook.

This plus the previous changes, fixed the hotplugs triggered by MST
sink during the disable/enable sequence, those were causing source to
try to do a link training while it was not ready causing CPU pipe
FIFO underrrus on TGL.

BSpec: 4231
BSpec: 4163
BSpec: 22243
BSpec: 49190
Cc: Lucas De Marchi <lucas.demarchi@xxxxxxxxx>
Signed-off-by: José Roberto de Souza <jose.souza@xxxxxxxxx>
---
 drivers/gpu/drm/i915/display/intel_ddi.c     | 25 +++++--
 drivers/gpu/drm/i915/display/intel_display.c |  2 +
 drivers/gpu/drm/i915/display/intel_dp_mst.c  | 78 ++++++++++++++++----
 drivers/gpu/drm/i915/display/intel_dp_mst.h  |  2 +
 4 files changed, 87 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index aa0249333175..5950bc1ccc88 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -34,6 +34,7 @@
 #include "intel_ddi.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_dp_mst.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
 #include "intel_dpio_phy.h"
@@ -1954,17 +1955,27 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state
 	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
 	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
 	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
-	i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);
-	u32 val = I915_READ(reg);
+	u32 val;
+
+	val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+	val &= ~TRANS_DDI_FUNC_ENABLE;
 
 	if (INTEL_GEN(dev_priv) >= 12) {
-		val &= ~(TRANS_DDI_FUNC_ENABLE | TGL_TRANS_DDI_PORT_MASK |
-			 TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
+		if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST)) {
+			val &= ~TGL_TRANS_DDI_PORT_MASK;
+		} else {
+			struct intel_encoder *encoder;
+			enum transcoder master;
+
+			encoder = intel_ddi_get_crtc_encoder(crtc);
+			master = intel_dp_mst_master_trans_get(encoder);
+			if (crtc_state->cpu_transcoder != master)
+				val &= ~TGL_TRANS_DDI_PORT_MASK;
+		}
 	} else {
-		val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK |
-			 TRANS_DDI_DP_VC_PAYLOAD_ALLOC);
+		val &= ~TRANS_DDI_PORT_MASK;
 	}
-	I915_WRITE(reg, val);
+	I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), val);
 
 	if (dev_priv->quirks & QUIRK_INCREASE_DDI_DISABLED_TIME &&
 	    intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 35a59108194e..e81b3d731c16 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -6843,6 +6843,8 @@ static void haswell_crtc_disable(struct intel_atomic_state *state,
 	if (!transcoder_is_dsi(cpu_transcoder))
 		intel_disable_pipe(old_crtc_state);
 
+	intel_dp_mst_post_trans_disabled(old_crtc_state);
+
 	if (INTEL_GEN(dev_priv) >= 11)
 		icl_disable_transcoder_port_sync(old_crtc_state);
 
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 53afe3e179f7..dc5e372bc32b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -360,6 +360,57 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder,
 					  old_crtc_state, old_conn_state);
 }
 
+static void
+dp_mst_post_trans_disabled(struct intel_encoder *encoder,
+			   const struct intel_crtc_state *old_crtc_state,
+			   const struct drm_connector_state *old_conn_state)
+{
+	struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
+	struct intel_digital_port *intel_dig_port = intel_mst->primary;
+	struct intel_dp *intel_dp = &intel_dig_port->dp;
+	struct intel_connector *connector =
+		to_intel_connector(old_conn_state->connector);
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	u32 val;
+
+	drm_dp_update_payload_part2(&intel_dp->mst_mgr);
+
+	val = I915_READ(TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder));
+	val &= ~TRANS_DDI_DP_VC_PAYLOAD_ALLOC;
+	I915_WRITE(TRANS_DDI_FUNC_CTL(old_crtc_state->cpu_transcoder), val);
+
+	if (intel_de_wait_for_set(dev_priv, intel_dp->regs.dp_tp_status,
+				  DP_TP_STATUS_ACT_SENT, 1))
+		DRM_ERROR("Timed out waiting for ACT sent when disabling\n");
+
+	drm_dp_check_act_status(&intel_dp->mst_mgr);
+
+	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port);
+}
+
+void
+intel_dp_mst_post_trans_disabled(const struct intel_crtc_state *old_crtc_state)
+{
+	struct drm_atomic_state *state = old_crtc_state->uapi.state;
+	struct drm_connector_state *old_conn_state;
+	struct drm_connector *conn;
+	int i;
+
+	if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST))
+		return;
+
+	for_each_old_connector_in_state(state, conn, old_conn_state, i) {
+		struct intel_encoder *encoder;
+
+		if (old_conn_state->crtc != old_crtc_state->uapi.crtc)
+			continue;
+
+		encoder = to_intel_encoder(old_conn_state->best_encoder);
+		dp_mst_post_trans_disabled(encoder, old_crtc_state,
+					   old_conn_state);
+	}
+}
+
 static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
 				      const struct intel_crtc_state *old_crtc_state,
 				      const struct drm_connector_state *old_conn_state)
@@ -373,6 +424,12 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
 
 	intel_dp->active_mst_links--;
 
+	/*
+	 * Power down mst path before disabling the port, otherwise we end
+	 * up getting interrupts from the sink upon detecting link loss.
+	 */
+	drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
+				     false);
 	/*
 	 * From TGL BSpec "If multi-stream slave transcoder: Configure
 	 * Transcoder Clock Select to direct no clock to the transcoder"
@@ -383,22 +440,17 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder,
 	if (INTEL_GEN(dev_priv) < 12 || intel_dp->active_mst_links)
 		intel_ddi_disable_pipe_clock(old_crtc_state);
 
-	/* this can fail */
-	drm_dp_check_act_status(&intel_dp->mst_mgr);
-	/* and this can also fail */
-	drm_dp_update_payload_part2(&intel_dp->mst_mgr);
-
-	drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port);
-
-	/*
-	 * Power down mst path before disabling the port, otherwise we end
-	 * up getting interrupts from the sink upon detecting link loss.
-	 */
-	drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
-				     false);
 
 	intel_mst->connector = NULL;
 	if (intel_dp->active_mst_links == 0) {
+		enum transcoder cpu_transcoder;
+		u32 val;
+
+		cpu_transcoder = old_crtc_state->cpu_transcoder;
+		val = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));
+		val &= ~TGL_TRANS_DDI_PORT_MASK;
+		I915_WRITE(TRANS_DDI_FUNC_CTL(cpu_transcoder), val);
+
 		intel_dig_port->base.post_disable(&intel_dig_port->base,
 						  old_crtc_state, NULL);
 		intel_dp->mst_master_transcoder = INVALID_TRANSCODER;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.h b/drivers/gpu/drm/i915/display/intel_dp_mst.h
index e6f28a517182..567873c0ac91 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.h
@@ -7,11 +7,13 @@
 #define __INTEL_DP_MST_H__
 
 struct intel_digital_port;
+struct intel_crtc_state;
 struct intel_encoder;
 
 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);
 int intel_dp_mst_encoder_active_links(struct intel_digital_port *intel_dig_port);
+void intel_dp_mst_post_trans_disabled(const struct intel_crtc_state *old_crtc_state);
 enum transcoder intel_dp_mst_master_trans_get(struct intel_encoder *encoder);
 
 #endif /* __INTEL_DP_MST_H__ */
-- 
2.24.0

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




[Index of Archives]     [AMD Graphics]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux