Skip to content

Commit 169eaf2

Browse files
committed
drm/amd/display: Add early 8b/10b channel equalization test pattern sequence
JIRA: https://issues.redhat.com/browse/RHEL-75958 commit 9c44f61d0317da3d8ced02faae0a8c76bf9547ee Author: Michael Strauss <michael.strauss@amd.com> Date: Mon Dec 4 16:30:39 2023 +0800 drm/amd/display: Add early 8b/10b channel equalization test pattern sequence commit 8989cb9 upstream. [WHY] Early EQ pattern sequence is required for some LTTPR + old dongle combinations. [HOW] If DP_EARLY_8B10B_TPS2 chip cap is set, this new sequence programs phy to output TPS2 before initiating link training and writes TPS1 to LTTPR training pattern register as instructed by vendor. Add function to get embedded LTTPR target address offset. Reviewed-by: Wenjing Liu <wenjing.liu@amd.com> Signed-off-by: Michael Strauss <michael.strauss@amd.com> Signed-off-by: TungYu Lu <tungyu.lu@amd.com> Signed-off-by: Ray Wu <ray.wu@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: José Expósito <jexposit@redhat.com>
1 parent 672f50b commit 169eaf2

File tree

5 files changed

+62
-4
lines changed

5 files changed

+62
-4
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,14 @@ uint8_t dp_parse_lttpr_repeater_count(uint8_t lttpr_repeater_count)
158158
return 0; // invalid value
159159
}
160160

161+
uint32_t dp_get_closest_lttpr_offset(uint8_t lttpr_count)
162+
{
163+
/* Calculate offset for LTTPR closest to DPTX which is highest in the chain
164+
* Offset is 0 for single LTTPR cases as base LTTPR DPCD addresses target LTTPR 1
165+
*/
166+
return DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE * (lttpr_count - 1);
167+
}
168+
161169
uint32_t link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
162170
{
163171
switch (bw) {

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link);
4848
/* Convert PHY repeater count read from DPCD uint8_t. */
4949
uint8_t dp_parse_lttpr_repeater_count(uint8_t lttpr_repeater_count);
5050

51+
/* Calculate embedded LTTPR address offset for vendor-specific behaviour */
52+
uint32_t dp_get_closest_lttpr_offset(uint8_t lttpr_count);
53+
5154
bool dp_is_sink_present(struct dc_link *link);
5255

5356
bool dp_is_lttpr_present(struct dc_link *link);

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,6 @@ void override_training_settings(
785785
lt_settings->lttpr_mode = LTTPR_MODE_NON_LTTPR;
786786

787787
dp_get_lttpr_mode_override(link, &lt_settings->lttpr_mode);
788-
789788
}
790789

791790
enum dc_dp_training_pattern decide_cr_training_pattern(

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

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,14 @@ void decide_8b_10b_training_settings(
142142
lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link);
143143
lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting, lt_settings->lttpr_mode);
144144
dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
145+
146+
/* Some embedded LTTPRs rely on receiving TPS2 before LT to interop reliably with sensitive VGA dongles
147+
* This allows these LTTPRs to minimize freq/phase and skew variation during lock and deskew sequences
148+
*/
149+
if ((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) ==
150+
AMD_EXT_DISPLAY_PATH_CAPS__DP_EARLY_8B10B_TPS2) {
151+
lt_settings->lttpr_early_tps2 = true;
152+
}
145153
}
146154

147155
enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link)
@@ -173,6 +181,42 @@ enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link)
173181
return LTTPR_MODE_NON_LTTPR;
174182
}
175183

184+
static void set_link_settings_and_perform_early_tps2_retimer_pre_lt_sequence(struct dc_link *link,
185+
const struct link_resource *link_res,
186+
struct link_training_settings *lt_settings,
187+
uint32_t lttpr_count)
188+
{
189+
/* Vendor-specific LTTPR early TPS2 sequence:
190+
* 1. Output TPS2
191+
* 2. Wait 400us
192+
* 3. Set link settings as usual
193+
* 4. Write TPS1 to DP_TRAINING_PATTERN_SET_PHY_REPEATERx targeting LTTPR closest to host
194+
* 5. Wait 1ms
195+
* 6. Begin link training as usual
196+
* */
197+
198+
uint32_t closest_lttpr_address_offset = dp_get_closest_lttpr_offset(lttpr_count);
199+
200+
union dpcd_training_pattern dpcd_pattern = {0};
201+
202+
dpcd_pattern.v1_4.TRAINING_PATTERN_SET = 1;
203+
dpcd_pattern.v1_4.SCRAMBLING_DISABLE = 1;
204+
205+
DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS2. Wait 400us.\n", __func__);
206+
207+
dp_set_hw_training_pattern(link, link_res, DP_TRAINING_PATTERN_SEQUENCE_2, DPRX);
208+
209+
dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
210+
211+
udelay(400);
212+
213+
dpcd_set_link_settings(link, lt_settings);
214+
215+
core_link_write_dpcd(link, DP_TRAINING_PATTERN_SET_PHY_REPEATER1 + closest_lttpr_address_offset, &dpcd_pattern.raw, 1);
216+
217+
udelay(1000);
218+
}
219+
176220
enum link_training_result perform_8b_10b_clock_recovery_sequence(
177221
struct dc_link *link,
178222
const struct link_resource *link_res,
@@ -383,22 +427,24 @@ enum link_training_result dp_perform_8b_10b_link_training(
383427
{
384428
enum link_training_result status = LINK_TRAINING_SUCCESS;
385429

386-
uint8_t repeater_cnt;
430+
uint8_t repeater_cnt = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
387431
uint8_t repeater_id;
388432
uint8_t lane = 0;
389433

390434
if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
391435
start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
392436

393437
/* 1. set link rate, lane count and spread. */
394-
dpcd_set_link_settings(link, lt_settings);
438+
if (lt_settings->lttpr_early_tps2)
439+
set_link_settings_and_perform_early_tps2_retimer_pre_lt_sequence(link, link_res, lt_settings, repeater_cnt);
440+
else
441+
dpcd_set_link_settings(link, lt_settings);
395442

396443
if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
397444

398445
/* 2. perform link training (set link training done
399446
* to false is done as well)
400447
*/
401-
repeater_cnt = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
402448

403449
for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
404450
repeater_id--) {

drivers/gpu/drm/amd/display/include/link_service_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ struct link_training_settings {
8989
bool enhanced_framing;
9090
enum lttpr_mode lttpr_mode;
9191

92+
bool lttpr_early_tps2;
93+
9294
/* disallow different lanes to have different lane settings */
9395
bool disallow_per_lane_settings;
9496
/* dpcd lane settings will always use the same hw lane settings

0 commit comments

Comments
 (0)