When a DP-to-HDMI 2.1 PCON is disconnected, frl.is_trained remains
set from the previous connection. On reconnect, intel_dp_check_frl_training()
checks this flag first and returns early if set, bypassing the entire FRL
training sequence entirely - including drm_dp_pcon_frl_prepare() which
sets SOURCE_CONTROLLED_MODE. As a result the source never drives FRL
negotiation on reconnect, and the HDMI FRL link may not be re-established
correctly.

The root cause is that frl.is_trained reflects the driver's last known
state and is not invalidated when the physical link goes away. From the
source's perspective, once the PCON is disconnected the downstream HDMI
FRL link state is unknown and must be treated as gone.

Add intel_dp_pcon_disconnect(), mirroring intel_dp_mst_disconnect() and
intel_dp_tunnel_disconnect(), which clears frl.is_trained and
frl.trained_rate_gbps on disconnect. This ensures intel_dp_check_frl_training()
always performs a fresh FRL negotiation on the next connect.

Signed-off-by: Xiao Lu <[email protected]>
---
 drivers/gpu/drm/i915/display/intel_dp.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c 
b/drivers/gpu/drm/i915/display/intel_dp.c
index 113d767e62e9..3643b6c4c1bc 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4996,6 +4996,27 @@ intel_dp_mst_disconnect(struct intel_dp *intel_dp)
        drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst.mgr, intel_dp->is_mst);
 }
 
+/*
+ * On disconnect, the downstream PCON and its HDMI FRL link state are gone
+ * from the source's perspective. Clear the cached FRL training state so that
+ * intel_dp_check_frl_training() performs a fresh FRL negotiation on the next
+ * connect, rather than skipping training based on stale state.
+ */
+static void
+intel_dp_pcon_disconnect(struct intel_dp *intel_dp)
+{
+       struct intel_display *display = to_intel_display(intel_dp);
+
+       if (!intel_dp_is_hdmi_2_1_sink(intel_dp))
+               return;
+
+       drm_dbg_kms(display->drm,
+                   "PCON HDMI2.1 sink disconnected, resetting FRL state (was 
trained at %d Gbps)\n",
+                   intel_dp->frl.trained_rate_gbps);
+       intel_dp->frl.is_trained = false;
+       intel_dp->frl.trained_rate_gbps = 0;
+}
+
 #define INTEL_DP_DEVICE_SERVICE_IRQ_MASK_SST   (DP_AUTOMATED_TEST_REQUEST | \
                                                 DP_CP_IRQ | \
                                                 DP_SINK_SPECIFIC_IRQ)
@@ -6337,6 +6358,8 @@ intel_dp_detect(struct drm_connector *_connector,
 
                intel_dp_tunnel_disconnect(intel_dp);
 
+               intel_dp_pcon_disconnect(intel_dp);
+
                intel_dp_tunnel_uhbr_lanes_wa_reset(intel_dp);
 
                goto out_unset_edid;
-- 
2.43.0

Reply via email to