Commit 82253671 authored by Jimmy Kizito's avatar Jimmy Kizito Committed by Alex Deucher

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: default avatarJimmy Kizito <Jimmy.Kizito@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarStylon Wang <stylon.wang@amd.com>
Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ede4f6da
......@@ -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 {
......
......@@ -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;
......
......@@ -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]);
......
......@@ -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);
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment