From: Wayne Lin <Wayne.Lin@xxxxxxx> 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@xxxxxxx> Signed-off-by: Fangzhi Zuo <Jerry.Zuo@xxxxxxx> --- .../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