[PATCH] drm/amd/display: Handle removed connector in early_unregister

Fangzhi Zuo Jerry.Zuo at amd.com
Thu Feb 3 17:47:59 UTC 2022


From: Wayne Lin <Wayne.Lin at amd.com>

This patch lived in our internal branch since August
but somehow missed the merge to upstream.

Original Patch:
(dc: Handle removed connector in early_unregister)

Signed-off-by: Wayne Lin <Wayne.Lin at amd.com>
Signed-off-by: Fangzhi Zuo <Jerry.Zuo at amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  7 ++++
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   | 41 +++++++++++++++++--
 .../gpu/drm/amd/display/dc/core/dc_stream.c   | 12 ++++++
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |  1 +
 4 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f5941e59e5ad..529b3ddaa10b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3034,6 +3034,7 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
 	struct drm_connector *connector = &aconnector->base;
 	struct drm_device *dev = connector->dev;
 	enum dc_connection_type new_connection_type = dc_connection_none;
+	enum dc_connection_type old_connection_type = aconnector->dc_link->type;
 	struct amdgpu_device *adev = drm_to_adev(dev);
 	struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state);
 	struct dm_crtc_state *dm_crtc_state = NULL;
@@ -3074,7 +3075,13 @@ static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector)
 			drm_kms_helper_hotplug_event(dev);
 
 	} else if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) {
+		/**
+		 * MST cases are handled within .early_unregister where we
+		 * can handle disconnected conectors reported by long HPD
+		 * and CSN.
+		 */
 		if (new_connection_type == dc_connection_none &&
+			old_connection_type != dc_connection_mst_branch &&
 		    aconnector->dc_link->type == dc_connection_none &&
 		    dm_crtc_state)
 			dm_set_dpms_off(aconnector->dc_link, dm_crtc_state);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index 8e97d21bdf5c..7cd1f1f57d6e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -139,11 +139,46 @@ amdgpu_dm_mst_connector_late_register(struct drm_connector *connector)
 static void
 amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector)
 {
-	struct amdgpu_dm_connector *amdgpu_dm_connector =
-		to_amdgpu_dm_connector(connector);
-	struct drm_dp_mst_port *port = amdgpu_dm_connector->port;
+	struct amdgpu_dm_connector *aconnector =
+                to_amdgpu_dm_connector(connector);
+	struct drm_dp_mst_port *port = aconnector->port;
+	struct dc_stream_update stream_update;
+	struct dc_stream_state *stream_state;
+	struct drm_device *ddev = aconnector->base.dev;
+	struct amdgpu_device *adev = drm_to_adev(ddev);
+	struct dc_link *dc_link = aconnector->dc_link;
+	struct dc_sink *dc_sink = aconnector->dc_sink;
+	bool dpms_off = true;
 
 	drm_dp_mst_connector_early_unregister(connector, port);
+
+	ASSERT(dc_link);
+
+	if (dc_sink) {
+		mutex_lock(&ddev->mode_config.mutex);
+		mutex_lock(&adev->dm.dc_lock);
+
+		memset(&stream_update, 0, sizeof(stream_update));
+		stream_update.dpms_off = &dpms_off;
+
+		/*set stream dpms_off*/
+		stream_state = dc_stream_get_stream_by_sink(dc_sink);
+		if (stream_state != NULL) {
+				stream_update.stream = stream_state;
+				dc_commit_updates_for_stream(stream_state->ctx->dc, NULL, 0,
+										stream_state, &stream_update,
+										stream_state->ctx->dc->current_state);
+		}
+
+		/*clear the remote sink of the link*/
+		dc_link_remove_remote_sink(dc_link, dc_sink);
+		dc_sink_release(dc_sink);
+		aconnector->dc_sink = NULL;
+
+		mutex_unlock(&adev->dm.dc_lock);
+		mutex_unlock(&ddev->mode_config.mutex);
+	}
+
 }
 
 static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 57cf4cb82370..a77c90c14e85 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -739,3 +739,15 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
 			stream->link->link_index);
 }
 
+struct dc_stream_state *dc_stream_get_stream_by_sink(struct dc_sink *sink)
+{
+	uint8_t i;
+	struct dc_context *ctx = sink->ctx;
+
+	for (i = 0; i < ctx->dc->current_state->stream_count; i++) {
+		if (ctx->dc->current_state->streams[i]->sink == sink)
+			return ctx->dc->current_state->streams[i];
+	}
+
+	return NULL;
+}
\ No newline at end of file
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index f631b61abedd..89f67c711161 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -321,6 +321,7 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream);
 uint8_t dc_get_current_stream_count(struct dc *dc);
 struct dc_stream_state *dc_get_stream_at_index(struct dc *dc, uint8_t i);
 struct dc_stream_state *dc_stream_find_from_link(const struct dc_link *link);
+struct dc_stream_state *dc_stream_get_stream_by_sink(struct dc_sink *sink);
 
 /*
  * Return the current frame counter.
-- 
2.25.1



More information about the amd-gfx mailing list