diff options
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/amd/display/dc/dc_dp_types.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c | 38 | 
2 files changed, 33 insertions, 9 deletions
| diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h index 0bad8304ccf6..d346f8ae1634 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h @@ -1172,8 +1172,8 @@ struct dc_lttpr_caps {  	union dp_128b_132b_supported_lttpr_link_rates supported_128b_132b_rates;  	union dp_alpm_lttpr_cap alpm;  	uint8_t aux_rd_interval[MAX_REPEATER_CNT - 1]; -	uint8_t lttpr_ieee_oui[3]; -	uint8_t lttpr_device_id[6]; +	uint8_t lttpr_ieee_oui[3]; // Always read from closest LTTPR to host +	uint8_t lttpr_device_id[6]; // Always read from closest LTTPR to host  };  struct dc_dongle_dfp_cap_ext { diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index a5127c2d47ef..0f965380a9b4 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -385,9 +385,15 @@ bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx)  bool dp_is_lttpr_present(struct dc_link *link)  {  	/* Some sink devices report invalid LTTPR revision, so don't validate against that cap */ -	return (dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && +	uint32_t lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); +	bool is_lttpr_present = (lttpr_count > 0 &&  			link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&  			link->dpcd_caps.lttpr_caps.max_lane_count <= 4); + +	if (lttpr_count > 0 && !is_lttpr_present) +		DC_LOG_ERROR("LTTPR count is nonzero but invalid lane count reported. Assuming no LTTPR present.\n"); + +	return is_lttpr_present;  }  /* in DP compliance test, DPR-120 may have @@ -1551,6 +1557,8 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)  	uint8_t lttpr_dpcd_data[10] = {0};  	enum dc_status status;  	bool is_lttpr_present; +	uint32_t lttpr_count; +	uint32_t closest_lttpr_offset;  	/* Logic to determine LTTPR support*/  	bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; @@ -1602,20 +1610,22 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)  			lttpr_dpcd_data[DP_LTTPR_ALPM_CAPABILITIES -  							DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; +	lttpr_count = dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt); +  	/* If this chip cap is set, at least one retimer must exist in the chain  	 * Override count to 1 if we receive a known bad count (0 or an invalid value) */  	if (((link->chip_caps & AMD_EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK) == AMD_EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && -			(dp_parse_lttpr_repeater_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) { +			lttpr_count == 0) {  		/* If you see this message consistently, either the host platform has FIXED_VS flag  		 * incorrectly configured or the sink device is returning an invalid count.  		 */  		DC_LOG_ERROR("lttpr_caps phy_repeater_cnt is 0x%x, forcing it to 0x80.",  			     link->dpcd_caps.lttpr_caps.phy_repeater_cnt);  		link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80; +		lttpr_count = 1;  		DC_LOG_DC("lttpr_caps forced phy_repeater_cnt = %d\n", link->dpcd_caps.lttpr_caps.phy_repeater_cnt);  	} -	/* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */  	is_lttpr_present = dp_is_lttpr_present(link);  	DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present); @@ -1623,11 +1633,25 @@ enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)  	if (is_lttpr_present) {  		CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: "); -		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)); -		CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), "LTTPR IEEE OUI: "); +		// Identify closest LTTPR to determine if workarounds required for known embedded LTTPR +		closest_lttpr_offset = dp_get_closest_lttpr_offset(lttpr_count); -		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)); -		CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), "LTTPR Device ID: "); +		core_link_read_dpcd(link, (DP_LTTPR_IEEE_OUI + closest_lttpr_offset), +				link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui)); +		core_link_read_dpcd(link, (DP_LTTPR_DEVICE_ID + closest_lttpr_offset), +				link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id)); + +		if (lttpr_count > 1) { +			CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), +					"Closest LTTPR To Host's IEEE OUI: "); +			CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), +					"Closest LTTPR To Host's LTTPR Device ID: "); +		} else { +			CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_ieee_oui, sizeof(link->dpcd_caps.lttpr_caps.lttpr_ieee_oui), +					"LTTPR IEEE OUI: "); +			CONN_DATA_DETECT(link, link->dpcd_caps.lttpr_caps.lttpr_device_id, sizeof(link->dpcd_caps.lttpr_caps.lttpr_device_id), +					"LTTPR Device ID: "); +		}  	}  	return status; | 
