From: Allen Li Date: Tue, 10 Mar 2026 08:49:08 +0000 (+0800) Subject: drm/amd/display: Add Replay/PSR active check in link loss status check X-Git-Tag: v7.2-rc1~141^2~24^2~150 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=32c542fdedc2e3bf61b4147c0ea41de0505d72d0;p=thirdparty%2Flinux.git 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 Signed-off-by: Allen Li Signed-off-by: Chenyu Chen Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c index 1860d44f63c1f..dd19b912c48c5 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c @@ -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 (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); - - status = false; - if (out_link_loss) - *out_link_loss = true; - - dp_trace_link_loss_increment(link); + 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 (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; + + dp_trace_link_loss_increment(link); + } } if (link->dpcd_caps.usb4_dp_tun_info.dp_tun_cap.bits.dp_tunneling) {