[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