Skip to content

Commit b03a599

Browse files
Derek Laialexdeucher
authored andcommitted
drm/amd/display: Set link rate set if eDP ver >= 1.4.
[Why] If eDP ver >= 1.4, the Source device must use LINK_RATE_SET. [How] Get LINK_RATE_SET by reading DPCD 10h-1fh, then write DPCD 00115h before link training. Signed-off-by: Derek Lai <[email protected]> Reviewed-by: Tony Cheng <[email protected]> Acked-by: Leo Li <[email protected]> Signed-off-by: Alex Deucher <[email protected]>
1 parent 7eb9097 commit b03a599

File tree

3 files changed

+111
-8
lines changed

3 files changed

+111
-8
lines changed

drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ static void dpcd_set_link_settings(
117117
core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL,
118118
&downspread.raw, sizeof(downspread));
119119

120+
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
121+
(link->dpcd_caps.link_rate_set >= 1 &&
122+
link->dpcd_caps.link_rate_set <= 8)) {
123+
core_link_write_dpcd(link, DP_LINK_RATE_SET,
124+
&link->dpcd_caps.link_rate_set, 1);
125+
}
126+
120127
DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x\n %x spread = %x\n",
121128
__func__,
122129
DP_LINK_BW_SET,
@@ -2489,13 +2496,105 @@ bool detect_dp_sink_caps(struct dc_link *link)
24892496
/* TODO save sink caps in link->sink */
24902497
}
24912498

2499+
enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
2500+
{
2501+
enum dc_link_rate link_rate;
2502+
// LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
2503+
switch (link_rate_in_khz) {
2504+
case 1620000:
2505+
link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
2506+
break;
2507+
case 2160000:
2508+
link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
2509+
break;
2510+
case 2430000:
2511+
link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
2512+
break;
2513+
case 2700000:
2514+
link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
2515+
break;
2516+
case 3240000:
2517+
link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
2518+
break;
2519+
case 4320000:
2520+
link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
2521+
break;
2522+
case 5400000:
2523+
link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
2524+
break;
2525+
case 8100000:
2526+
link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
2527+
break;
2528+
default:
2529+
link_rate = LINK_RATE_UNKNOWN;
2530+
break;
2531+
}
2532+
return link_rate;
2533+
}
2534+
24922535
void detect_edp_sink_caps(struct dc_link *link)
24932536
{
2494-
retrieve_link_cap(link);
2537+
uint8_t supported_link_rates[16] = {0};
2538+
uint32_t entry;
2539+
uint32_t link_rate_in_khz;
2540+
enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
2541+
uint8_t link_rate_set = 0;
24952542

2496-
if (link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)
2497-
link->reported_link_cap.link_rate = LINK_RATE_HIGH2;
2543+
retrieve_link_cap(link);
24982544

2545+
if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
2546+
// Read DPCD 00010h - 0001Fh 16 bytes at one shot
2547+
core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES,
2548+
supported_link_rates, sizeof(supported_link_rates));
2549+
2550+
link->dpcd_caps.link_rate_set = 0;
2551+
for (entry = 0; entry < 16; entry += 2) {
2552+
// DPCD register reports per-lane link rate = 16-bit link rate capability
2553+
// value X 200 kHz. Need multipler to find link rate in kHz.
2554+
link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
2555+
supported_link_rates[entry]) * 200;
2556+
2557+
if (link_rate_in_khz != 0) {
2558+
link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
2559+
if (link->reported_link_cap.link_rate < link_rate) {
2560+
link->reported_link_cap.link_rate = link_rate;
2561+
2562+
switch (link_rate) {
2563+
case LINK_RATE_LOW:
2564+
link_rate_set = 1;
2565+
break;
2566+
case LINK_RATE_RATE_2:
2567+
link_rate_set = 2;
2568+
break;
2569+
case LINK_RATE_RATE_3:
2570+
link_rate_set = 3;
2571+
break;
2572+
case LINK_RATE_HIGH:
2573+
link_rate_set = 4;
2574+
break;
2575+
case LINK_RATE_RBR2:
2576+
link_rate_set = 5;
2577+
break;
2578+
case LINK_RATE_RATE_6:
2579+
link_rate_set = 6;
2580+
break;
2581+
case LINK_RATE_HIGH2:
2582+
link_rate_set = 7;
2583+
break;
2584+
case LINK_RATE_HIGH3:
2585+
link_rate_set = 8;
2586+
break;
2587+
default:
2588+
link_rate_set = 0;
2589+
break;
2590+
}
2591+
2592+
if (link->dpcd_caps.link_rate_set < link_rate_set)
2593+
link->dpcd_caps.link_rate_set = link_rate_set;
2594+
}
2595+
}
2596+
}
2597+
}
24992598
link->verified_link_cap = link->reported_link_cap;
25002599
}
25012600

drivers/gpu/drm/amd/display/dc/dc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,7 @@ struct dpcd_caps {
659659
int8_t branch_dev_name[6];
660660
int8_t branch_hw_revision;
661661
int8_t branch_fw_revision[2];
662+
uint8_t link_rate_set;
662663

663664
bool allow_invalid_MSA_timing_param;
664665
bool panel_mode_edp;

drivers/gpu/drm/amd/display/dc/dc_dp_types.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,14 @@ enum dc_lane_count {
4646
*/
4747
enum dc_link_rate {
4848
LINK_RATE_UNKNOWN = 0,
49-
LINK_RATE_LOW = 0x06,
50-
LINK_RATE_HIGH = 0x0A,
51-
LINK_RATE_RBR2 = 0x0C,
52-
LINK_RATE_HIGH2 = 0x14,
53-
LINK_RATE_HIGH3 = 0x1E
49+
LINK_RATE_LOW = 0x06, // Rate_1 (RBR) - 1.62 Gbps/Lane
50+
LINK_RATE_RATE_2 = 0x08, // Rate_2 - 2.16 Gbps/Lane
51+
LINK_RATE_RATE_3 = 0x09, // Rate_3 - 2.43 Gbps/Lane
52+
LINK_RATE_HIGH = 0x0A, // Rate_4 (HBR) - 2.70 Gbps/Lane
53+
LINK_RATE_RBR2 = 0x0C, // Rate_5 (RBR2)- 3.24 Gbps/Lane
54+
LINK_RATE_RATE_6 = 0x10, // Rate_6 - 4.32 Gbps/Lane
55+
LINK_RATE_HIGH2 = 0x14, // Rate_7 (HBR2)- 5.40 Gbps/Lane
56+
LINK_RATE_HIGH3 = 0x1E // Rate_8 (HBR3)- 8.10 Gbps/Lane
5457
};
5558

5659
enum dc_link_spread {

0 commit comments

Comments
 (0)