Skip to content

Commit 2faa365

Browse files
Ilya Bakoulinalexdeucher
authored andcommitted
drm/amd/display: Work around bad DPCD state on link loss
[Why] This display doesn't properly indicate link loss through DPCD bits such as CR_DONE / CHANNEL_EQ_DONE / SYMBOL_LOCKED / INTERLANE_ALIGN_DONE, which all remain set. In addition, DPCD200Eh doesn't match the value of DPCD204h in all cases. For these reasons, we can miss re-training the link, since we don't properly detect link loss with this display. [Why] Add display-specific workaround to read DPCD204h, so that we can detect link loss based on 128b132b-specific status bits in this register. Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Reviewed-by: Wenjing Liu <wenjing.liu@amd.com> Acked-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com> Signed-off-by: Ilya Bakoulin <ilya.bakoulin@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 2036b34 commit 2faa365

2 files changed

Lines changed: 27 additions & 0 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,6 +1525,7 @@ struct dc_link {
15251525
bool dpia_forced_tbt3_mode;
15261526
bool dongle_mode_timing_override;
15271527
bool blank_stream_on_ocs_change;
1528+
bool read_dpcd204h_on_irq_hpd;
15281529
} wa_flags;
15291530
struct link_mst_stream_allocation_table mst_stream_alloc_table;
15301531

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,25 @@ void dp_handle_link_loss(struct dc_link *link)
208208
}
209209
}
210210

211+
static void read_dpcd204h_on_irq_hpd(struct dc_link *link, union hpd_irq_data *irq_data)
212+
{
213+
enum dc_status retval;
214+
union lane_align_status_updated dpcd_lane_status_updated;
215+
216+
retval = core_link_read_dpcd(
217+
link,
218+
DP_LANE_ALIGN_STATUS_UPDATED,
219+
&dpcd_lane_status_updated.raw,
220+
sizeof(union lane_align_status_updated));
221+
222+
if (retval == DC_OK) {
223+
irq_data->bytes.lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b =
224+
dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b;
225+
irq_data->bytes.lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b =
226+
dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b;
227+
}
228+
}
229+
211230
enum dc_status dp_read_hpd_rx_irq_data(
212231
struct dc_link *link,
213232
union hpd_irq_data *irq_data)
@@ -249,6 +268,13 @@ enum dc_status dp_read_hpd_rx_irq_data(
249268
irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI - DP_SINK_COUNT_ESI];
250269
irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI - DP_SINK_COUNT_ESI];
251270
irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI - DP_SINK_COUNT_ESI];
271+
272+
/*
273+
* This display doesn't have correct values in DPCD200Eh.
274+
* Read and check DPCD204h instead.
275+
*/
276+
if (link->wa_flags.read_dpcd204h_on_irq_hpd)
277+
read_dpcd204h_on_irq_hpd(link, irq_data);
252278
}
253279

254280
return retval;

0 commit comments

Comments
 (0)