Skip to content

Commit 749eb52

Browse files
committed
drm/amd/display: Get LTTPR IEEE OUI/Device ID From Closest LTTPR To Host
JIRA: https://issues.redhat.com/browse/RHEL-75958 commit af02a1913a15d99ac8b6fc25f25ce5222d1c191b Author: Michael Strauss <michael.strauss@amd.com> Date: Wed Feb 26 10:03:48 2025 -0500 drm/amd/display: Get LTTPR IEEE OUI/Device ID From Closest LTTPR To Host commit d358a51 upstream. [WHY] These fields are read for the explicit purpose of detecting embedded LTTPRs (i.e. between host ASIC and the user-facing port), and thus need to calculate the correct DPCD address offset based on LTTPR count to target the appropriate LTTPR's DPCD register space with these queries. [HOW] Cascaded LTTPRs in a link each snoop and increment LTTPR count when queried via DPCD read, so an LTTPR embedded in a source device (e.g. USB4 port on a laptop) will always be addressible using the max LTTPR count seen by the host. Therefore we simply need to use a recently added helper function to calculate the correct DPCD address to target potentially embedded LTTPRs based on the received LTTPR count. Cc: Mario Limonciello <mario.limonciello@amd.com> Cc: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Wenjing Liu <wenjing.liu@amd.com> Signed-off-by: Michael Strauss <michael.strauss@amd.com> Signed-off-by: Alex Hung <alex.hung@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com> (cherry picked from commit 791897f) Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: José Expósito <jexposit@redhat.com>
1 parent 169eaf2 commit 749eb52

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,8 +1157,8 @@ struct dc_lttpr_caps {
11571157
union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates;
11581158
union dp_alpm_lttpr_cap alpm;
11591159
uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1];
1160-
uint8_t lttpr_ieee_oui[3];
1161-
uint8_t lttpr_device_id[6];
1160+
uint8_t lttpr_ieee_oui[3]; // Always read from closest LTTPR to host
1161+
uint8_t lttpr_device_id[6]; // Always read from closest LTTPR to host
11621162
};
11631163

11641164
struct dc_dongle_dfp_cap_ext {

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

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -385,9 +385,15 @@ bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx)
385385
bool dp_is_lttpr_present(struct dc_link *link)
386386
{
387387
/* Some sink devices report invalid LTTPR revision, so don't validate against that cap */
388-
return (dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 &&
388+
uint32_t lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
389+
bool is_lttpr_present = (lttpr_count > 0 &&
389390
link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
390391
link->dpcd_caps.lttpr_caps.max_lane_count <= 4);
392+
393+
if (lttpr_count > 0 && !is_lttpr_present)
394+
DC_LOG_ERROR("LTTPR count is nonzero but invalid lane count reported. Assuming no LTTPR present.\n");
395+
396+
return is_lttpr_present;
391397
}
392398

393399
/* in DP compliance test, DPR-120 may have
@@ -1551,6 +1557,8 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
15511557
uint8_t lttpr_dpcd_data[10] = {0};
15521558
enum dc_status status;
15531559
bool is_lttpr_present;
1560+
uint32_t lttpr_count;
1561+
uint32_t closest_lttpr_offset;
15541562

15551563
/* Logic to determine LTTPR support*/
15561564
bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
@@ -1602,32 +1610,48 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
16021610
lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES -
16031611
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV];
16041612

1613+
lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1614+
16051615
/* If this chip cap is set, at least one retimer must exist in the chain
16061616
* Override count to 1 if we receive a known bad count (0 or an invalid value) */
16071617
if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
1608-
(dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) {
1618+
lttpr_count == 0) {
16091619
/* If you see this message consistently, either the host platform has FIXED_VS flag
16101620
* incorrectly configured or the sink device is returning an invalid count.
16111621
*/
16121622
DC_LOG_ERROR("lttpr_caps phy_repeater_cnt is 0x%x, forcing it to 0x80.",
16131623
link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
16141624
link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80;
1625+
lttpr_count = 1;
16151626
DC_LOG_DC("lttpr_caps forced phy_repeater_cnt = %d\n", link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
16161627
}
16171628

1618-
/* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
16191629
is_lttpr_present = dp_is_lttpr_present(link);
16201630

16211631
DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present);
16221632

16231633
if (is_lttpr_present) {
16241634
CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
16251635

1626-
core_link_read_dpcd(link, DP_LTTPR_IEEE_OUI, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui));
1627-
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), "LTTPR IEEE OUI: ");
1636+
// Identify closest LTTPR to determine if workarounds required for known embedded LTTPR
1637+
closest_lttpr_offset = dp_get_closest_lttpr_offset(lttpr_count);
16281638

1629-
core_link_read_dpcd(link, DP_LTTPR_DEVICE_ID, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id));
1630-
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), "LTTPR Device ID: ");
1639+
core_link_read_dpcd(link, (DP_LTTPR_IEEE_OUI + closest_lttpr_offset),
1640+
link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui));
1641+
core_link_read_dpcd(link, (DP_LTTPR_DEVICE_ID + closest_lttpr_offset),
1642+
link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id));
1643+
1644+
if (lttpr_count > 1) {
1645+
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui),
1646+
"Closest LTTPR To Host's IEEE OUI: ");
1647+
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id),
1648+
"Closest LTTPR To Host's LTTPR Device ID: ");
1649+
} else {
1650+
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui),
1651+
"LTTPR IEEE OUI: ");
1652+
CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id),
1653+
"LTTPR Device ID: ");
1654+
}
16311655
}
16321656

16331657
return status;

0 commit comments

Comments
 (0)