diff options
author | Jimmy Kizito <Jimmy.Kizito@amd.com> | 2021-04-07 18:56:19 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2021-05-10 18:10:00 -0400 |
commit | 8225367130666bf2961399a85913af1b4497d9b4 (patch) | |
tree | 0bdb1edf89c3505eb7230e26eeed3d6eecdd1317 /drivers/gpu/drm/amd/display/dc/core | |
parent | drm/amd/display: Update setting of DP training parameters. (diff) | |
download | linux-dev-8225367130666bf2961399a85913af1b4497d9b4.tar.xz linux-dev-8225367130666bf2961399a85913af1b4497d9b4.zip |
drm/amd/display: Add fallback and abort paths for DP link training.
[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.Kizito@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Stylon Wang <stylon.wang@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 40 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 |
3 files changed, 38 insertions, 10 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 a87613f265f0..dd95d002e156 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]); |