Commit 61436301 authored by Weiguang Li's avatar Weiguang Li Committed by Alex Deucher
Browse files

drm/amd/display: Add ESD detection for replay recovery



[HOW]
Add Replay recovery flow so that when HPD occurs and ESD is detected,
Replay can restore the system back to normal.

Reviewed-by: default avatarWenjing Liu <wenjing.liu@amd.com>
Reviewed-by: default avatarRobin Chen <robin.chen@amd.com>
Reviewed-by: default avatarAric Cyr <aric.cyr@amd.com>
Signed-off-by: default avatarWeiguang Li <wei-guang.li@amd.com>
Signed-off-by: default avatarAlex Hung <alex.hung@amd.com>
Tested-by: default avatarDan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent a879009f
Loading
Loading
Loading
Loading
+25 −11
Original line number Diff line number Diff line
@@ -223,9 +223,10 @@ static void handle_hpd_irq_vesa_replay_sink(struct dc_link *link)
	}
}

static void handle_hpd_irq_replay_sink(struct dc_link *link)
static void handle_hpd_irq_replay_sink(struct dc_link *link, bool *need_re_enable)
{
	union dpcd_replay_configuration replay_configuration = {0};
	union dpcd_replay_configuration replay_sink_status = {0};
	/*AMD Replay version reuse DP_PSR_ERROR_STATUS for REPLAY_ERROR status.*/
	union psr_error_status replay_error_status = {0};
	bool ret = false;
@@ -265,9 +266,17 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link)
		&replay_error_status.raw,
		sizeof(replay_error_status.raw));

	dm_helpers_dp_read_dpcd(
		link->ctx,
		link,
		DP_PR_REPLAY_SINK_STATUS,
		&replay_sink_status.raw,
		1);

	if (replay_error_status.bits.LINK_CRC_ERROR ||
		replay_configuration.bits.DESYNC_ERROR_STATUS ||
		replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS) {
		replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS ||
		replay_sink_status.bits.SINK_DEVICE_REPLAY_STATUS == 0x7) {
		bool allow_active;

		link->replay_settings.config.replay_error_status.raw |= replay_error_status.raw;
@@ -299,8 +308,7 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link)
		if (link->replay_settings.replay_allow_active) {
			allow_active = false;
			edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
			allow_active = true;
			edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
			*need_re_enable = true;
		}
	}
}
@@ -460,6 +468,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
	union device_service_irq device_service_clear = {0};
	enum dc_status result;
	bool status = false;
	bool replay_re_enable_needed = false;

	if (out_link_loss)
		*out_link_loss = false;
@@ -519,7 +528,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
		/* PSR-related error was detected and handled */
		return true;

	handle_hpd_irq_replay_sink(link);
	handle_hpd_irq_replay_sink(link, &replay_re_enable_needed);

	/* If PSR-related error handled, Main link may be off,
	 * so do not handle as a normal sink status change interrupt.
@@ -538,14 +547,14 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
		return false;
	}

	/* For now we only handle 'Downstream port status' case.
	/* Handle 'Downstream port status' case for all DP link types.
	 * If we got sink count changed it means
	 * Downstream port status changed,
	 * then DM should call DC to do the detection.
	 * NOTE: Do not handle link loss on eDP since it is internal link
	 * NOTE: Now includes eDP link loss detection and retraining
	 */
	if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
			dp_parse_link_loss_status(

	if (dp_parse_link_loss_status(
			link,
			&hpd_irq_dpcd_data)) {
		/* Connectivity log: link loss */
@@ -576,6 +585,11 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
			!= link->dpcd_sink_count)
		status = true;

	if (replay_re_enable_needed) {
		bool allow_active = true;

		edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
	}
	/* reasons for HPD RX:
	 * 1. Link Loss - ie Re-train the Link
	 * 2. MST sideband message
+3 −0
Original line number Diff line number Diff line
@@ -64,6 +64,9 @@
#ifndef DP_PR_ERROR_STATUS                  // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PR_ERROR_STATUS                  0x2020  /* DP 2.0 */
#endif /* DP_PR_ERROR_STATUS */
#ifndef DP_PR_REPLAY_SINK_STATUS            // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PR_REPLAY_SINK_STATUS            0x2022
#endif /* DP_PR_REPLAY_SINK_STATUS */
#ifndef DP_PR_LINK_CRC_ERROR               // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PR_LINK_CRC_ERROR               (1 << 0)
#endif /* DP_PR_LINK_CRC_ERROR */