drm/amd/display: Add Replay/PSR active check in link loss status check

[Why&How]
To avoid unnecessary link retraining when the panel is in Replay/PSR mode,
we need to check if it's in active state and ESD information before we
decide to retrain the link.

Reviewed-by: ChunTao Tso <chuntao.tso@amd.com>
Signed-off-by: Allen Li <allen.li@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Allen Li 2026-03-10 16:49:08 +08:00 committed by Alex Deucher
parent 3c108046e1
commit 32c542fded

View File

@ -223,7 +223,7 @@ static void handle_hpd_irq_vesa_replay_sink(struct dc_link *link)
}
}
static void handle_hpd_irq_replay_sink(struct dc_link *link, bool *need_re_enable)
static void handle_hpd_irq_replay_sink(struct dc_link *link, bool *need_re_enable, bool *replay_esd_detection_needed)
{
union dpcd_replay_configuration replay_configuration = {0};
union dpcd_replay_configuration replay_sink_status = {0};
@ -311,6 +311,14 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link, bool *need_re_enabl
*need_re_enable = true;
}
}
if (!link->replay_settings.replay_allow_active &&
replay_sink_status.bits.SINK_DEVICE_REPLAY_STATUS == 0x7) {
/* If sink device replay status is 0x7 and replay is disabled,
* it means sink is in a bad state and link retraining is needed to recover
*/
*replay_esd_detection_needed = true;
}
}
void dp_handle_link_loss(struct dc_link *link)
@ -469,6 +477,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
enum dc_status result;
bool status = false;
bool replay_re_enable_needed = false;
bool replay_esd_detection_needed = false;
if (out_link_loss)
*out_link_loss = false;
@ -482,6 +491,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",
__func__, link->link_index);
handle_hpd_irq_replay_sink(link, &replay_re_enable_needed, &replay_esd_detection_needed);
/* All the "handle_hpd_irq_xxx()" methods
* should be called only after
@ -528,8 +538,6 @@ 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, &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.
*/
@ -552,27 +560,30 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
* Downstream port status changed,
* then DM should call DC to do the detection.
* NOTE: Now includes eDP link loss detection and retraining
* Link will be retrained if panel is not EDP or
* Replay ESD recovery is needed.
*/
if (link->connector_signal != SIGNAL_TYPE_EDP || replay_esd_detection_needed) {
if (dp_parse_link_loss_status(
link,
&hpd_irq_dpcd_data)) {
/* Connectivity log: link loss */
CONN_DATA_LINK_LOSS(link,
hpd_irq_dpcd_data.raw,
sizeof(hpd_irq_dpcd_data),
"Status: ");
if (dp_parse_link_loss_status(
link,
&hpd_irq_dpcd_data)) {
/* Connectivity log: link loss */
CONN_DATA_LINK_LOSS(link,
hpd_irq_dpcd_data.raw,
sizeof(hpd_irq_dpcd_data),
"Status: ");
if (defer_handling && has_left_work)
*has_left_work = true;
else
dp_handle_link_loss(link);
if (defer_handling && has_left_work)
*has_left_work = true;
else
dp_handle_link_loss(link);
status = false;
if (out_link_loss)
*out_link_loss = true;
status = false;
if (out_link_loss)
*out_link_loss = true;
dp_trace_link_loss_increment(link);
dp_trace_link_loss_increment(link);
}
}
if (link->dpcd_caps.usb4_dp_tun_info.dp_tun_cap.bits.dp_tunneling) {