drm/amd/display: USB-C / thunderbolt dock specific workaround
reading dpcd 0x600 cause link loss for a particular USB-C dock with thurderbolt. workaround by avoiding dcpd 0x600 read unless it's necessary. Signed-off-by: Hersen Wu <hersenxs.wu@amd.com> Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> Acked-by: Harry Wentland <harry.wentland@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
320a127437
commit
97011249c3
@ -1512,7 +1512,7 @@ static bool hpd_rx_irq_check_link_loss_status(
|
|||||||
struct dc_link *link,
|
struct dc_link *link,
|
||||||
union hpd_irq_data *hpd_irq_dpcd_data)
|
union hpd_irq_data *hpd_irq_dpcd_data)
|
||||||
{
|
{
|
||||||
uint8_t irq_reg_rx_power_state;
|
uint8_t irq_reg_rx_power_state = 0;
|
||||||
enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
|
enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
|
||||||
union lane_status lane_status;
|
union lane_status lane_status;
|
||||||
uint32_t lane;
|
uint32_t lane;
|
||||||
@ -1524,60 +1524,55 @@ static bool hpd_rx_irq_check_link_loss_status(
|
|||||||
|
|
||||||
if (link->cur_link_settings.lane_count == 0)
|
if (link->cur_link_settings.lane_count == 0)
|
||||||
return return_code;
|
return return_code;
|
||||||
/*1. Check that we can handle interrupt: Not in FS DOS,
|
|
||||||
* Not in "Display Timeout" state, Link is trained.
|
|
||||||
*/
|
|
||||||
|
|
||||||
dpcd_result = core_link_read_dpcd(link,
|
/*1. Check that Link Status changed, before re-training.*/
|
||||||
DP_SET_POWER,
|
|
||||||
&irq_reg_rx_power_state,
|
|
||||||
sizeof(irq_reg_rx_power_state));
|
|
||||||
|
|
||||||
if (dpcd_result != DC_OK) {
|
/*parse lane status*/
|
||||||
irq_reg_rx_power_state = DP_SET_POWER_D0;
|
for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
|
||||||
dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
|
/* check status of lanes 0,1
|
||||||
"%s: DPCD read failed to obtain power state.\n",
|
* changed DpcdAddress_Lane01Status (0x202)
|
||||||
__func__);
|
*/
|
||||||
|
lane_status.raw = get_nibble_at_index(
|
||||||
|
&hpd_irq_dpcd_data->bytes.lane01_status.raw,
|
||||||
|
lane);
|
||||||
|
|
||||||
|
if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
|
||||||
|
!lane_status.bits.CR_DONE_0 ||
|
||||||
|
!lane_status.bits.SYMBOL_LOCKED_0) {
|
||||||
|
/* if one of the channel equalization, clock
|
||||||
|
* recovery or symbol lock is dropped
|
||||||
|
* consider it as (link has been
|
||||||
|
* dropped) dp sink status has changed
|
||||||
|
*/
|
||||||
|
sink_status_changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irq_reg_rx_power_state == DP_SET_POWER_D0) {
|
/* Check interlane align.*/
|
||||||
|
if (sink_status_changed ||
|
||||||
|
!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
|
||||||
|
|
||||||
/*2. Check that Link Status changed, before re-training.*/
|
dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
|
||||||
|
"%s: Link Status changed.\n", __func__);
|
||||||
|
|
||||||
/*parse lane status*/
|
return_code = true;
|
||||||
for (lane = 0;
|
|
||||||
lane < link->cur_link_settings.lane_count;
|
|
||||||
lane++) {
|
|
||||||
|
|
||||||
/* check status of lanes 0,1
|
/*2. Check that we can handle interrupt: Not in FS DOS,
|
||||||
* changed DpcdAddress_Lane01Status (0x202)*/
|
* Not in "Display Timeout" state, Link is trained.
|
||||||
lane_status.raw = get_nibble_at_index(
|
*/
|
||||||
&hpd_irq_dpcd_data->bytes.lane01_status.raw,
|
dpcd_result = core_link_read_dpcd(link,
|
||||||
lane);
|
DP_SET_POWER,
|
||||||
|
&irq_reg_rx_power_state,
|
||||||
if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
|
sizeof(irq_reg_rx_power_state));
|
||||||
!lane_status.bits.CR_DONE_0 ||
|
|
||||||
!lane_status.bits.SYMBOL_LOCKED_0) {
|
|
||||||
/* if one of the channel equalization, clock
|
|
||||||
* recovery or symbol lock is dropped
|
|
||||||
* consider it as (link has been
|
|
||||||
* dropped) dp sink status has changed*/
|
|
||||||
sink_status_changed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check interlane align.*/
|
|
||||||
if (sink_status_changed ||
|
|
||||||
!hpd_irq_dpcd_data->bytes.lane_status_updated.bits.
|
|
||||||
INTERLANE_ALIGN_DONE) {
|
|
||||||
|
|
||||||
|
if (dpcd_result != DC_OK) {
|
||||||
dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
|
dm_logger_write(link->ctx->logger, LOG_HW_HPD_IRQ,
|
||||||
"%s: Link Status changed.\n",
|
"%s: DPCD read failed to obtain power state.\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
} else {
|
||||||
return_code = true;
|
if (irq_reg_rx_power_state != DP_SET_POWER_D0)
|
||||||
|
return_code = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user