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) <[email protected]>
---
 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

Reply via email to