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

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
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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 {
+32 −8
Original line number Diff line number Diff line
@@ -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;
+2 −1
Original line number Diff line number Diff line
@@ -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]);

+2 −1
Original line number Diff line number Diff line
@@ -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);

+2 −0
Original line number Diff line number Diff line
@@ -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 {