diff options
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4673-drm-amd-display-Reset-PHY-in-link-re-training.patch')
-rw-r--r-- | meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4673-drm-amd-display-Reset-PHY-in-link-re-training.patch | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4673-drm-amd-display-Reset-PHY-in-link-re-training.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4673-drm-amd-display-Reset-PHY-in-link-re-training.patch new file mode 100644 index 00000000..6b893f04 --- /dev/null +++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4673-drm-amd-display-Reset-PHY-in-link-re-training.patch @@ -0,0 +1,222 @@ +From 82e02f0a49cee28db7f5c7f222e03ab31527e8be Mon Sep 17 00:00:00 2001 +From: Paul Hsieh <paul.hsieh@amd.com> +Date: Fri, 1 Nov 2019 14:41:37 +0800 +Subject: [PATCH 4673/4736] drm/amd/display: Reset PHY in link re-training + +[Why] +Link training failed randomly when plugging USB-C display in/out. + +[How] +If link training failed, reset PHY in link re-training. + +Change-Id: Ic0f8c50e5da346777e96fa73f1137e6c4abef9f2 +Signed-off-by: Paul Hsieh <paul.hsieh@amd.com> +Reviewed-by: Wenjing Liu <Wenjing.Liu@amd.com> +Acked-by: Leo Li <sunpeng.li@amd.com> +--- + drivers/gpu/drm/amd/display/dc/core/dc_link.c | 31 ++------- + .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 68 +++++++++++++++---- + .../drm/amd/display/dc/core/dc_link_hwss.c | 14 +--- + .../gpu/drm/amd/display/dc/inc/dc_link_dp.h | 5 +- + 4 files changed, 66 insertions(+), 52 deletions(-) + +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 9f53cbcc7152..1c056a687161 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c +@@ -1529,40 +1529,17 @@ static enum dc_status enable_link_dp( + if (state->clk_mgr && !apply_seamless_boot_optimization) + state->clk_mgr->funcs->update_clocks(state->clk_mgr, state, false); + +- dp_enable_link_phy( +- link, +- pipe_ctx->stream->signal, +- pipe_ctx->clock_source->id, +- &link_settings); +- +- if (stream->sink_patches.dppowerup_delay > 0) { +- int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay; +- +- msleep(delay_dp_power_up_in_ms); +- } +- +- panel_mode = dp_get_panel_mode(link); +- 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); + skip_video_pattern = true; + + if (link_settings.link_rate == LINK_RATE_LOW) + skip_video_pattern = false; + +- if (link->aux_access_disabled) { +- dc_link_dp_perform_link_training_skip_aux(link, &link_settings); +- +- link->cur_link_settings = link_settings; +- status = DC_OK; +- } else if (perform_link_training_with_retries( +- link, ++ if (perform_link_training_with_retries( + &link_settings, + skip_video_pattern, +- LINK_TRAINING_ATTEMPTS)) { ++ LINK_TRAINING_ATTEMPTS, ++ pipe_ctx, ++ pipe_ctx->stream->signal)) { + link->cur_link_settings = link_settings; + status = DC_OK; + } +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 272261192e82..537b4dee8f22 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 +@@ -1433,23 +1433,58 @@ enum link_training_result dc_link_dp_perform_link_training( + } + + bool perform_link_training_with_retries( +- struct dc_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern, +- int attempts) ++ int attempts, ++ struct pipe_ctx *pipe_ctx, ++ enum signal_type signal) + { + uint8_t j; + uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY; ++ struct dc_stream_state *stream = pipe_ctx->stream; ++ struct dc_link *link = stream->link; ++ enum dp_panel_mode panel_mode = dp_get_panel_mode(link); + + for (j = 0; j < attempts; ++j) { + +- if (dc_link_dp_perform_link_training( ++ dp_enable_link_phy( ++ link, ++ signal, ++ pipe_ctx->clock_source->id, ++ link_setting); ++ ++ if (stream->sink_patches.dppowerup_delay > 0) { ++ int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay; ++ ++ msleep(delay_dp_power_up_in_ms); ++ } ++ ++ 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; ++ } else if (dc_link_dp_perform_link_training( + link, + link_setting, + skip_video_pattern) == LINK_TRAINING_SUCCESS) + return true; + ++ /* latest link training still fail, skip delay and keep PHY on ++ */ ++ if (j == (attempts - 1)) ++ break; ++ ++ dp_disable_link_phy(link, signal); ++ + msleep(delay_between_attempts); ++ + delay_between_attempts += LINK_TRAINING_RETRY_DELAY; + } + +@@ -2770,17 +2805,26 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd + sizeof(hpd_irq_dpcd_data), + "Status: "); + +- perform_link_training_with_retries(link, +- &link->cur_link_settings, +- true, LINK_TRAINING_ATTEMPTS); +- + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i]; +- if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link && +- pipe_ctx->stream->dpms_off == false && +- pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { +- dc_link_allocate_mst_payload(pipe_ctx); +- } ++ if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link) ++ break; ++ } ++ ++ if (pipe_ctx == NULL || pipe_ctx->stream == NULL) ++ return false; ++ ++ dp_disable_link_phy(link, pipe_ctx->stream->signal); ++ ++ perform_link_training_with_retries(&link->cur_link_settings, ++ true, LINK_TRAINING_ATTEMPTS, ++ pipe_ctx, ++ pipe_ctx->stream->signal); ++ ++ if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link && ++ pipe_ctx->stream->dpms_off == false && ++ pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { ++ dc_link_allocate_mst_payload(pipe_ctx); + } + + status = false; +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +index 67ce12df23f1..548aac02ca11 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +@@ -333,20 +333,12 @@ void dp_retrain_link_dp_test(struct dc_link *link, + memset(&link->cur_link_settings, 0, + sizeof(link->cur_link_settings)); + +- link->link_enc->funcs->enable_dp_output( +- link->link_enc, +- link_setting, +- pipes[i].clock_source->id); +- link->cur_link_settings = *link_setting; +- +- dp_receiver_power_ctrl(link, true); +- + perform_link_training_with_retries( +- link, + link_setting, + skip_video_pattern, +- LINK_TRAINING_ATTEMPTS); +- ++ LINK_TRAINING_ATTEMPTS, ++ &pipes[i], ++ SIGNAL_TYPE_DISPLAY_PORT); + + link->dc->hwss.enable_stream(&pipes[i]); + +diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +index 4879cf54d8f1..6198bccd6199 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h +@@ -57,10 +57,11 @@ void decide_link_settings( + struct dc_link_settings *link_setting); + + bool perform_link_training_with_retries( +- struct dc_link *link, + const struct dc_link_settings *link_setting, + bool skip_video_pattern, +- int attempts); ++ int attempts, ++ struct pipe_ctx *pipe_ctx, ++ enum signal_type signal); + + bool is_mst_supported(struct dc_link *link); + +-- +2.17.1 + |