Skip to content

Commit 1888320

Browse files
committed
FRL training: Add retry loop, don't prefer non-borrowing rates
1 parent ed5efca commit 1888320

3 files changed

Lines changed: 49 additions & 31 deletions

File tree

drivers/gpu/drm/amd/display/dc/link/link_dpms.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1940,7 +1940,7 @@ static enum dc_status enable_link_hdmi(struct pipe_ctx *pipe_ctx)
19401940
pipe_ctx->stream->signal,
19411941
&link->cur_link_settings);
19421942

1943-
if (!dc_link_perform_frl_training(link, &pipe_ctx->link_res)) {
1943+
if (!dc_link_perform_frl_training_with_retries(link, &pipe_ctx->link_res)) {
19441944
DC_LOG_HW_LINK_TRAINING("HDMI FRL: training failed\n");
19451945
return DC_ERROR_UNEXPECTED;
19461946
}

drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.c

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#define FRL_POLL_DELAY_MS 2
2626
#define FRL_MAX_POLLS 100
2727

28+
#define FRL_TRAINING_RETRIES 10
29+
2830
static bool frl_read_scdc(struct dc_link *link, uint8_t offset, void *buf,
2931
uint32_t size)
3032
{
@@ -90,12 +92,6 @@ bool dc_link_perform_frl_training(struct dc_link *link,
9092
write_buffer[0] = 0x01;
9193
frl_write_scdc(link, HDMI_SCDC_SOURCE_VERSION, write_buffer, 1);
9294

93-
retrain:
94-
/* Reset FRL rate */
95-
write_buffer[0] = 0;
96-
write_buffer[1] = 0;
97-
frl_write_scdc(link, HDMI_SCDC_CONFIG_0, write_buffer, 2);
98-
9995
/* ------------------------------------------------------------------ */
10096
/* Step 2: Wait for FLT_READY */
10197
/* ------------------------------------------------------------------ */
@@ -197,7 +193,7 @@ bool dc_link_perform_frl_training(struct dc_link *link,
197193
return true;
198194
} else if (update & SCDC_FLT_UPDATE_BIT) {
199195
DC_LOG_HW_LINK_TRAINING("HDMI FRL: retraining needed\n");
200-
goto retrain;
196+
return false;
201197
} else {
202198
DC_LOG_HW_LINK_TRAINING("HDMI FRL: did not receive status update!\n");
203199
return false;
@@ -244,6 +240,24 @@ bool dc_link_perform_frl_training(struct dc_link *link,
244240
return false;
245241
}
246242

243+
bool dc_link_perform_frl_training_with_retries(struct dc_link *link,
244+
const struct link_resource *link_res)
245+
{
246+
bool success;
247+
int i;
248+
249+
for (i = 0; i < FRL_TRAINING_RETRIES; ++i) {
250+
success = dc_link_perform_frl_training(link, link_res);
251+
252+
if (success)
253+
break;
254+
255+
DC_LOG_HW_LINK_TRAINING("FRL: Training attempt %d failed!");
256+
}
257+
258+
return success;
259+
}
260+
247261
void dc_link_disable_frl(struct dc_link *link)
248262
{
249263
uint8_t write_buffer[2];
@@ -511,9 +525,6 @@ bool hdmi_decide_link_settings(
511525
uint8_t frl_rate;
512526
static const uint32_t frl_rates_gbps[] = {3, 6, 6, 8, 10, 12};
513527
uint8_t max_rate = stream->link->local_sink->edid_caps.frl_caps.max_rate;
514-
uint8_t best_borrow_rate = 0;
515-
uint8_t best_borrow_lanes = 0;
516-
struct dfm_results best_borrow_res = {0};
517528

518529
if (max_rate == 0 || max_rate > 6)
519530
return false;
@@ -553,29 +564,14 @@ bool hdmi_decide_link_settings(
553564
perform_dfm_check(&cfg, &res);
554565

555566
if (res.total_supported) {
556-
if (res.tb_borrowed == 0) {
557-
pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate;
558-
pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes;
567+
pipe_ctx->link_config.dp_link_settings.frl_rate = frl_rate;
568+
pipe_ctx->link_config.dp_link_settings.lane_count = cfg.lanes;
559569

560-
pr_info("HDMI FRL: Rate %d Supported. Borrowed: 0, Margin: %d ppm\n",
561-
frl_rate, res.margin_ppm);
562-
return true;
563-
} else if (best_borrow_rate == 0) {
564-
best_borrow_rate = frl_rate;
565-
best_borrow_lanes = cfg.lanes;
566-
best_borrow_res = res;
567-
}
570+
pr_info("HDMI FRL: Rate %d Supported. Borrowed: %d, Margin: %d ppm\n",
571+
frl_rate, res.tb_borrowed, res.margin_ppm);
572+
return true;
568573
}
569574
}
570575

571-
if (best_borrow_rate > 0) {
572-
pipe_ctx->link_config.dp_link_settings.frl_rate = best_borrow_rate;
573-
pipe_ctx->link_config.dp_link_settings.lane_count = best_borrow_lanes;
574-
575-
pr_info("HDMI FRL: Rate %d Supported (with borrowing). Borrowed: %llu, Margin: %d ppm\n",
576-
best_borrow_rate, best_borrow_res.tb_borrowed, best_borrow_res.margin_ppm);
577-
return true;
578-
}
579-
580576
return false;
581577
}

drivers/gpu/drm/amd/display/dc/link/protocols/link_frl_training.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,28 @@ bool dc_link_perform_frl_training(struct dc_link *link,
3535
const struct link_resource *link_res);
3636

3737
/*
38+
* Attempt HDMI 2.1 FRL link training up to FRL_TRAINING_RETRIES times.
39+
*
40+
* @link:
41+
* DC link representing the HDMI connection.
42+
*
43+
* @link_res:
44+
* Link resources containing the HPO HDMI FRL link encoder.
45+
*
46+
* @frl_rate:
47+
* FRL rate index as defined by HDMI 2.1 (1–6).
48+
*
49+
* @lane_count:
50+
* Number of FRL lanes (3 or 4).
51+
*
52+
* Returns:
53+
* true - training completed successfully, link is active
54+
* false - training failed, link is disabled
55+
*/
56+
bool dc_link_perform_frl_training_with_retries(struct dc_link *link,
57+
const struct link_resource *link_res);
58+
59+
/*
3860
* Disable FRL mode in the sink. Allows fallback to TMDS.
3961
*/
4062
void dc_link_disable_frl(struct dc_link *link);

0 commit comments

Comments
 (0)