[PATCH] drm/i915/lnl+/tc: Fix false disconnect of active DP-alt TC port during long HPD pulse

Chia-Lin Kao (AceLan) posted 1 patch 1 month, 1 week ago
drivers/gpu/drm/i915/display/intel_tc.c | 5 +++++
1 file changed, 5 insertions(+)
[PATCH] drm/i915/lnl+/tc: Fix false disconnect of active DP-alt TC port during long HPD pulse
Posted by Chia-Lin Kao (AceLan) 1 month, 1 week ago
On platforms using XELPDP+ (Lunar Lake and later), tc_phy_hpd_live_status()
reads the PICAINTERRUPT_ISR register to determine DP-alt live status. The
XELPDP_DP_ALT_HOTPLUG_MASK bit in this register reflects the live HPD signal,
which deasserts (goes low) during a long HPD pulse from the sink.

When an LTTPR dongle (e.g. HP Type-C to HDMI, 03f0:8a4a) fires a long HPD
pulse after link training, intel_tc_port_connected() reads PICAINTERRUPT_ISR
and returns false even though the PHY is still owned and the link is active.
Since intel_tc_port_handles_hpd_glitches() returns true for TC dp-alt ports,
the 4ms glitch-filter retry loop in intel_digital_port_connected_locked() is
bypassed immediately, giving no protection against this transient deassertion.

The AUX abort logic then fires (-ENXIO), the hotplug handler marks DP-1 as
disconnected, and the compositor responds by disabling eDP-1, causing the
internal display to disappear.

Fix this by trusting the PHY ownership register
(XELPDP_PORT_BUF_CTL1 & XELPDP_TC_PHY_OWNERSHIP) over the transient HPD
live status in intel_tc_port_connected() when the port has an active link
(link_refcount > 0). The ownership register is stable and does not toggle
during HPD pulses.

The TC cold power domain is guaranteed to be held when link_refcount > 0,
as __intel_tc_port_lock() already asserts and verifies this via tc_phy_is_owned()
before we reach intel_tc_port_connected().

Without this fix, triggering mirror mode via hotkey on HP ZBook with HP Type-C
to HDMI dongle (03f0:8a4a) causes:

  [drm:intel_dp_hpd_pulse] got hpd irq on [ENCODER:270:DDI TC1/PHY TC1] - long
  [drm:intel_tc_port_update_mode] Port D/TC#1: TC port mode reset (disconnected -> tbt-alt)
  [drm:intel_dp_hpd_pulse] got hpd irq on [ENCODER:270:DDI TC1/PHY TC1] - long
  [drm:intel_hotplug_detect_connector] [CONNECTOR:271:DP-1] status updated from connected to disconnected

With this fix, the port correctly stays in DP-alt mode:

  [drm:intel_tc_port_update_mode] Port D/TC#1: TC port mode reset (dp-alt -> disconnected)
  [drm:intel_tc_port_update_mode] Port D/TC#1: TC port mode reset (disconnected -> dp-alt)

Signed-off-by: Chia-Lin Kao (AceLan) <acelan.kao@canonical.com>
---
 drivers/gpu/drm/i915/display/intel_tc.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index bd12148e42f70..0967cfc75f522 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -1732,6 +1732,11 @@ bool intel_tc_port_connected(struct intel_encoder *encoder)
 	if (tc->mode != TC_PORT_DISCONNECTED)
 		mask = BIT(tc->mode);
 
+	if (tc->link_refcount > 0 &&
+	    tc->mode == TC_PORT_DP_ALT &&
+	    tc_phy_is_owned(tc))
+		return true;
+
 	return tc_phy_hpd_live_status(tc) & mask;
 }
 
-- 
2.51.0