drm/amd/display: Add work around for AUX failure on wake.
[Why] When waking from low-power states, a DP sink may remain unresponsive to AUX transactions. [How] Try to toggle DPCD SET_POWER register repeatedly (up to a maximum timeout value) until DP sink becomes responsive. Reviewed-by: Mustapha Ghaddar <Mustapha.Ghaddar@amd.com> Acked-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Jimmy Kizito <Jimmy.Kizito@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
a905f0b59f
commit
84d1ce0631
@ -5216,6 +5216,62 @@ static void retrieve_cable_id(struct dc_link *link)
|
|||||||
&link->dpcd_caps.cable_id, &usbc_cable_id);
|
&link->dpcd_caps.cable_id, &usbc_cable_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DPRX may take some time to respond to AUX messages after HPD asserted.
|
||||||
|
* If AUX read unsuccessful, try to wake unresponsive DPRX by toggling DPCD SET_POWER (0x600).
|
||||||
|
*/
|
||||||
|
static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout_ms)
|
||||||
|
{
|
||||||
|
enum dc_status status = DC_ERROR_UNEXPECTED;
|
||||||
|
uint8_t dpcd_data = 0;
|
||||||
|
uint64_t start_ts = 0;
|
||||||
|
uint64_t current_ts = 0;
|
||||||
|
uint64_t time_taken_ms = 0;
|
||||||
|
enum dc_connection_type type = dc_connection_none;
|
||||||
|
|
||||||
|
status = core_link_read_dpcd(
|
||||||
|
link,
|
||||||
|
DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
|
||||||
|
&dpcd_data,
|
||||||
|
sizeof(dpcd_data));
|
||||||
|
|
||||||
|
if (status != DC_OK) {
|
||||||
|
DC_LOG_WARNING("%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms.",
|
||||||
|
__func__,
|
||||||
|
timeout_ms);
|
||||||
|
start_ts = dm_get_timestamp(link->ctx);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (!dc_link_detect_sink(link, &type) || type == dc_connection_none)
|
||||||
|
break;
|
||||||
|
|
||||||
|
dpcd_data = DP_SET_POWER_D3;
|
||||||
|
status = core_link_write_dpcd(
|
||||||
|
link,
|
||||||
|
DP_SET_POWER,
|
||||||
|
&dpcd_data,
|
||||||
|
sizeof(dpcd_data));
|
||||||
|
|
||||||
|
dpcd_data = DP_SET_POWER_D0;
|
||||||
|
status = core_link_write_dpcd(
|
||||||
|
link,
|
||||||
|
DP_SET_POWER,
|
||||||
|
&dpcd_data,
|
||||||
|
sizeof(dpcd_data));
|
||||||
|
|
||||||
|
current_ts = dm_get_timestamp(link->ctx);
|
||||||
|
time_taken_ms = div_u64(dm_get_elapse_time_in_ns(link->ctx, current_ts, start_ts), 1000000);
|
||||||
|
} while (status != DC_OK && time_taken_ms < timeout_ms);
|
||||||
|
|
||||||
|
DC_LOG_WARNING("%s: DPCD SET_POWER %s after %lld ms%s",
|
||||||
|
__func__,
|
||||||
|
(status == DC_OK) ? "succeeded" : "failed",
|
||||||
|
time_taken_ms,
|
||||||
|
(type == dc_connection_none) ? ". Unplugged." : ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
static bool retrieve_link_cap(struct dc_link *link)
|
static bool retrieve_link_cap(struct dc_link *link)
|
||||||
{
|
{
|
||||||
/* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
|
/* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
|
||||||
@ -5251,6 +5307,9 @@ static bool retrieve_link_cap(struct dc_link *link)
|
|||||||
dc_link_aux_try_to_configure_timeout(link->ddc,
|
dc_link_aux_try_to_configure_timeout(link->ddc,
|
||||||
LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
|
LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
|
||||||
|
|
||||||
|
/* Try to ensure AUX channel active before proceeding. */
|
||||||
|
status = wa_try_to_wake_dprx(link, LINK_AUX_WAKE_TIMEOUT_MS);
|
||||||
|
|
||||||
is_lttpr_present = dp_retrieve_lttpr_cap(link);
|
is_lttpr_present = dp_retrieve_lttpr_cap(link);
|
||||||
/* Read DP tunneling information. */
|
/* Read DP tunneling information. */
|
||||||
status = dpcd_get_tunneling_device_data(link);
|
status = dpcd_get_tunneling_device_data(link);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#define MAX_MTP_SLOT_COUNT 64
|
#define MAX_MTP_SLOT_COUNT 64
|
||||||
#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
|
#define DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE 0x50
|
||||||
#define TRAINING_AUX_RD_INTERVAL 100 //us
|
#define TRAINING_AUX_RD_INTERVAL 100 //us
|
||||||
|
#define LINK_AUX_WAKE_TIMEOUT_MS 1500 // Timeout when trying to wake unresponsive DPRX.
|
||||||
|
|
||||||
struct dc_link;
|
struct dc_link;
|
||||||
struct dc_stream_state;
|
struct dc_stream_state;
|
||||||
|
Loading…
Reference in New Issue
Block a user