aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4673-drm-amd-display-Reset-PHY-in-link-re-training.patch
diff options
context:
space:
mode:
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.patch222
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
+