diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 48ab51533d5d6..841cc051b7d01 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3298,9 +3298,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) write_i2c_redriver_setting(pipe_ctx, false); } } - dc->hwss.disable_stream(pipe_ctx); disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); + + dc->hwss.disable_stream(pipe_ctx); + if (pipe_ctx->stream->timing.flags.DSC) { if (dc_is_dp_signal(pipe_ctx->stream->signal)) dp_set_dsc_enable(pipe_ctx, false); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 91cd884d6f257..6124af571bff6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1102,6 +1102,10 @@ static inline enum link_training_result perform_link_training_int( dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE; dpcd_set_training_pattern(link, dpcd_pattern); + /* delay 5ms after notifying sink of idle pattern before switching output */ + if (link->connector_signal != SIGNAL_TYPE_EDP) + msleep(5); + /* 4. mainlink output idle pattern*/ dp_set_hw_test_pattern(link, DP_TEST_PATTERN_VIDEO_MODE, NULL, 0); @@ -1551,6 +1555,12 @@ bool perform_link_training_with_retries( struct dc_link *link = stream->link; enum dp_panel_mode panel_mode = dp_get_panel_mode(link); + /* We need to do this before the link training to ensure the idle pattern in SST + * mode will be sent right after the link training + */ + link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, + pipe_ctx->stream_res.stream_enc->id, true); + for (j = 0; j < attempts; ++j) { dp_enable_link_phy( @@ -1567,12 +1577,6 @@ bool perform_link_training_with_retries( dp_set_panel_mode(link, panel_mode); - /* We need to do this before the link training to ensure the idle pattern in SST - * mode will be sent right after the link training - */ - link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc, - pipe_ctx->stream_res.stream_enc->id, true); - if (link->aux_access_disabled) { dc_link_dp_perform_link_training_skip_aux(link, link_setting); return true; diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b77e9dc160863..2af1d74d16ad8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1069,8 +1069,17 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx) link->dc->hwss.set_abm_immediate_disable(pipe_ctx); } - if (dc_is_dp_signal(pipe_ctx->stream->signal)) + if (dc_is_dp_signal(pipe_ctx->stream->signal)) { pipe_ctx->stream_res.stream_enc->funcs->dp_blank(pipe_ctx->stream_res.stream_enc); + + /* + * After output is idle pattern some sinks need time to recognize the stream + * has changed or they enter protection state and hang. + */ + if (!dc_is_embedded_signal(pipe_ctx->stream->signal)) + msleep(60); + } + }