Skip to content

Commit ad5594a

Browse files
Michael Straussalexdeucher
authored andcommitted
drm/amd/display: Support Compliance Test Pattern Generation with DP2 Retimer
[WHY] Certain retimer requires workarounds in order to correctly output test patterns. [HOW] Add vendor-specific aux sequences to program retimer's TX and pattern generator when specific compliance test patterns are requested by sink. Note: SQ128 w/a in DPMF mode only works in one flip orientation currently Reviewed-by: Hansen Dsouza <hansen.dsouza@amd.com> Reviewed-by: Wenjing Liu <wenjing.liu@amd.com> Acked-by: Stylon Wang <stylon.wang@amd.com> Signed-off-by: Michael Strauss <michael.strauss@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent dba2429 commit ad5594a

17 files changed

Lines changed: 738 additions & 237 deletions

drivers/gpu/drm/amd/display/dc/core/dc_resource.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#include "link/hwss/link_hwss_dio.h"
4646
#include "link/hwss/link_hwss_dpia.h"
4747
#include "link/hwss/link_hwss_hpo_dp.h"
48+
#include "link/hwss/link_hwss_dio_fixed_vs_pe_retimer.h"
49+
#include "link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.h"
4850

4951
#if defined(CONFIG_DRM_AMD_DC_SI)
5052
#include "dce60/dce60_resource.h"
@@ -4198,11 +4200,13 @@ const struct link_hwss *get_link_hwss(const struct dc_link *link,
41984200
* with an hpo encoder. Or we can return a very dummy one that doesn't
41994201
* do work for all functions
42004202
*/
4201-
return get_hpo_dp_link_hwss();
4203+
return (requires_fixed_vs_pe_retimer_hpo_link_hwss(link) ?
4204+
get_hpo_fixed_vs_pe_retimer_dp_link_hwss() : get_hpo_dp_link_hwss());
42024205
else if (can_use_dpia_link_hwss(link, link_res))
42034206
return get_dpia_link_hwss();
42044207
else if (can_use_dio_link_hwss(link, link_res))
4205-
return get_dio_link_hwss();
4208+
return (requires_fixed_vs_pe_retimer_dio_link_hwss(link)) ?
4209+
get_dio_fixed_vs_pe_retimer_link_hwss() : get_dio_link_hwss();
42064210
else
42074211
return get_virtual_link_hwss();
42084212
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,7 @@ struct dc_link {
14981498
enum engine_id eng_id;
14991499

15001500
bool test_pattern_enabled;
1501+
enum dp_test_pattern current_test_pattern;
15011502
union compliance_test_state compliance_test_state;
15021503

15031504
void *priv;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ struct link_service {
179179
int (*aux_transfer_raw)(struct ddc_service *ddc,
180180
struct aux_payload *payload,
181181
enum aux_return_code_type *operation_result);
182+
bool (*configure_fixed_vs_pe_retimer)(
183+
struct ddc_service *ddc,
184+
const uint8_t *data,
185+
uint32_t len);
182186
bool (*aux_transfer_with_retries_no_mutex)(struct ddc_service *ddc,
183187
struct aux_payload *payload);
184188
bool (*is_in_aux_transaction_mode)(struct ddc_service *ddc);

drivers/gpu/drm/amd/display/dc/link/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ AMD_DISPLAY_FILES += $(AMD_DAL_LINK_ACCESSORIES)
4242
###############################################################################
4343
# hwss
4444
###############################################################################
45-
LINK_HWSS = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o
45+
LINK_HWSS = link_hwss_dio.o link_hwss_dpia.o link_hwss_hpo_dp.o \
46+
link_hwss_dio_fixed_vs_pe_retimer.o link_hwss_hpo_fixed_vs_pe_retimer_dp.o
4647

4748
AMD_DAL_LINK_HWSS = $(addprefix $(AMDDALPATH)/dc/link/hwss/, \
4849
$(LINK_HWSS))

drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ bool dp_set_test_pattern(
703703

704704
/* Reset Test Pattern state */
705705
link->test_pattern_enabled = false;
706+
link->current_test_pattern = test_pattern;
706707

707708
return true;
708709
}
@@ -740,6 +741,7 @@ bool dp_set_test_pattern(
740741
if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
741742
/* Set Test Pattern state */
742743
link->test_pattern_enabled = true;
744+
link->current_test_pattern = test_pattern;
743745
if (p_link_settings != NULL)
744746
dpcd_set_link_settings(link,
745747
p_link_settings);
@@ -938,6 +940,7 @@ bool dp_set_test_pattern(
938940

939941
/* Set Test Pattern state */
940942
link->test_pattern_enabled = true;
943+
link->current_test_pattern = test_pattern;
941944
}
942945

943946
return true;

drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ void set_dio_dp_lane_settings(struct dc_link *link,
166166
link_enc->funcs->dp_set_lane_settings(link_enc, link_settings, lane_settings);
167167
}
168168

169-
static void update_dio_stream_allocation_table(struct dc_link *link,
169+
void update_dio_stream_allocation_table(struct dc_link *link,
170170
const struct link_resource *link_res,
171171
const struct link_mst_stream_allocation_table *table)
172172
{

drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dio.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,8 @@ void setup_dio_audio_output(struct pipe_ctx *pipe_ctx,
5555
struct audio_output *audio_output, uint32_t audio_inst);
5656
void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx);
5757
void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx);
58+
void update_dio_stream_allocation_table(struct dc_link *link,
59+
const struct link_resource *link_res,
60+
const struct link_mst_stream_allocation_table *table);
5861

5962
#endif /* __LINK_HWSS_DIO_H__ */
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* Copyright 2023 Advanced Micro Devices, Inc.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17+
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18+
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20+
* OTHER DEALINGS IN THE SOFTWARE.
21+
*
22+
* Authors: AMD
23+
*
24+
*/
25+
#include "link_hwss_dio.h"
26+
#include "link_hwss_dio_fixed_vs_pe_retimer.h"
27+
#include "link_enc_cfg.h"
28+
29+
uint8_t dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(struct dc_link *link)
30+
{
31+
// TODO: Get USB-C cable orientation
32+
if (link->cur_link_settings.lane_count == LANE_COUNT_FOUR)
33+
return 0xF2;
34+
else
35+
return 0x12;
36+
}
37+
38+
void dp_dio_fixed_vs_pe_retimer_exit_manual_automation(struct dc_link *link)
39+
{
40+
const uint8_t dp_type = dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(link);
41+
const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06};
42+
const uint8_t vendor_lttpr_exit_manual_automation_1[4] = {0x1, 0x50, dp_type, 0x0};
43+
const uint8_t vendor_lttpr_exit_manual_automation_2[4] = {0x1, 0x50, 0x50, 0x0};
44+
const uint8_t vendor_lttpr_exit_manual_automation_3[4] = {0x1, 0x51, 0x50, 0x0};
45+
const uint8_t vendor_lttpr_exit_manual_automation_4[4] = {0x1, 0x10, 0x58, 0x0};
46+
const uint8_t vendor_lttpr_exit_manual_automation_5[4] = {0x1, 0x10, 0x59, 0x0};
47+
const uint8_t vendor_lttpr_exit_manual_automation_6[4] = {0x1, 0x30, 0x51, 0x0};
48+
const uint8_t vendor_lttpr_exit_manual_automation_7[4] = {0x1, 0x30, 0x52, 0x0};
49+
const uint8_t vendor_lttpr_exit_manual_automation_8[4] = {0x1, 0x30, 0x54, 0x0};
50+
const uint8_t vendor_lttpr_exit_manual_automation_9[4] = {0x1, 0x30, 0x55, 0x0};
51+
52+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
53+
&vendor_lttpr_exit_manual_automation_0[0], sizeof(vendor_lttpr_exit_manual_automation_0));
54+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
55+
&vendor_lttpr_exit_manual_automation_1[0], sizeof(vendor_lttpr_exit_manual_automation_1));
56+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
57+
&vendor_lttpr_exit_manual_automation_2[0], sizeof(vendor_lttpr_exit_manual_automation_2));
58+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
59+
&vendor_lttpr_exit_manual_automation_3[0], sizeof(vendor_lttpr_exit_manual_automation_3));
60+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
61+
&vendor_lttpr_exit_manual_automation_4[0], sizeof(vendor_lttpr_exit_manual_automation_4));
62+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
63+
&vendor_lttpr_exit_manual_automation_5[0], sizeof(vendor_lttpr_exit_manual_automation_5));
64+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
65+
&vendor_lttpr_exit_manual_automation_6[0], sizeof(vendor_lttpr_exit_manual_automation_6));
66+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
67+
&vendor_lttpr_exit_manual_automation_7[0], sizeof(vendor_lttpr_exit_manual_automation_7));
68+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
69+
&vendor_lttpr_exit_manual_automation_8[0], sizeof(vendor_lttpr_exit_manual_automation_8));
70+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
71+
&vendor_lttpr_exit_manual_automation_9[0], sizeof(vendor_lttpr_exit_manual_automation_9));
72+
}
73+
74+
static bool set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override(struct dc_link *link,
75+
const struct link_resource *link_res, struct encoder_set_dp_phy_pattern_param *tp_params,
76+
const struct link_hwss *link_hwss)
77+
{
78+
struct encoder_set_dp_phy_pattern_param hw_tp_params = { 0 };
79+
const uint8_t pltpat_custom[10] = {0x1F, 0x7C, 0xF0, 0xC1, 0x07, 0x1F, 0x7C, 0xF0, 0xC1, 0x07};
80+
const uint8_t vendor_lttpr_write_data_pg0[4] = {0x1, 0x11, 0x0, 0x0};
81+
const uint8_t vendor_lttpr_exit_manual_automation_0[4] = {0x1, 0x11, 0x0, 0x06};
82+
83+
84+
if (tp_params == NULL)
85+
return false;
86+
87+
if (link->current_test_pattern >= DP_TEST_PATTERN_SQUARE_BEGIN &&
88+
link->current_test_pattern <= DP_TEST_PATTERN_SQUARE_END) {
89+
// Deprogram overrides from previous test pattern
90+
dp_dio_fixed_vs_pe_retimer_exit_manual_automation(link);
91+
}
92+
93+
switch (tp_params->dp_phy_pattern) {
94+
case DP_TEST_PATTERN_80BIT_CUSTOM:
95+
if (tp_params->custom_pattern_size == 0 || memcmp(tp_params->custom_pattern,
96+
pltpat_custom, tp_params->custom_pattern_size) != 0)
97+
return false;
98+
break;
99+
case DP_TEST_PATTERN_D102:
100+
break;
101+
default:
102+
if (link->current_test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM ||
103+
link->current_test_pattern == DP_TEST_PATTERN_D102)
104+
// Deprogram overrides from previous test pattern
105+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
106+
&vendor_lttpr_exit_manual_automation_0[0],
107+
sizeof(vendor_lttpr_exit_manual_automation_0));
108+
109+
return false;
110+
}
111+
112+
hw_tp_params.dp_phy_pattern = tp_params->dp_phy_pattern;
113+
hw_tp_params.dp_panel_mode = tp_params->dp_panel_mode;
114+
115+
if (link_hwss->ext.set_dp_link_test_pattern)
116+
link_hwss->ext.set_dp_link_test_pattern(link, link_res, &hw_tp_params);
117+
118+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
119+
&vendor_lttpr_write_data_pg0[0], sizeof(vendor_lttpr_write_data_pg0));
120+
121+
return true;
122+
}
123+
124+
static void set_dio_fixed_vs_pe_retimer_dp_link_test_pattern(struct dc_link *link,
125+
const struct link_resource *link_res,
126+
struct encoder_set_dp_phy_pattern_param *tp_params)
127+
{
128+
struct link_encoder *link_enc = link_enc_cfg_get_link_enc(link);
129+
130+
if (!set_dio_fixed_vs_pe_retimer_dp_link_test_pattern_override(
131+
link, link_res, tp_params, get_dio_link_hwss())) {
132+
link_enc->funcs->dp_set_phy_pattern(link_enc, tp_params);
133+
}
134+
link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_SET_SOURCE_PATTERN);
135+
}
136+
137+
void enable_dio_fixed_vs_pe_retimer_program_4lane_output(struct dc_link *link)
138+
{
139+
const uint8_t vendor_lttpr_write_data_4lane_1[4] = {0x1, 0x6E, 0xF2, 0x19};
140+
const uint8_t vendor_lttpr_write_data_4lane_2[4] = {0x1, 0x6B, 0xF2, 0x01};
141+
const uint8_t vendor_lttpr_write_data_4lane_3[4] = {0x1, 0x6D, 0xF2, 0x18};
142+
const uint8_t vendor_lttpr_write_data_4lane_4[4] = {0x1, 0x6C, 0xF2, 0x03};
143+
const uint8_t vendor_lttpr_write_data_4lane_5[4] = {0x1, 0x03, 0xF3, 0x06};
144+
145+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
146+
&vendor_lttpr_write_data_4lane_1[0], sizeof(vendor_lttpr_write_data_4lane_1));
147+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
148+
&vendor_lttpr_write_data_4lane_2[0], sizeof(vendor_lttpr_write_data_4lane_2));
149+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
150+
&vendor_lttpr_write_data_4lane_3[0], sizeof(vendor_lttpr_write_data_4lane_3));
151+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
152+
&vendor_lttpr_write_data_4lane_4[0], sizeof(vendor_lttpr_write_data_4lane_4));
153+
link->dc->link_srv->configure_fixed_vs_pe_retimer(link->ddc,
154+
&vendor_lttpr_write_data_4lane_5[0], sizeof(vendor_lttpr_write_data_4lane_5));
155+
}
156+
157+
static void enable_dio_fixed_vs_pe_retimer_dp_link_output(struct dc_link *link,
158+
const struct link_resource *link_res,
159+
enum signal_type signal,
160+
enum clock_source_id clock_source,
161+
const struct dc_link_settings *link_settings)
162+
{
163+
if (link_settings->lane_count == LANE_COUNT_FOUR)
164+
enable_dio_fixed_vs_pe_retimer_program_4lane_output(link);
165+
166+
enable_dio_dp_link_output(link, link_res, signal, clock_source, link_settings);
167+
}
168+
169+
static const struct link_hwss dio_fixed_vs_pe_retimer_link_hwss = {
170+
.setup_stream_encoder = setup_dio_stream_encoder,
171+
.reset_stream_encoder = reset_dio_stream_encoder,
172+
.setup_stream_attribute = setup_dio_stream_attribute,
173+
.disable_link_output = disable_dio_link_output,
174+
.setup_audio_output = setup_dio_audio_output,
175+
.enable_audio_packet = enable_dio_audio_packet,
176+
.disable_audio_packet = disable_dio_audio_packet,
177+
.ext = {
178+
.set_throttled_vcp_size = set_dio_throttled_vcp_size,
179+
.enable_dp_link_output = enable_dio_fixed_vs_pe_retimer_dp_link_output,
180+
.set_dp_link_test_pattern = set_dio_fixed_vs_pe_retimer_dp_link_test_pattern,
181+
.set_dp_lane_settings = set_dio_dp_lane_settings,
182+
.update_stream_allocation_table = update_dio_stream_allocation_table,
183+
},
184+
};
185+
186+
bool requires_fixed_vs_pe_retimer_dio_link_hwss(const struct dc_link *link)
187+
{
188+
if (!(link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN))
189+
return false;
190+
191+
if (!link->dpcd_caps.lttpr_caps.main_link_channel_coding.bits.DP_128b_132b_SUPPORTED)
192+
return false;
193+
194+
return true;
195+
}
196+
197+
const struct link_hwss *get_dio_fixed_vs_pe_retimer_link_hwss(void)
198+
{
199+
return &dio_fixed_vs_pe_retimer_link_hwss;
200+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright 2023 Advanced Micro Devices, Inc.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a
5+
* copy of this software and associated documentation files (the "Software"),
6+
* to deal in the Software without restriction, including without limitation
7+
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8+
* and/or sell copies of the Software, and to permit persons to whom the
9+
* Software is furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17+
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18+
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20+
* OTHER DEALINGS IN THE SOFTWARE.
21+
*
22+
* Authors: AMD
23+
*
24+
*/
25+
#ifndef __LINK_HWSS_DIO_FIXED_VS_PE_RETIMER_H__
26+
#define __LINK_HWSS_DIO_FIXED_VS_PE_RETIMER_H__
27+
28+
#include "link.h"
29+
30+
uint32_t dp_dio_fixed_vs_pe_retimer_get_lttpr_write_address(struct dc_link *link);
31+
uint8_t dp_dio_fixed_vs_pe_retimer_lane_cfg_to_hw_cfg(struct dc_link *link);
32+
void dp_dio_fixed_vs_pe_retimer_exit_manual_automation(struct dc_link *link);
33+
void enable_dio_fixed_vs_pe_retimer_program_4lane_output(struct dc_link *link);
34+
bool requires_fixed_vs_pe_retimer_dio_link_hwss(const struct dc_link *link);
35+
const struct link_hwss *get_dio_fixed_vs_pe_retimer_link_hwss(void);
36+
37+
#endif /* __LINK_HWSS_DIO_FIXED_VS_PE_RETIMER_H__ */

0 commit comments

Comments
 (0)