* [PATCH 1/3] drm/amd/display: Apply requested TxFFE level right away in FRL training
2026-11-10 13:09 [PATCH 0/3] drm/amd/display: HDMI FRL training fixes for slow sinks Andrzej Piątyszek
@ 2026-11-10 13:09 ` Andrzej Piątyszek
2026-11-10 13:09 ` [PATCH 2/3] drm/amd/display: Wait up to 1 s for slow sinks in FRL link training Andrzej Piątyszek
2026-11-10 13:09 ` [PATCH 3/3] drm/amd/display: Retry the same FRL rate after a sink timeout Andrzej Piątyszek
2 siblings, 0 replies; 4+ messages in thread
From: Andrzej Piątyszek @ 2026-11-10 13:09 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, Fangzhi Zuo, Relja Vojvodic, Ilya Bakoulin,
David Airlie, Simona Vetter, dri-devel, linux-kernel,
Andrzej Piątyszek
When the sink answers an LTP request with 0xE (next TxFFE level) in
LTS:3, hdmi_frl_perform_link_training() programs the new level only on
the next poll, and only if the sink has set FLT_update again by then.
The sink usually has not, as the driver has just cleared FLT_update.
The sink keeps asking, and current_FFE advances without reaching the
PHY.
A Samsung QE65Q80T (2020) needs one TxFFE step at 10 Gbps x 4, so its
link mostly ends up at 6 Gbps x 3.
Program the requested level right away and drop the deferred
programming.
Fixes: cbb8e2044b9e ("drm/amd/display: Add DC link support for FRL")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Andrzej Piątyszek <andrzej.piatyszek@gmail.com>
---
.../display/dc/link/protocols/link_hdmi_frl.c | 33 ++++++++-----------
1 file changed, 13 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
index 960f18fe2..78e62bfec 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
@@ -640,26 +640,6 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s
prev_flt_update = scdc_update.fields.FLT_UPDATE;
}
- /*Set TxFFE = TxFFE0*/
- /*Program FFE_Levels - scdc_config has this field at 0 */
- if (override_FFE) {
- if (current_FFE == 0)
- dio_link_enc->funcs->prog_eq_setting(dio_link_enc, current_FFE,
- test_req.fields.TXFFE_DEEMPHASIS,
- test_req.fields.TXFFE_PRESHOOT,
- test_req.fields.TXFFE_NOFFE,
- link_settings);
- else {
- if (scdc_update.fields.FLT_UPDATE)
- dio_link_enc->funcs->prog_eq_setting(dio_link_enc, current_FFE,
- test_req.fields.TXFFE_DEEMPHASIS,
- test_req.fields.TXFFE_PRESHOOT,
- test_req.fields.TXFFE_NOFFE,
- link_settings);
- }
- FRL_INFO("FRL LINK TRAINING: TxFFE = %d.\n", current_FFE);
- override_FFE = false;
- }
if (scdc_update.fields.FLT_UPDATE) {
offset = HDMI_SCDC_LTP_REQ;
link_query_ddc_data(ddc_service, slave_address,
@@ -749,6 +729,19 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s
ln1_pattern = pre_ln1_pattern;
ln2_pattern = pre_ln2_pattern;
ln3_pattern = pre_ln3_pattern;
+
+ /*
+ * The sink re-evaluates the link as soon as FLT_update
+ * is cleared, so program the requested level now.
+ */
+ dio_link_enc->funcs->prog_eq_setting(dio_link_enc,
+ current_FFE,
+ test_req.fields.TXFFE_DEEMPHASIS,
+ test_req.fields.TXFFE_PRESHOOT,
+ test_req.fields.TXFFE_NOFFE,
+ link_settings);
+ FRL_INFO("FRL LINK TRAINING: TxFFE = %d.\n", current_FFE);
+ override_FFE = false;
}
FRL_INFO("FRL LINK TRAINING: Setting Training Pattern [ln0,ln1,ln2,ln3] = [%d,%d,%d,%d].\n",
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 2/3] drm/amd/display: Wait up to 1 s for slow sinks in FRL link training
2026-11-10 13:09 [PATCH 0/3] drm/amd/display: HDMI FRL training fixes for slow sinks Andrzej Piątyszek
2026-11-10 13:09 ` [PATCH 1/3] drm/amd/display: Apply requested TxFFE level right away in FRL training Andrzej Piątyszek
@ 2026-11-10 13:09 ` Andrzej Piątyszek
2026-11-10 13:09 ` [PATCH 3/3] drm/amd/display: Retry the same FRL rate after a sink timeout Andrzej Piątyszek
2 siblings, 0 replies; 4+ messages in thread
From: Andrzej Piątyszek @ 2026-11-10 13:09 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, Fangzhi Zuo, Relja Vojvodic, Ilya Bakoulin,
David Airlie, Simona Vetter, dri-devel, linux-kernel,
Andrzej Piątyszek
LTS:3 gives the sink 220 ms (320 ms at 16 Gbps and above) to answer an
LTP request before the driver gives up on the rate. A Samsung QE65Q80T
(2020) sometimes answers at 10 Gbps x 4 only after 225 to 967 ms, so
link verification falls back to 6 Gbps x 3.
Wait up to 1 s at every rate. Sinks that answer within the old limit
are unaffected; a sink that never answers costs up to 1 s per rate in
the polling loop instead of 220 ms.
Fixes: cbb8e2044b9e ("drm/amd/display: Add DC link support for FRL")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Andrzej Piątyszek <andrzej.piatyszek@gmail.com>
---
.../drm/amd/display/dc/link/protocols/link_hdmi_frl.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
index 78e62bfec..97b2b9b74 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
@@ -612,10 +612,13 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s
FRL_INFO("FRL LINK TRAINING: Poll for FLT_UPDATE.\n");
/*LTS:3: Start Link Training*/
- /*Start FLT Timer = 200 ms, or 300ms if link rate >= 16Gbps*/
+ /*
+ * Start FLT Timer. Some sinks need longer than the nominal 200 ms
+ * (300 ms at 16 Gbps and above) to answer an LTP request, so wait
+ * up to 1 s before giving up on this rate.
+ */
num_polls = 0;
- if (link_settings->frl_link_rate >= HDMI_FRL_LINK_RATE_16GBPS)
- poll_timeout_ns = 320 * 1000 * 1000;
+ poll_timeout_ns = 1000 * 1000 * 1000;
flt_poll_start = dm_get_timestamp(ddc_service->ctx);
uint8_t prev_flt_update = 0;
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 3/3] drm/amd/display: Retry the same FRL rate after a sink timeout
2026-11-10 13:09 [PATCH 0/3] drm/amd/display: HDMI FRL training fixes for slow sinks Andrzej Piątyszek
2026-11-10 13:09 ` [PATCH 1/3] drm/amd/display: Apply requested TxFFE level right away in FRL training Andrzej Piątyszek
2026-11-10 13:09 ` [PATCH 2/3] drm/amd/display: Wait up to 1 s for slow sinks in FRL link training Andrzej Piątyszek
@ 2026-11-10 13:09 ` Andrzej Piątyszek
2 siblings, 0 replies; 4+ messages in thread
From: Andrzej Piątyszek @ 2026-11-10 13:09 UTC (permalink / raw)
To: amd-gfx
Cc: Harry Wentland, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, Fangzhi Zuo, Relja Vojvodic, Ilya Bakoulin,
David Airlie, Simona Vetter, dri-devel, linux-kernel,
Andrzej Piątyszek
hdmi_frl_perform_link_training_with_fallback() lowers the rate after any
failed attempt, even when the sink never answered. The enable path,
hdmi_frl_perform_link_training_with_retries(), tries the same rate again
instead.
After waking up, a Samsung QE65Q80T (2020) can stay silent at
10 Gbps x 4 for a few seconds and then train in about 33 ms. Link
verification moves to a lower rate before that happens.
After a timeout, try the same rate again, up to max_retries times per
verification, as the enable path does. A sink that never answers costs
up to three extra attempts.
Fixes: cbb8e2044b9e ("drm/amd/display: Add DC link support for FRL")
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Andrzej Piątyszek <andrzej.piatyszek@gmail.com>
---
.../amd/display/dc/link/protocols/link_hdmi_frl.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
index 97b2b9b74..129834d6d 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
@@ -818,9 +818,14 @@ enum link_result hdmi_frl_perform_link_training_with_fallback(
enum clock_source_id frl_phy_clock_source_id)
{
enum link_result status = LINK_RESULT_UNKNOWN;
+ unsigned int retries = 0;
+ unsigned int max_retries = 3;
DC_LOGGER_INIT(link->ctx->logger);
+ if (link->preferred_hdmi_frl_settings.valid)
+ max_retries = link->preferred_hdmi_frl_settings.max_retries;
+
/* FRL Link Training */
while (status != LINK_RESULT_FALLBACK) {
if (link->frl_link_settings.frl_link_rate ==
@@ -846,6 +851,15 @@ enum link_result hdmi_frl_perform_link_training_with_fallback(
if (status == LINK_RESULT_SUCCESS)
break;
+ /*
+ * A sink that is still waking up may not answer at all. Retry the
+ * same rate before going lower, as many times as link enable does.
+ */
+ if (status == LINK_RESULT_TIMEOUT && retries < max_retries) {
+ retries++;
+ continue;
+ }
+
link->frl_link_settings.frl_link_rate--;
if (link->frl_link_settings.frl_link_rate <
HDMI_FRL_LINK_RATE_6GBPS_4LANE)
--
2.56.0
^ permalink raw reply [flat|nested] 4+ messages in thread