From: Jimmy Kizito <jimmy.kiz...@amd.com>

[Why]
When enabling a DisplayPort stream:
- Optionally reducing link bandwidth between failed link training
attempts should progressively relax training requirements.
- Abandoning link training altogether if a sink is unplugged should
avoid unnecessary training attempts.

[How]
- Add fallback parameter to DP link training function and reduce link
bandwidth between failed training attempts as long as stream bandwidth
requirements are met.
- Add training status for sink unplug and abort training when this
status is reported.

Signed-off-by: Jimmy Kizito <jimmy.kiz...@amd.com>
Reviewed-by: Jun Lei <jun....@amd.com>
Acked-by: Stylon Wang <stylon.w...@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc_link.c |  5 ++-
 .../gpu/drm/amd/display/dc/core/dc_link_dp.c  | 40 +++++++++++++++----
 .../drm/amd/display/dc/core/dc_link_hwss.c    |  3 +-
 .../gpu/drm/amd/display/dc/inc/dc_link_dp.h   |  3 +-
 .../amd/display/include/link_service_types.h  |  2 +
 5 files changed, 42 insertions(+), 11 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 d040d235c2db..c4405eba724c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -1750,6 +1750,8 @@ static enum dc_status enable_link_dp(struct dc_state 
*state,
        bool apply_seamless_boot_optimization = false;
        uint32_t bl_oled_enable_delay = 50; // in ms
        const uint32_t post_oui_delay = 30; // 30ms
+       /* Reduce link bandwidth between failed link training attempts. */
+       bool do_fallback = false;
 
        // check for seamless boot
        for (i = 0; i < state->stream_count; i++) {
@@ -1788,7 +1790,8 @@ static enum dc_status enable_link_dp(struct dc_state 
*state,
                                               skip_video_pattern,
                                               LINK_TRAINING_ATTEMPTS,
                                               pipe_ctx,
-                                              pipe_ctx->stream->signal)) {
+                                              pipe_ctx->stream->signal,
+                                              do_fallback)) {
                link->cur_link_settings = link_settings;
                status = DC_OK;
        } else {
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 8565281e6179..b6ed57ba7a48 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
@@ -1701,18 +1701,31 @@ bool perform_link_training_with_retries(
        bool skip_video_pattern,
        int attempts,
        struct pipe_ctx *pipe_ctx,
-       enum signal_type signal)
+       enum signal_type signal,
+       bool do_fallback)
 {
        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;
+       struct link_encoder *link_enc;
+       enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
+       struct dc_link_settings currnet_setting = *link_setting;
+
+       /* Dynamically assigned link encoders associated with stream rather than
+        * link.
+        */
+       if (link->dc->res_pool->funcs->link_encs_assign)
+               link_enc = stream->link_enc;
+       else
+               link_enc = link->link_enc;
+       ASSERT(link_enc);
 
        /* 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,
+       link_enc->funcs->connect_dig_be_to_fe(link_enc,
                                                        
pipe_ctx->stream_res.stream_enc->id, true);
 
        for (j = 0; j < attempts; ++j) {
@@ -1724,7 +1737,7 @@ bool perform_link_training_with_retries(
                        link,
                        signal,
                        pipe_ctx->clock_source->id,
-                       link_setting);
+                       &currnet_setting);
 
                if (stream->sink_patches.dppowerup_delay > 0) {
                        int delay_dp_power_up_in_ms = 
stream->sink_patches.dppowerup_delay;
@@ -1739,14 +1752,12 @@ bool perform_link_training_with_retries(
                         panel_mode != DP_PANEL_MODE_DEFAULT);
 
                if (link->aux_access_disabled) {
-                       dc_link_dp_perform_link_training_skip_aux(link, 
link_setting);
+                       dc_link_dp_perform_link_training_skip_aux(link, 
&currnet_setting);
                        return true;
                } else {
-                       enum link_training_result status = 
LINK_TRAINING_CR_FAIL_LANE0;
-
                                status = dc_link_dp_perform_link_training(
                                                                                
link,
-                                                                               
link_setting,
+                                                                               
&currnet_setting,
                                                                                
skip_video_pattern);
                        if (status == LINK_TRAINING_SUCCESS)
                                return true;
@@ -1754,7 +1765,7 @@ bool perform_link_training_with_retries(
 
                /* latest link training still fail, skip delay and keep PHY on
                 */
-               if (j == (attempts - 1))
+               if (j == (attempts - 1) && link->ep_type == 
DISPLAY_ENDPOINT_PHY)
                        break;
 
                DC_LOG_WARNING("%s: Link training attempt %u of %d failed\n",
@@ -1762,6 +1773,19 @@ bool perform_link_training_with_retries(
 
                dp_disable_link_phy(link, signal);
 
+               /* Abort link training if failure due to sink being unplugged. 
*/
+               if (status == LINK_TRAINING_ABORT)
+                       break;
+               else if (do_fallback) {
+                       decide_fallback_link_setting(*link_setting, 
&currnet_setting, status);
+                       /* Fail link training if reduced link bandwidth no 
longer meets
+                        * stream requirements.
+                        */
+                       if (dc_bandwidth_in_kbps_from_timing(&stream->timing) <
+                                       dc_link_bandwidth_kbps(link, 
&currnet_setting))
+                               break;
+               }
+
                msleep(delay_between_attempts);
 
                delay_between_attempts += LINK_TRAINING_RETRY_DELAY;
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 b426f878fb99..13c5c4a34a58 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
@@ -384,7 +384,8 @@ void dp_retrain_link_dp_test(struct dc_link *link,
                                        skip_video_pattern,
                                        LINK_TRAINING_ATTEMPTS,
                                        &pipes[i],
-                                       SIGNAL_TYPE_DISPLAY_PORT);
+                                       SIGNAL_TYPE_DISPLAY_PORT,
+                                       false);
 
                        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 699de64a7e44..38e6fbf1e26d 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
@@ -65,7 +65,8 @@ bool perform_link_training_with_retries(
        bool skip_video_pattern,
        int attempts,
        struct pipe_ctx *pipe_ctx,
-       enum signal_type signal);
+       enum signal_type signal,
+       bool do_fallback);
 
 bool is_mst_supported(struct dc_link *link);
 
diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h 
b/drivers/gpu/drm/amd/display/include/link_service_types.h
index 7392a89e771f..5a250f41004f 100644
--- a/drivers/gpu/drm/amd/display/include/link_service_types.h
+++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
@@ -68,6 +68,8 @@ enum link_training_result {
        LINK_TRAINING_LQA_FAIL,
        /* one of the CR,EQ or symbol lock is dropped */
        LINK_TRAINING_LINK_LOSS,
+       /* Abort link training (because sink unplugged) */
+       LINK_TRAINING_ABORT,
 };
 
 struct link_training_settings {
-- 
2.25.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to