Bug Summary

File:dev/pci/drm/amd/display/dc/core/dc_link_dp.c
Warning:line 2495, column 5
Value stored to 'status' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name dc_link_dp.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c
1/*
2 * Copyright 2015 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#include "dm_services.h"
25#include "dc.h"
26#include "dc_link_dp.h"
27#include "dm_helpers.h"
28#include "opp.h"
29#include "dsc.h"
30#include "clk_mgr.h"
31#include "resource.h"
32
33#include "inc/core_types.h"
34#include "link_hwss.h"
35#include "dc_link_ddc.h"
36#include "core_status.h"
37#include "dpcd_defs.h"
38#include "dc_dmub_srv.h"
39#include "dce/dmub_hw_lock_mgr.h"
40#include "inc/dc_link_dpia.h"
41#include "inc/link_enc_cfg.h"
42#include "link/link_dp_trace.h"
43
44/*Travis*/
45static const uint8_t DP_VGA_LVDS_CONVERTER_ID_2[] = "sivarT";
46/*Nutmeg*/
47static const uint8_t DP_VGA_LVDS_CONVERTER_ID_3[] = "dnomlA";
48
49#define DC_LOGGERlink->ctx->logger \
50 link->ctx->logger
51#define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */
52
53#include "link_dpcd.h"
54
55#ifndef MAX
56#define MAX(X, Y)(((X)>(Y))?(X):(Y)) ((X) > (Y) ? (X) : (Y))
57#endif
58#ifndef MIN
59#define MIN(X, Y)(((X)<(Y))?(X):(Y)) ((X) < (Y) ? (X) : (Y))
60#endif
61
62 /* maximum pre emphasis level allowed for each voltage swing level*/
63 static const enum dc_pre_emphasis
64 voltage_swing_to_pre_emphasis[] = { PRE_EMPHASIS_LEVEL3,
65 PRE_EMPHASIS_LEVEL2,
66 PRE_EMPHASIS_LEVEL1,
67 PRE_EMPHASIS_DISABLED };
68
69enum {
70 POST_LT_ADJ_REQ_LIMIT = 6,
71 POST_LT_ADJ_REQ_TIMEOUT = 200
72};
73
74struct dp_lt_fallback_entry {
75 enum dc_lane_count lane_count;
76 enum dc_link_rate link_rate;
77};
78
79static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = {
80 /* This link training fallback array is ordered by
81 * link bandwidth from highest to lowest.
82 * DP specs makes it a normative policy to always
83 * choose the next highest link bandwidth during
84 * link training fallback.
85 */
86 {LANE_COUNT_FOUR, LINK_RATE_UHBR20},
87 {LANE_COUNT_FOUR, LINK_RATE_UHBR13_5},
88 {LANE_COUNT_TWO, LINK_RATE_UHBR20},
89 {LANE_COUNT_FOUR, LINK_RATE_UHBR10},
90 {LANE_COUNT_TWO, LINK_RATE_UHBR13_5},
91 {LANE_COUNT_FOUR, LINK_RATE_HIGH3},
92 {LANE_COUNT_ONE, LINK_RATE_UHBR20},
93 {LANE_COUNT_TWO, LINK_RATE_UHBR10},
94 {LANE_COUNT_FOUR, LINK_RATE_HIGH2},
95 {LANE_COUNT_ONE, LINK_RATE_UHBR13_5},
96 {LANE_COUNT_TWO, LINK_RATE_HIGH3},
97 {LANE_COUNT_ONE, LINK_RATE_UHBR10},
98 {LANE_COUNT_TWO, LINK_RATE_HIGH2},
99 {LANE_COUNT_FOUR, LINK_RATE_HIGH},
100 {LANE_COUNT_ONE, LINK_RATE_HIGH3},
101 {LANE_COUNT_FOUR, LINK_RATE_LOW},
102 {LANE_COUNT_ONE, LINK_RATE_HIGH2},
103 {LANE_COUNT_TWO, LINK_RATE_HIGH},
104 {LANE_COUNT_TWO, LINK_RATE_LOW},
105 {LANE_COUNT_ONE, LINK_RATE_HIGH},
106 {LANE_COUNT_ONE, LINK_RATE_LOW},
107};
108
109static const struct dc_link_settings fail_safe_link_settings = {
110 .lane_count = LANE_COUNT_ONE,
111 .link_rate = LINK_RATE_LOW,
112 .link_spread = LINK_SPREAD_DISABLED,
113};
114
115static bool_Bool decide_fallback_link_setting(
116 struct dc_link *link,
117 struct dc_link_settings *max,
118 struct dc_link_settings *cur,
119 enum link_training_result training_result);
120static void maximize_lane_settings(const struct link_training_settings *lt_settings,
121 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
122static void override_lane_settings(const struct link_training_settings *lt_settings,
123 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
124
125static uint32_t get_cr_training_aux_rd_interval(struct dc_link *link,
126 const struct dc_link_settings *link_settings)
127{
128 union training_aux_rd_interval training_rd_interval;
129 uint32_t wait_in_micro_secs = 100;
130
131 memset(&training_rd_interval, 0, sizeof(training_rd_interval))__builtin_memset((&training_rd_interval), (0), (sizeof(training_rd_interval
)))
;
132 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
133 link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
134 core_link_read_dpcd(
135 link,
136 DP_TRAINING_AUX_RD_INTERVAL0x00e,
137 (uint8_t *)&training_rd_interval,
138 sizeof(training_rd_interval));
139 if (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL)
140 wait_in_micro_secs = training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL * 4000;
141 }
142
143 return wait_in_micro_secs;
144}
145
146static uint32_t get_eq_training_aux_rd_interval(
147 struct dc_link *link,
148 const struct dc_link_settings *link_settings)
149{
150 union training_aux_rd_interval training_rd_interval;
151
152 memset(&training_rd_interval, 0, sizeof(training_rd_interval))__builtin_memset((&training_rd_interval), (0), (sizeof(training_rd_interval
)))
;
153 if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
154 core_link_read_dpcd(
155 link,
156 DP_128b_132b_TRAINING_AUX_RD_INTERVAL0x2216,
157 (uint8_t *)&training_rd_interval,
158 sizeof(training_rd_interval));
159 } else if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING &&
160 link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
161 core_link_read_dpcd(
162 link,
163 DP_TRAINING_AUX_RD_INTERVAL0x00e,
164 (uint8_t *)&training_rd_interval,
165 sizeof(training_rd_interval));
166 }
167
168 switch (training_rd_interval.bits.TRAINIG_AUX_RD_INTERVAL) {
169 case 0: return 400;
170 case 1: return 4000;
171 case 2: return 8000;
172 case 3: return 12000;
173 case 4: return 16000;
174 case 5: return 32000;
175 case 6: return 64000;
176 default: return 400;
177 }
178}
179
180void dp_wait_for_training_aux_rd_interval(
181 struct dc_link *link,
182 uint32_t wait_in_micro_secs)
183{
184 if (wait_in_micro_secs > 1000)
185 drm_msleep(wait_in_micro_secs/1000)mdelay(wait_in_micro_secs/1000);
186 else
187 udelay(wait_in_micro_secs);
188
189 DC_LOG_HW_LINK_TRAINING("%s:\n wait = %d\n",do { } while(0)
190 __func__,do { } while(0)
191 wait_in_micro_secs)do { } while(0);
192}
193
194enum dpcd_training_patterns
195 dc_dp_training_pattern_to_dpcd_training_pattern(
196 struct dc_link *link,
197 enum dc_dp_training_pattern pattern)
198{
199 enum dpcd_training_patterns dpcd_tr_pattern =
200 DPCD_TRAINING_PATTERN_VIDEOIDLE;
201
202 switch (pattern) {
203 case DP_TRAINING_PATTERN_SEQUENCE_1:
204 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_1;
205 break;
206 case DP_TRAINING_PATTERN_SEQUENCE_2:
207 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_2;
208 break;
209 case DP_TRAINING_PATTERN_SEQUENCE_3:
210 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_3;
211 break;
212 case DP_TRAINING_PATTERN_SEQUENCE_4:
213 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_4;
214 break;
215 case DP_128b_132b_TPS1:
216 dpcd_tr_pattern = DPCD_128b_132b_TPS1;
217 break;
218 case DP_128b_132b_TPS2:
219 dpcd_tr_pattern = DPCD_128b_132b_TPS2;
220 break;
221 case DP_128b_132b_TPS2_CDS:
222 dpcd_tr_pattern = DPCD_128b_132b_TPS2_CDS;
223 break;
224 case DP_TRAINING_PATTERN_VIDEOIDLE:
225 dpcd_tr_pattern = DPCD_TRAINING_PATTERN_VIDEOIDLE;
226 break;
227 default:
228 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 228); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
229 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",do { } while(0)
230 __func__, pattern)do { } while(0);
231 break;
232 }
233
234 return dpcd_tr_pattern;
235}
236
237static void dpcd_set_training_pattern(
238 struct dc_link *link,
239 enum dc_dp_training_pattern training_pattern)
240{
241 union dpcd_training_pattern dpcd_pattern = {0};
242
243 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
244 dc_dp_training_pattern_to_dpcd_training_pattern(
245 link, training_pattern);
246
247 core_link_write_dpcd(
248 link,
249 DP_TRAINING_PATTERN_SET0x102,
250 &dpcd_pattern.raw,
251 1);
252
253 DC_LOG_HW_LINK_TRAINING("%s\n %x pattern = %x\n",do { } while(0)
254 __func__,do { } while(0)
255 DP_TRAINING_PATTERN_SET,do { } while(0)
256 dpcd_pattern.v1_4.TRAINING_PATTERN_SET)do { } while(0);
257}
258
259static enum dc_dp_training_pattern decide_cr_training_pattern(
260 const struct dc_link_settings *link_settings)
261{
262 switch (dp_get_link_encoding_format(link_settings)) {
263 case DP_8b_10b_ENCODING:
264 default:
265 return DP_TRAINING_PATTERN_SEQUENCE_1;
266 case DP_128b_132b_ENCODING:
267 return DP_128b_132b_TPS1;
268 }
269}
270
271static enum dc_dp_training_pattern decide_eq_training_pattern(struct dc_link *link,
272 const struct dc_link_settings *link_settings)
273{
274 struct link_encoder *link_enc;
275 struct encoder_feature_support *enc_caps;
276 struct dpcd_caps *rx_caps = &link->dpcd_caps;
277 enum dc_dp_training_pattern pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
278
279 link_enc = link_enc_cfg_get_link_enc(link);
280 ASSERT(link_enc)do { if (({ static int __warned; int __ret = !!(!(link_enc));
if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(link_enc)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 280); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
281 enc_caps = &link_enc->features;
282
283 switch (dp_get_link_encoding_format(link_settings)) {
284 case DP_8b_10b_ENCODING:
285 if (enc_caps->flags.bits.IS_TPS4_CAPABLE &&
286 rx_caps->max_down_spread.bits.TPS4_SUPPORTED)
287 pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
288 else if (enc_caps->flags.bits.IS_TPS3_CAPABLE &&
289 rx_caps->max_ln_count.bits.TPS3_SUPPORTED)
290 pattern = DP_TRAINING_PATTERN_SEQUENCE_3;
291 else
292 pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
293 break;
294 case DP_128b_132b_ENCODING:
295 pattern = DP_128b_132b_TPS2;
296 break;
297 default:
298 pattern = DP_TRAINING_PATTERN_SEQUENCE_2;
299 break;
300 }
301 return pattern;
302}
303
304static uint8_t get_dpcd_link_rate(const struct dc_link_settings *link_settings)
305{
306 uint8_t link_rate = 0;
307 enum dp_link_encoding encoding = dp_get_link_encoding_format(link_settings);
308
309 if (encoding == DP_128b_132b_ENCODING)
310 switch (link_settings->link_rate) {
311 case LINK_RATE_UHBR10:
312 link_rate = 0x1;
313 break;
314 case LINK_RATE_UHBR20:
315 link_rate = 0x2;
316 break;
317 case LINK_RATE_UHBR13_5:
318 link_rate = 0x4;
319 break;
320 default:
321 link_rate = 0;
322 break;
323 }
324 else if (encoding == DP_8b_10b_ENCODING)
325 link_rate = (uint8_t) link_settings->link_rate;
326 else
327 link_rate = 0;
328
329 return link_rate;
330}
331
332static void dp_fixed_vs_pe_read_lane_adjust(
333 struct dc_link *link,
334 union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX])
335{
336 const uint8_t vendor_lttpr_write_data_vs[3] = {0x0, 0x53, 0x63};
337 const uint8_t vendor_lttpr_write_data_pe[3] = {0x0, 0x54, 0x63};
338 const uint8_t offset = dp_convert_to_count(
339 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
340 uint32_t vendor_lttpr_write_address = 0xF004F;
341 uint32_t vendor_lttpr_read_address = 0xF0053;
342 uint8_t dprx_vs = 0;
343 uint8_t dprx_pe = 0;
344 uint8_t lane;
345
346 if (offset != 0xFF) {
347 vendor_lttpr_write_address +=
348 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
349 vendor_lttpr_read_address +=
350 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
351 }
352
353 /* W/A to read lane settings requested by DPRX */
354 core_link_write_dpcd(
355 link,
356 vendor_lttpr_write_address,
357 &vendor_lttpr_write_data_vs[0],
358 sizeof(vendor_lttpr_write_data_vs));
359 core_link_read_dpcd(
360 link,
361 vendor_lttpr_read_address,
362 &dprx_vs,
363 1);
364 core_link_write_dpcd(
365 link,
366 vendor_lttpr_write_address,
367 &vendor_lttpr_write_data_pe[0],
368 sizeof(vendor_lttpr_write_data_pe));
369 core_link_read_dpcd(
370 link,
371 vendor_lttpr_read_address,
372 &dprx_pe,
373 1);
374
375 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
376 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET = (dprx_vs >> (2 * lane)) & 0x3;
377 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET = (dprx_pe >> (2 * lane)) & 0x3;
378 }
379}
380
381static void dp_fixed_vs_pe_set_retimer_lane_settings(
382 struct dc_link *link,
383 const union dpcd_training_lane dpcd_lane_adjust[LANE_COUNT_DP_MAX],
384 uint8_t lane_count)
385{
386 const uint8_t offset = dp_convert_to_count(
387 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
388 const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
389 uint32_t vendor_lttpr_write_address = 0xF004F;
390 uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
391 uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
392 uint8_t lane = 0;
393
394 if (offset != 0xFF) {
395 vendor_lttpr_write_address +=
396 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
397 }
398
399 for (lane = 0; lane < lane_count; lane++) {
400 vendor_lttpr_write_data_vs[3] |=
401 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
402 vendor_lttpr_write_data_pe[3] |=
403 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
404 }
405
406 /* Force LTTPR to output desired VS and PE */
407 core_link_write_dpcd(
408 link,
409 vendor_lttpr_write_address,
410 &vendor_lttpr_write_data_reset[0],
411 sizeof(vendor_lttpr_write_data_reset));
412 core_link_write_dpcd(
413 link,
414 vendor_lttpr_write_address,
415 &vendor_lttpr_write_data_vs[0],
416 sizeof(vendor_lttpr_write_data_vs));
417 core_link_write_dpcd(
418 link,
419 vendor_lttpr_write_address,
420 &vendor_lttpr_write_data_pe[0],
421 sizeof(vendor_lttpr_write_data_pe));
422}
423
424enum dc_status dpcd_set_link_settings(
425 struct dc_link *link,
426 const struct link_training_settings *lt_settings)
427{
428 uint8_t rate;
429 enum dc_status status;
430
431 union down_spread_ctrl downspread = {0};
432 union lane_count_set lane_count_set = {0};
433
434 downspread.raw = (uint8_t)
435 (lt_settings->link_settings.link_spread);
436
437 lane_count_set.bits.LANE_COUNT_SET =
438 lt_settings->link_settings.lane_count;
439
440 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
441 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
442
443
444 if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
445 lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
446 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
447 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
448 }
449
450 status = core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL0x107,
451 &downspread.raw, sizeof(downspread));
452
453 status = core_link_write_dpcd(link, DP_LANE_COUNT_SET0x101,
454 &lane_count_set.raw, 1);
455
456 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
457 lt_settings->link_settings.use_link_rate_set == true1) {
458 rate = 0;
459 /* WA for some MUX chips that will power down with eDP and lose supported
460 * link rate set for eDP 1.4. Source reads DPCD 0x010 again to ensure
461 * MUX chip gets link rate set back before link training.
462 */
463 if (link->connector_signal == SIGNAL_TYPE_EDP) {
464 uint8_t supported_link_rates[16];
465
466 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES0x010,
467 supported_link_rates, sizeof(supported_link_rates));
468 }
469 status = core_link_write_dpcd(link, DP_LINK_BW_SET0x100, &rate, 1);
470 status = core_link_write_dpcd(link, DP_LINK_RATE_SET0x115,
471 &lt_settings->link_settings.link_rate_set, 1);
472 } else {
473 rate = get_dpcd_link_rate(&lt_settings->link_settings);
474
475 status = core_link_write_dpcd(link, DP_LINK_BW_SET0x100, &rate, 1);
476 }
477
478 if (rate) {
479 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",do { } while(0)
480 __func__,do { } while(0)
481 DP_LINK_BW_SET,do { } while(0)
482 lt_settings->link_settings.link_rate,do { } while(0)
483 DP_LANE_COUNT_SET,do { } while(0)
484 lt_settings->link_settings.lane_count,do { } while(0)
485 lt_settings->enhanced_framing,do { } while(0)
486 DP_DOWNSPREAD_CTRL,do { } while(0)
487 lt_settings->link_settings.link_spread)do { } while(0);
488 } else {
489 DC_LOG_HW_LINK_TRAINING("%s\n %x rate set = %x\n %x lane = %x framing = %x\n %x spread = %x\n",do { } while(0)
490 __func__,do { } while(0)
491 DP_LINK_RATE_SET,do { } while(0)
492 lt_settings->link_settings.link_rate_set,do { } while(0)
493 DP_LANE_COUNT_SET,do { } while(0)
494 lt_settings->link_settings.lane_count,do { } while(0)
495 lt_settings->enhanced_framing,do { } while(0)
496 DP_DOWNSPREAD_CTRL,do { } while(0)
497 lt_settings->link_settings.link_spread)do { } while(0);
498 }
499
500 return status;
501}
502
503uint8_t dc_dp_initialize_scrambling_data_symbols(
504 struct dc_link *link,
505 enum dc_dp_training_pattern pattern)
506{
507 uint8_t disable_scrabled_data_symbols = 0;
508
509 switch (pattern) {
510 case DP_TRAINING_PATTERN_SEQUENCE_1:
511 case DP_TRAINING_PATTERN_SEQUENCE_2:
512 case DP_TRAINING_PATTERN_SEQUENCE_3:
513 disable_scrabled_data_symbols = 1;
514 break;
515 case DP_TRAINING_PATTERN_SEQUENCE_4:
516 case DP_128b_132b_TPS1:
517 case DP_128b_132b_TPS2:
518 disable_scrabled_data_symbols = 0;
519 break;
520 default:
521 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 521); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
522 DC_LOG_HW_LINK_TRAINING("%s: Invalid HW Training pattern: %d\n",do { } while(0)
523 __func__, pattern)do { } while(0);
524 break;
525 }
526 return disable_scrabled_data_symbols;
527}
528
529static inline bool_Bool is_repeater(const struct link_training_settings *lt_settings, uint32_t offset)
530{
531 return (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) && (offset != 0);
532}
533
534static void dpcd_set_lt_pattern_and_lane_settings(
535 struct dc_link *link,
536 const struct link_training_settings *lt_settings,
537 enum dc_dp_training_pattern pattern,
538 uint32_t offset)
539{
540 uint32_t dpcd_base_lt_offset;
541
542 uint8_t dpcd_lt_buffer[5] = {0};
543 union dpcd_training_pattern dpcd_pattern = {0};
544 uint32_t size_in_bytes;
545 bool_Bool edp_workaround = false0; /* TODO link_prop.INTERNAL */
546 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET0x102;
547
548 if (is_repeater(lt_settings, offset))
549 dpcd_base_lt_offset = DP_TRAINING_PATTERN_SET_PHY_REPEATER10xf0010 +
550 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
551
552 /*****************************************************************
553 * DpcdAddress_TrainingPatternSet
554 *****************************************************************/
555 dpcd_pattern.v1_4.TRAINING_PATTERN_SET =
556 dc_dp_training_pattern_to_dpcd_training_pattern(link, pattern);
557
558 dpcd_pattern.v1_4.SCRAMBLING_DISABLE =
559 dc_dp_initialize_scrambling_data_symbols(link, pattern);
560
561 dpcd_lt_buffer[DP_TRAINING_PATTERN_SET0x102 - DP_TRAINING_PATTERN_SET0x102]
562 = dpcd_pattern.raw;
563
564 if (is_repeater(lt_settings, offset)) {
565 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n 0x%X pattern = %x\n",do { } while(0)
566 __func__,do { } while(0)
567 offset,do { } while(0)
568 dpcd_base_lt_offset,do { } while(0)
569 dpcd_pattern.v1_4.TRAINING_PATTERN_SET)do { } while(0);
570 } else {
571 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X pattern = %x\n",do { } while(0)
572 __func__,do { } while(0)
573 dpcd_base_lt_offset,do { } while(0)
574 dpcd_pattern.v1_4.TRAINING_PATTERN_SET)do { } while(0);
575 }
576
577 /* concatenate everything into one buffer*/
578 size_in_bytes = lt_settings->link_settings.lane_count *
579 sizeof(lt_settings->dpcd_lane_settings[0]);
580
581 // 0x00103 - 0x00102
582 memmove(__builtin_memmove((&dpcd_lt_buffer[0x103 - 0x102]), (lt_settings
->dpcd_lane_settings), (size_in_bytes))
583 &dpcd_lt_buffer[DP_TRAINING_LANE0_SET - DP_TRAINING_PATTERN_SET],__builtin_memmove((&dpcd_lt_buffer[0x103 - 0x102]), (lt_settings
->dpcd_lane_settings), (size_in_bytes))
584 lt_settings->dpcd_lane_settings,__builtin_memmove((&dpcd_lt_buffer[0x103 - 0x102]), (lt_settings
->dpcd_lane_settings), (size_in_bytes))
585 size_in_bytes)__builtin_memmove((&dpcd_lt_buffer[0x103 - 0x102]), (lt_settings
->dpcd_lane_settings), (size_in_bytes))
;
586
587 if (is_repeater(lt_settings, offset)) {
588 if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
589 DP_128b_132b_ENCODING)
590 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"do { } while(0)
591 " 0x%X TX_FFE_PRESET_VALUE = %x\n",do { } while(0)
592 __func__,do { } while(0)
593 offset,do { } while(0)
594 dpcd_base_lt_offset,do { } while(0)
595 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE)do { } while(0);
596 else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
597 DP_8b_10b_ENCODING)
598 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"do { } while(0)
599 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",do { } while(0)
600 __func__,do { } while(0)
601 offset,do { } while(0)
602 dpcd_base_lt_offset,do { } while(0)
603 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,do { } while(0)
604 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,do { } while(0)
605 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,do { } while(0)
606 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED)do { } while(0);
607 } else {
608 if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
609 DP_128b_132b_ENCODING)
610 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",do { } while(0)
611 __func__,do { } while(0)
612 dpcd_base_lt_offset,do { } while(0)
613 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE)do { } while(0);
614 else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
615 DP_8b_10b_ENCODING)
616 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",do { } while(0)
617 __func__,do { } while(0)
618 dpcd_base_lt_offset,do { } while(0)
619 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,do { } while(0)
620 lt_settings->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,do { } while(0)
621 lt_settings->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,do { } while(0)
622 lt_settings->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED)do { } while(0);
623 }
624 if (edp_workaround) {
625 /* for eDP write in 2 parts because the 5-byte burst is
626 * causing issues on some eDP panels (EPR#366724)
627 */
628 core_link_write_dpcd(
629 link,
630 DP_TRAINING_PATTERN_SET0x102,
631 &dpcd_pattern.raw,
632 sizeof(dpcd_pattern.raw));
633
634 core_link_write_dpcd(
635 link,
636 DP_TRAINING_LANE0_SET0x103,
637 (uint8_t *)(lt_settings->dpcd_lane_settings),
638 size_in_bytes);
639
640 } else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
641 DP_128b_132b_ENCODING) {
642 core_link_write_dpcd(
643 link,
644 dpcd_base_lt_offset,
645 dpcd_lt_buffer,
646 sizeof(dpcd_lt_buffer));
647 } else
648 /* write it all in (1 + number-of-lanes)-byte burst*/
649 core_link_write_dpcd(
650 link,
651 dpcd_base_lt_offset,
652 dpcd_lt_buffer,
653 size_in_bytes + sizeof(dpcd_pattern.raw));
654}
655
656bool_Bool dp_is_cr_done(enum dc_lane_count ln_count,
657 union lane_status *dpcd_lane_status)
658{
659 uint32_t lane;
660 /*LANEx_CR_DONE bits All 1's?*/
661 for (lane = 0; lane < (uint32_t)(ln_count); lane++) {
662 if (!dpcd_lane_status[lane].bits.CR_DONE_0)
663 return false0;
664 }
665 return true1;
666}
667
668bool_Bool dp_is_ch_eq_done(enum dc_lane_count ln_count,
669 union lane_status *dpcd_lane_status)
670{
671 bool_Bool done = true1;
672 uint32_t lane;
673 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
674 if (!dpcd_lane_status[lane].bits.CHANNEL_EQ_DONE_0)
675 done = false0;
676 return done;
677}
678
679bool_Bool dp_is_symbol_locked(enum dc_lane_count ln_count,
680 union lane_status *dpcd_lane_status)
681{
682 bool_Bool locked = true1;
683 uint32_t lane;
684 for (lane = 0; lane < (uint32_t)(ln_count); lane++)
685 if (!dpcd_lane_status[lane].bits.SYMBOL_LOCKED_0)
686 locked = false0;
687 return locked;
688}
689
690bool_Bool dp_is_interlane_aligned(union lane_align_status_updated align_status)
691{
692 return align_status.bits.INTERLANE_ALIGN_DONE == 1;
693}
694
695void dp_hw_to_dpcd_lane_settings(
696 const struct link_training_settings *lt_settings,
697 const struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
698 union dpcd_training_lane dpcd_lane_settings[])
699{
700 uint8_t lane = 0;
701
702 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
703 if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
704 DP_8b_10b_ENCODING) {
705 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET =
706 (uint8_t)(hw_lane_settings[lane].VOLTAGE_SWING);
707 dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET =
708 (uint8_t)(hw_lane_settings[lane].PRE_EMPHASIS);
709 dpcd_lane_settings[lane].bits.MAX_SWING_REACHED =
710 (hw_lane_settings[lane].VOLTAGE_SWING ==
711 VOLTAGE_SWING_MAX_LEVEL ? 1 : 0);
712 dpcd_lane_settings[lane].bits.MAX_PRE_EMPHASIS_REACHED =
713 (hw_lane_settings[lane].PRE_EMPHASIS ==
714 PRE_EMPHASIS_MAX_LEVEL ? 1 : 0);
715 }
716 else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
717 DP_128b_132b_ENCODING) {
718 dpcd_lane_settings[lane].tx_ffe.PRESET_VALUE =
719 hw_lane_settings[lane].FFE_PRESET.settings.level;
720 }
721 }
722}
723
724void dp_decide_lane_settings(
725 const struct link_training_settings *lt_settings,
726 const union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
727 struct dc_lane_settings hw_lane_settings[LANE_COUNT_DP_MAX],
728 union dpcd_training_lane dpcd_lane_settings[])
729{
730 uint32_t lane;
731
732 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
733 if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
734 DP_8b_10b_ENCODING) {
735 hw_lane_settings[lane].VOLTAGE_SWING =
736 (enum dc_voltage_swing)(ln_adjust[lane].bits.
737 VOLTAGE_SWING_LANE);
738 hw_lane_settings[lane].PRE_EMPHASIS =
739 (enum dc_pre_emphasis)(ln_adjust[lane].bits.
740 PRE_EMPHASIS_LANE);
741 }
742 else if (dp_get_link_encoding_format(&lt_settings->link_settings) ==
743 DP_128b_132b_ENCODING) {
744 hw_lane_settings[lane].FFE_PRESET.raw =
745 ln_adjust[lane].tx_ffe.PRESET_VALUE;
746 }
747 }
748 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
749
750 if (lt_settings->disallow_per_lane_settings) {
751 /* we find the maximum of the requested settings across all lanes*/
752 /* and set this maximum for all lanes*/
753 maximize_lane_settings(lt_settings, hw_lane_settings);
754 override_lane_settings(lt_settings, hw_lane_settings);
755
756 if (lt_settings->always_match_dpcd_with_hw_lane_settings)
757 dp_hw_to_dpcd_lane_settings(lt_settings, hw_lane_settings, dpcd_lane_settings);
758 }
759
760}
761
762static uint8_t get_nibble_at_index(const uint8_t *buf,
763 uint32_t index)
764{
765 uint8_t nibble;
766 nibble = buf[index / 2];
767
768 if (index % 2)
769 nibble >>= 4;
770 else
771 nibble &= 0x0F;
772
773 return nibble;
774}
775
776static enum dc_pre_emphasis get_max_pre_emphasis_for_voltage_swing(
777 enum dc_voltage_swing voltage)
778{
779 enum dc_pre_emphasis pre_emphasis;
780 pre_emphasis = PRE_EMPHASIS_MAX_LEVEL;
781
782 if (voltage <= VOLTAGE_SWING_MAX_LEVEL)
783 pre_emphasis = voltage_swing_to_pre_emphasis[voltage];
784
785 return pre_emphasis;
786
787}
788
789static void maximize_lane_settings(const struct link_training_settings *lt_settings,
790 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
791{
792 uint32_t lane;
793 struct dc_lane_settings max_requested;
794
795 max_requested.VOLTAGE_SWING = lane_settings[0].VOLTAGE_SWING;
796 max_requested.PRE_EMPHASIS = lane_settings[0].PRE_EMPHASIS;
797 max_requested.FFE_PRESET = lane_settings[0].FFE_PRESET;
798
799 /* Determine what the maximum of the requested settings are*/
800 for (lane = 1; lane < lt_settings->link_settings.lane_count; lane++) {
801 if (lane_settings[lane].VOLTAGE_SWING > max_requested.VOLTAGE_SWING)
802 max_requested.VOLTAGE_SWING = lane_settings[lane].VOLTAGE_SWING;
803
804 if (lane_settings[lane].PRE_EMPHASIS > max_requested.PRE_EMPHASIS)
805 max_requested.PRE_EMPHASIS = lane_settings[lane].PRE_EMPHASIS;
806 if (lane_settings[lane].FFE_PRESET.settings.level >
807 max_requested.FFE_PRESET.settings.level)
808 max_requested.FFE_PRESET.settings.level =
809 lane_settings[lane].FFE_PRESET.settings.level;
810 }
811
812 /* make sure the requested settings are
813 * not higher than maximum settings*/
814 if (max_requested.VOLTAGE_SWING > VOLTAGE_SWING_MAX_LEVEL)
815 max_requested.VOLTAGE_SWING = VOLTAGE_SWING_MAX_LEVEL;
816
817 if (max_requested.PRE_EMPHASIS > PRE_EMPHASIS_MAX_LEVEL)
818 max_requested.PRE_EMPHASIS = PRE_EMPHASIS_MAX_LEVEL;
819 if (max_requested.FFE_PRESET.settings.level > DP_FFE_PRESET_MAX_LEVEL)
820 max_requested.FFE_PRESET.settings.level = DP_FFE_PRESET_MAX_LEVEL;
821
822 /* make sure the pre-emphasis matches the voltage swing*/
823 if (max_requested.PRE_EMPHASIS >
824 get_max_pre_emphasis_for_voltage_swing(
825 max_requested.VOLTAGE_SWING))
826 max_requested.PRE_EMPHASIS =
827 get_max_pre_emphasis_for_voltage_swing(
828 max_requested.VOLTAGE_SWING);
829
830 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
831 lane_settings[lane].VOLTAGE_SWING = max_requested.VOLTAGE_SWING;
832 lane_settings[lane].PRE_EMPHASIS = max_requested.PRE_EMPHASIS;
833 lane_settings[lane].FFE_PRESET = max_requested.FFE_PRESET;
834 }
835}
836
837static void override_lane_settings(const struct link_training_settings *lt_settings,
838 struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
839{
840 uint32_t lane;
841
842 if (lt_settings->voltage_swing == NULL((void *)0) &&
843 lt_settings->pre_emphasis == NULL((void *)0) &&
844 lt_settings->ffe_preset == NULL((void *)0) &&
845 lt_settings->post_cursor2 == NULL((void *)0))
846
847 return;
848
849 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
850 if (lt_settings->voltage_swing)
851 lane_settings[lane].VOLTAGE_SWING = *lt_settings->voltage_swing;
852 if (lt_settings->pre_emphasis)
853 lane_settings[lane].PRE_EMPHASIS = *lt_settings->pre_emphasis;
854 if (lt_settings->post_cursor2)
855 lane_settings[lane].POST_CURSOR2 = *lt_settings->post_cursor2;
856 if (lt_settings->ffe_preset)
857 lane_settings[lane].FFE_PRESET = *lt_settings->ffe_preset;
858 }
859}
860
861enum dc_status dp_get_lane_status_and_lane_adjust(
862 struct dc_link *link,
863 const struct link_training_settings *link_training_setting,
864 union lane_status ln_status[LANE_COUNT_DP_MAX],
865 union lane_align_status_updated *ln_align,
866 union lane_adjust ln_adjust[LANE_COUNT_DP_MAX],
867 uint32_t offset)
868{
869 unsigned int lane01_status_address = DP_LANE0_1_STATUS0x202;
870 uint8_t lane_adjust_offset = 4;
871 unsigned int lane01_adjust_address;
872 uint8_t dpcd_buf[6] = {0};
873 uint32_t lane;
874 enum dc_status status;
875
876 if (is_repeater(link_training_setting, offset)) {
877 lane01_status_address =
878 DP_LANE0_1_STATUS_PHY_REPEATER10xf0030 +
879 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
880 lane_adjust_offset = 3;
881 }
882
883 status = core_link_read_dpcd(
884 link,
885 lane01_status_address,
886 (uint8_t *)(dpcd_buf),
887 sizeof(dpcd_buf));
888
889 if (status != DC_OK) {
890 DC_LOG_HW_LINK_TRAINING("%s:\n Failed to read from address 0x%X,"do { } while(0)
891 " keep current lane status and lane adjust unchanged",do { } while(0)
892 __func__,do { } while(0)
893 lane01_status_address)do { } while(0);
894 return status;
895 }
896
897 for (lane = 0; lane <
898 (uint32_t)(link_training_setting->link_settings.lane_count);
899 lane++) {
900
901 ln_status[lane].raw =
902 get_nibble_at_index(&dpcd_buf[0], lane);
903 ln_adjust[lane].raw =
904 get_nibble_at_index(&dpcd_buf[lane_adjust_offset], lane);
905 }
906
907 ln_align->raw = dpcd_buf[2];
908
909 if (is_repeater(link_training_setting, offset)) {
910 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"do { } while(0)
911 " 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",do { } while(0)
912 __func__,do { } while(0)
913 offset,do { } while(0)
914 lane01_status_address, dpcd_buf[0],do { } while(0)
915 lane01_status_address + 1, dpcd_buf[1])do { } while(0);
916
917 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_1_PHY_REPEATER10xf0033 +
918 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
919
920 DC_LOG_HW_LINK_TRAINING("%s:\n LTTPR Repeater ID: %d\n"do { } while(0)
921 " 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",do { } while(0)
922 __func__,do { } while(0)
923 offset,do { } while(0)
924 lane01_adjust_address,do { } while(0)
925 dpcd_buf[lane_adjust_offset],do { } while(0)
926 lane01_adjust_address + 1,do { } while(0)
927 dpcd_buf[lane_adjust_offset + 1])do { } while(0);
928 } else {
929 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01Status = %x\n 0x%X Lane23Status = %x\n ",do { } while(0)
930 __func__,do { } while(0)
931 lane01_status_address, dpcd_buf[0],do { } while(0)
932 lane01_status_address + 1, dpcd_buf[1])do { } while(0);
933
934 lane01_adjust_address = DP_ADJUST_REQUEST_LANE0_10x206;
935
936 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X Lane01AdjustRequest = %x\n 0x%X Lane23AdjustRequest = %x\n",do { } while(0)
937 __func__,do { } while(0)
938 lane01_adjust_address,do { } while(0)
939 dpcd_buf[lane_adjust_offset],do { } while(0)
940 lane01_adjust_address + 1,do { } while(0)
941 dpcd_buf[lane_adjust_offset + 1])do { } while(0);
942 }
943
944 return status;
945}
946
947static enum dc_status dpcd_128b_132b_set_lane_settings(
948 struct dc_link *link,
949 const struct link_training_settings *link_training_setting)
950{
951 enum dc_status status = core_link_write_dpcd(link,
952 DP_TRAINING_LANE0_SET0x103,
953 (uint8_t *)(link_training_setting->dpcd_lane_settings),
954 sizeof(link_training_setting->dpcd_lane_settings));
955
956 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X TX_FFE_PRESET_VALUE = %x\n",do { } while(0)
957 __func__,do { } while(0)
958 DP_TRAINING_LANE0_SET,do { } while(0)
959 link_training_setting->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE)do { } while(0);
960 return status;
961}
962
963
964enum dc_status dpcd_set_lane_settings(
965 struct dc_link *link,
966 const struct link_training_settings *link_training_setting,
967 uint32_t offset)
968{
969 unsigned int lane0_set_address;
970 enum dc_status status;
971
972 lane0_set_address = DP_TRAINING_LANE0_SET0x103;
973
974 if (is_repeater(link_training_setting, offset))
975 lane0_set_address = DP_TRAINING_LANE0_SET_PHY_REPEATER10xf0011 +
976 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
977
978 status = core_link_write_dpcd(link,
979 lane0_set_address,
980 (uint8_t *)(link_training_setting->dpcd_lane_settings),
981 link_training_setting->link_settings.lane_count);
982
983 if (is_repeater(link_training_setting, offset)) {
984 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Repeater ID: %d\n"do { } while(0)
985 " 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",do { } while(0)
986 __func__,do { } while(0)
987 offset,do { } while(0)
988 lane0_set_address,do { } while(0)
989 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,do { } while(0)
990 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,do { } while(0)
991 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,do { } while(0)
992 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED)do { } while(0);
993
994 } else {
995 DC_LOG_HW_LINK_TRAINING("%s\n 0x%X VS set = %x PE set = %x max VS Reached = %x max PE Reached = %x\n",do { } while(0)
996 __func__,do { } while(0)
997 lane0_set_address,do { } while(0)
998 link_training_setting->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET,do { } while(0)
999 link_training_setting->dpcd_lane_settings[0].bits.PRE_EMPHASIS_SET,do { } while(0)
1000 link_training_setting->dpcd_lane_settings[0].bits.MAX_SWING_REACHED,do { } while(0)
1001 link_training_setting->dpcd_lane_settings[0].bits.MAX_PRE_EMPHASIS_REACHED)do { } while(0);
1002 }
1003
1004 return status;
1005}
1006
1007bool_Bool dp_is_max_vs_reached(
1008 const struct link_training_settings *lt_settings)
1009{
1010 uint32_t lane;
1011 for (lane = 0; lane <
1012 (uint32_t)(lt_settings->link_settings.lane_count);
1013 lane++) {
1014 if (lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET
1015 == VOLTAGE_SWING_MAX_LEVEL)
1016 return true1;
1017 }
1018 return false0;
1019
1020}
1021
1022static bool_Bool perform_post_lt_adj_req_sequence(
1023 struct dc_link *link,
1024 const struct link_resource *link_res,
1025 struct link_training_settings *lt_settings)
1026{
1027 enum dc_lane_count lane_count =
1028 lt_settings->link_settings.lane_count;
1029
1030 uint32_t adj_req_count;
1031 uint32_t adj_req_timer;
1032 bool_Bool req_drv_setting_changed;
1033 uint32_t lane;
1034 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1035 union lane_align_status_updated dpcd_lane_status_updated = {0};
1036 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1037
1038 req_drv_setting_changed = false0;
1039 for (adj_req_count = 0; adj_req_count < POST_LT_ADJ_REQ_LIMIT;
1040 adj_req_count++) {
1041
1042 req_drv_setting_changed = false0;
1043
1044 for (adj_req_timer = 0;
1045 adj_req_timer < POST_LT_ADJ_REQ_TIMEOUT;
1046 adj_req_timer++) {
1047
1048 dp_get_lane_status_and_lane_adjust(
1049 link,
1050 lt_settings,
1051 dpcd_lane_status,
1052 &dpcd_lane_status_updated,
1053 dpcd_lane_adjust,
1054 DPRX);
1055
1056 if (dpcd_lane_status_updated.bits.
1057 POST_LT_ADJ_REQ_IN_PROGRESS == 0)
1058 return true1;
1059
1060 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
1061 return false0;
1062
1063 if (!dp_is_ch_eq_done(lane_count, dpcd_lane_status) ||
1064 !dp_is_symbol_locked(lane_count, dpcd_lane_status) ||
1065 !dp_is_interlane_aligned(dpcd_lane_status_updated))
1066 return false0;
1067
1068 for (lane = 0; lane < (uint32_t)(lane_count); lane++) {
1069
1070 if (lt_settings->
1071 dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET !=
1072 dpcd_lane_adjust[lane].bits.VOLTAGE_SWING_LANE ||
1073 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET !=
1074 dpcd_lane_adjust[lane].bits.PRE_EMPHASIS_LANE) {
1075
1076 req_drv_setting_changed = true1;
1077 break;
1078 }
1079 }
1080
1081 if (req_drv_setting_changed) {
1082 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1083 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1084
1085 dc_link_dp_set_drive_settings(link,
1086 link_res,
1087 lt_settings);
1088 break;
1089 }
1090
1091 drm_msleep(1)mdelay(1);
1092 }
1093
1094 if (!req_drv_setting_changed) {
1095 DC_LOG_WARNING("%s: Post Link Training Adjust Request Timed out\n",printk("\0014" "[" "drm" "] " "%s: Post Link Training Adjust Request Timed out\n"
, __func__)
1096 __func__)printk("\0014" "[" "drm" "] " "%s: Post Link Training Adjust Request Timed out\n"
, __func__)
;
1097
1098 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 1098); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
1099 return true1;
1100 }
1101 }
1102 DC_LOG_WARNING("%s: Post Link Training Adjust Request limit reached\n",printk("\0014" "[" "drm" "] " "%s: Post Link Training Adjust Request limit reached\n"
, __func__)
1103 __func__)printk("\0014" "[" "drm" "] " "%s: Post Link Training Adjust Request limit reached\n"
, __func__)
;
1104
1105 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 1105); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
1106 return true1;
1107
1108}
1109
1110/* Only used for channel equalization */
1111uint32_t dp_translate_training_aux_read_interval(uint32_t dpcd_aux_read_interval)
1112{
1113 unsigned int aux_rd_interval_us = 400;
1114
1115 switch (dpcd_aux_read_interval) {
1116 case 0x01:
1117 aux_rd_interval_us = 4000;
1118 break;
1119 case 0x02:
1120 aux_rd_interval_us = 8000;
1121 break;
1122 case 0x03:
1123 aux_rd_interval_us = 12000;
1124 break;
1125 case 0x04:
1126 aux_rd_interval_us = 16000;
1127 break;
1128 case 0x05:
1129 aux_rd_interval_us = 32000;
1130 break;
1131 case 0x06:
1132 aux_rd_interval_us = 64000;
1133 break;
1134 default:
1135 break;
1136 }
1137
1138 return aux_rd_interval_us;
1139}
1140
1141enum link_training_result dp_get_cr_failure(enum dc_lane_count ln_count,
1142 union lane_status *dpcd_lane_status)
1143{
1144 enum link_training_result result = LINK_TRAINING_SUCCESS;
1145
1146 if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
1147 result = LINK_TRAINING_CR_FAIL_LANE0;
1148 else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
1149 result = LINK_TRAINING_CR_FAIL_LANE1;
1150 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
1151 result = LINK_TRAINING_CR_FAIL_LANE23;
1152 else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
1153 result = LINK_TRAINING_CR_FAIL_LANE23;
1154 return result;
1155}
1156
1157static enum link_training_result perform_channel_equalization_sequence(
1158 struct dc_link *link,
1159 const struct link_resource *link_res,
1160 struct link_training_settings *lt_settings,
1161 uint32_t offset)
1162{
1163 enum dc_dp_training_pattern tr_pattern;
1164 uint32_t retries_ch_eq;
1165 uint32_t wait_time_microsec;
1166 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
1167 union lane_align_status_updated dpcd_lane_status_updated = {0};
1168 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1169 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1170
1171 /* Note: also check that TPS4 is a supported feature*/
1172 tr_pattern = lt_settings->pattern_for_eq;
1173
1174 if (is_repeater(lt_settings, offset) && dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING)
1175 tr_pattern = DP_TRAINING_PATTERN_SEQUENCE_4;
1176
1177 dp_set_hw_training_pattern(link, link_res, tr_pattern, offset);
1178
1179 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
1180 retries_ch_eq++) {
1181
1182 dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
1183
1184 /* 2. update DPCD*/
1185 if (!retries_ch_eq)
1186 /* EPR #361076 - write as a 5-byte burst,
1187 * but only for the 1-st iteration
1188 */
1189
1190 dpcd_set_lt_pattern_and_lane_settings(
1191 link,
1192 lt_settings,
1193 tr_pattern, offset);
1194 else
1195 dpcd_set_lane_settings(link, lt_settings, offset);
1196
1197 /* 3. wait for receiver to lock-on*/
1198 wait_time_microsec = lt_settings->eq_pattern_time;
1199
1200 if (is_repeater(lt_settings, offset))
1201 wait_time_microsec =
1202 dp_translate_training_aux_read_interval(
1203 link->dpcd_caps.lttpr_caps.aux_rd_interval[offset - 1]);
1204
1205 dp_wait_for_training_aux_rd_interval(
1206 link,
1207 wait_time_microsec);
1208
1209 /* 4. Read lane status and requested
1210 * drive settings as set by the sink*/
1211
1212 dp_get_lane_status_and_lane_adjust(
1213 link,
1214 lt_settings,
1215 dpcd_lane_status,
1216 &dpcd_lane_status_updated,
1217 dpcd_lane_adjust,
1218 offset);
1219
1220 /* 5. check CR done*/
1221 if (!dp_is_cr_done(lane_count, dpcd_lane_status))
1222 return dpcd_lane_status[0].bits.CR_DONE_0 ?
1223 LINK_TRAINING_EQ_FAIL_CR_PARTIAL :
1224 LINK_TRAINING_EQ_FAIL_CR;
1225
1226 /* 6. check CHEQ done*/
1227 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
1228 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
1229 dp_is_interlane_aligned(dpcd_lane_status_updated))
1230 return LINK_TRAINING_SUCCESS;
1231
1232 /* 7. update VS/PE/PC2 in lt_settings*/
1233 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1234 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1235 }
1236
1237 return LINK_TRAINING_EQ_FAIL_EQ;
1238
1239}
1240
1241static void start_clock_recovery_pattern_early(struct dc_link *link,
1242 const struct link_resource *link_res,
1243 struct link_training_settings *lt_settings,
1244 uint32_t offset)
1245{
1246 DC_LOG_HW_LINK_TRAINING("%s\n GPU sends TPS1. Wait 400us.\n",do { } while(0)
1247 __func__)do { } while(0);
1248 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
1249 dp_set_hw_lane_settings(link, link_res, lt_settings, offset);
1250 udelay(400);
1251}
1252
1253static enum link_training_result perform_clock_recovery_sequence(
1254 struct dc_link *link,
1255 const struct link_resource *link_res,
1256 struct link_training_settings *lt_settings,
1257 uint32_t offset)
1258{
1259 uint32_t retries_cr;
1260 uint32_t retry_count;
1261 uint32_t wait_time_microsec;
1262 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
1263 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
1264 union lane_align_status_updated dpcd_lane_status_updated;
1265 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1266
1267 retries_cr = 0;
1268 retry_count = 0;
1269
1270 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status))__builtin_memset((&dpcd_lane_status), ('\0'), (sizeof(dpcd_lane_status
)))
;
1271 memset(&dpcd_lane_status_updated, '\0',__builtin_memset((&dpcd_lane_status_updated), ('\0'), (sizeof
(dpcd_lane_status_updated)))
1272 sizeof(dpcd_lane_status_updated))__builtin_memset((&dpcd_lane_status_updated), ('\0'), (sizeof
(dpcd_lane_status_updated)))
;
1273
1274 if (!link->ctx->dc->work_arounds.lt_early_cr_pattern)
1275 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, offset);
1276
1277 /* najeeb - The synaptics MST hub can put the LT in
1278 * infinite loop by switching the VS
1279 */
1280 /* between level 0 and level 1 continuously, here
1281 * we try for CR lock for LinkTrainingMaxCRRetry count*/
1282 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
1283 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
1284
1285
1286 /* 1. call HWSS to set lane settings*/
1287 dp_set_hw_lane_settings(
1288 link,
1289 link_res,
1290 lt_settings,
1291 offset);
1292
1293 /* 2. update DPCD of the receiver*/
1294 if (!retry_count)
1295 /* EPR #361076 - write as a 5-byte burst,
1296 * but only for the 1-st iteration.*/
1297 dpcd_set_lt_pattern_and_lane_settings(
1298 link,
1299 lt_settings,
1300 lt_settings->pattern_for_cr,
1301 offset);
1302 else
1303 dpcd_set_lane_settings(
1304 link,
1305 lt_settings,
1306 offset);
1307
1308 /* 3. wait receiver to lock-on*/
1309 wait_time_microsec = lt_settings->cr_pattern_time;
1310
1311 dp_wait_for_training_aux_rd_interval(
1312 link,
1313 wait_time_microsec);
1314
1315 /* 4. Read lane status and requested drive
1316 * settings as set by the sink
1317 */
1318 dp_get_lane_status_and_lane_adjust(
1319 link,
1320 lt_settings,
1321 dpcd_lane_status,
1322 &dpcd_lane_status_updated,
1323 dpcd_lane_adjust,
1324 offset);
1325
1326 /* 5. check CR done*/
1327 if (dp_is_cr_done(lane_count, dpcd_lane_status))
1328 return LINK_TRAINING_SUCCESS;
1329
1330 /* 6. max VS reached*/
1331 if ((dp_get_link_encoding_format(&lt_settings->link_settings) ==
1332 DP_8b_10b_ENCODING) &&
1333 dp_is_max_vs_reached(lt_settings))
1334 break;
1335
1336 /* 7. same lane settings*/
1337 /* Note: settings are the same for all lanes,
1338 * so comparing first lane is sufficient*/
1339 if ((dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING) &&
1340 lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
1341 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
1342 retries_cr++;
1343 else if ((dp_get_link_encoding_format(&lt_settings->link_settings) == DP_128b_132b_ENCODING) &&
1344 lt_settings->dpcd_lane_settings[0].tx_ffe.PRESET_VALUE ==
1345 dpcd_lane_adjust[0].tx_ffe.PRESET_VALUE)
1346 retries_cr++;
1347 else
1348 retries_cr = 0;
1349
1350 /* 8. update VS/PE/PC2 in lt_settings*/
1351 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1352 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1353 retry_count++;
1354 }
1355
1356 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
1357 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 1357); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
1358 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",__drm_err("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue"
, __func__, LINK_TRAINING_MAX_CR_RETRY)
1359 __func__,__drm_err("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue"
, __func__, LINK_TRAINING_MAX_CR_RETRY)
1360 LINK_TRAINING_MAX_CR_RETRY)__drm_err("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue"
, __func__, LINK_TRAINING_MAX_CR_RETRY)
;
1361
1362 }
1363
1364 return dp_get_cr_failure(lane_count, dpcd_lane_status);
1365}
1366
1367static inline enum link_training_result dp_transition_to_video_idle(
1368 struct dc_link *link,
1369 const struct link_resource *link_res,
1370 struct link_training_settings *lt_settings,
1371 enum link_training_result status)
1372{
1373 union lane_count_set lane_count_set = {0};
1374
1375 /* 4. mainlink output idle pattern*/
1376 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL((void *)0), 0);
1377
1378 /*
1379 * 5. post training adjust if required
1380 * If the upstream DPTX and downstream DPRX both support TPS4,
1381 * TPS4 must be used instead of POST_LT_ADJ_REQ.
1382 */
1383 if (link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED != 1 ||
1384 lt_settings->pattern_for_eq >= DP_TRAINING_PATTERN_SEQUENCE_4) {
1385 /* delay 5ms after Main Link output idle pattern and then check
1386 * DPCD 0202h.
1387 */
1388 if (link->connector_signal != SIGNAL_TYPE_EDP && status == LINK_TRAINING_SUCCESS) {
1389 drm_msleep(5)mdelay(5);
1390 status = dp_check_link_loss_status(link, lt_settings);
1391 }
1392 return status;
1393 }
1394
1395 if (status == LINK_TRAINING_SUCCESS &&
1396 perform_post_lt_adj_req_sequence(link, link_res, lt_settings) == false0)
1397 status = LINK_TRAINING_LQA_FAIL;
1398
1399 lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
1400 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
1401 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
1402
1403 core_link_write_dpcd(
1404 link,
1405 DP_LANE_COUNT_SET0x101,
1406 &lane_count_set.raw,
1407 sizeof(lane_count_set));
1408
1409 return status;
1410}
1411
1412enum link_training_result dp_check_link_loss_status(
1413 struct dc_link *link,
1414 const struct link_training_settings *link_training_setting)
1415{
1416 enum link_training_result status = LINK_TRAINING_SUCCESS;
1417 union lane_status lane_status;
1418 uint8_t dpcd_buf[6] = {0};
1419 uint32_t lane;
1420
1421 core_link_read_dpcd(
1422 link,
1423 DP_SINK_COUNT0x200,
1424 (uint8_t *)(dpcd_buf),
1425 sizeof(dpcd_buf));
1426
1427 /*parse lane status*/
1428 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
1429 /*
1430 * check lanes status
1431 */
1432 lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane);
1433
1434 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
1435 !lane_status.bits.CR_DONE_0 ||
1436 !lane_status.bits.SYMBOL_LOCKED_0) {
1437 /* if one of the channel equalization, clock
1438 * recovery or symbol lock is dropped
1439 * consider it as (link has been
1440 * dropped) dp sink status has changed
1441 */
1442 status = LINK_TRAINING_LINK_LOSS;
1443 break;
1444 }
1445 }
1446
1447 return status;
1448}
1449
1450static inline void decide_8b_10b_training_settings(
1451 struct dc_link *link,
1452 const struct dc_link_settings *link_setting,
1453 struct link_training_settings *lt_settings)
1454{
1455 memset(lt_settings, '\0', sizeof(struct link_training_settings))__builtin_memset((lt_settings), ('\0'), (sizeof(struct link_training_settings
)))
;
1456
1457 /* Initialize link settings */
1458 lt_settings->link_settings.use_link_rate_set = link_setting->use_link_rate_set;
1459 lt_settings->link_settings.link_rate_set = link_setting->link_rate_set;
1460 lt_settings->link_settings.link_rate = link_setting->link_rate;
1461 lt_settings->link_settings.lane_count = link_setting->lane_count;
1462 /* TODO hard coded to SS for now
1463 * lt_settings.link_settings.link_spread =
1464 * dal_display_path_is_ss_supported(
1465 * path_mode->display_path) ?
1466 * LINK_SPREAD_05_DOWNSPREAD_30KHZ :
1467 * LINK_SPREAD_DISABLED;
1468 */
1469 lt_settings->link_settings.link_spread = link->dp_ss_off ?
1470 LINK_SPREAD_DISABLED : LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1471 lt_settings->cr_pattern_time = get_cr_training_aux_rd_interval(link, link_setting);
1472 lt_settings->eq_pattern_time = get_eq_training_aux_rd_interval(link, link_setting);
1473 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_setting);
1474 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_setting);
1475 lt_settings->enhanced_framing = 1;
1476 lt_settings->should_set_fec_ready = true1;
1477 lt_settings->disallow_per_lane_settings = true1;
1478 lt_settings->always_match_dpcd_with_hw_lane_settings = true1;
1479 lt_settings->lttpr_mode = dp_decide_8b_10b_lttpr_mode(link);
1480 dp_hw_to_dpcd_lane_settings(lt_settings, lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1481}
1482
1483static inline void decide_128b_132b_training_settings(struct dc_link *link,
1484 const struct dc_link_settings *link_settings,
1485 struct link_training_settings *lt_settings)
1486{
1487 memset(lt_settings, 0, sizeof(*lt_settings))__builtin_memset((lt_settings), (0), (sizeof(*lt_settings)));
1488
1489 lt_settings->link_settings = *link_settings;
1490 /* TODO: should decide link spread when populating link_settings */
1491 lt_settings->link_settings.link_spread = link->dp_ss_off ? LINK_SPREAD_DISABLED :
1492 LINK_SPREAD_05_DOWNSPREAD_30KHZ;
1493
1494 lt_settings->pattern_for_cr = decide_cr_training_pattern(link_settings);
1495 lt_settings->pattern_for_eq = decide_eq_training_pattern(link, link_settings);
1496 lt_settings->eq_pattern_time = 2500;
1497 lt_settings->eq_wait_time_limit = 400000;
1498 lt_settings->eq_loop_count_limit = 20;
1499 lt_settings->pattern_for_cds = DP_128b_132b_TPS2_CDS;
1500 lt_settings->cds_pattern_time = 2500;
1501 lt_settings->cds_wait_time_limit = (dp_convert_to_count(
1502 link->dpcd_caps.lttpr_caps.phy_repeater_cnt) + 1) * 20000;
1503 lt_settings->disallow_per_lane_settings = true1;
1504 lt_settings->lttpr_mode = dp_decide_128b_132b_lttpr_mode(link);
1505 dp_hw_to_dpcd_lane_settings(lt_settings,
1506 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1507}
1508
1509void dp_decide_training_settings(
1510 struct dc_link *link,
1511 const struct dc_link_settings *link_settings,
1512 struct link_training_settings *lt_settings)
1513{
1514 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
1515 decide_8b_10b_training_settings(link, link_settings, lt_settings);
1516 else if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING)
1517 decide_128b_132b_training_settings(link, link_settings, lt_settings);
1518}
1519
1520static void override_training_settings(
1521 struct dc_link *link,
1522 const struct dc_link_training_overrides *overrides,
1523 struct link_training_settings *lt_settings)
1524{
1525 uint32_t lane;
1526
1527 /* Override link spread */
1528 if (!link->dp_ss_off && overrides->downspread != NULL((void *)0))
1529 lt_settings->link_settings.link_spread = *overrides->downspread ?
1530 LINK_SPREAD_05_DOWNSPREAD_30KHZ
1531 : LINK_SPREAD_DISABLED;
1532
1533 /* Override lane settings */
1534 if (overrides->voltage_swing != NULL((void *)0))
1535 lt_settings->voltage_swing = overrides->voltage_swing;
1536 if (overrides->pre_emphasis != NULL((void *)0))
1537 lt_settings->pre_emphasis = overrides->pre_emphasis;
1538 if (overrides->post_cursor2 != NULL((void *)0))
1539 lt_settings->post_cursor2 = overrides->post_cursor2;
1540 if (overrides->ffe_preset != NULL((void *)0))
1541 lt_settings->ffe_preset = overrides->ffe_preset;
1542 /* Override HW lane settings with BIOS forced values if present */
1543 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
1544 lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
1545 lt_settings->voltage_swing = &link->bios_forced_drive_settings.VOLTAGE_SWING;
1546 lt_settings->pre_emphasis = &link->bios_forced_drive_settings.PRE_EMPHASIS;
1547 lt_settings->always_match_dpcd_with_hw_lane_settings = false0;
1548 }
1549 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
1550 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING =
1551 lt_settings->voltage_swing != NULL((void *)0) ?
1552 *lt_settings->voltage_swing :
1553 VOLTAGE_SWING_LEVEL0;
1554 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS =
1555 lt_settings->pre_emphasis != NULL((void *)0) ?
1556 *lt_settings->pre_emphasis
1557 : PRE_EMPHASIS_DISABLED;
1558 lt_settings->hw_lane_settings[lane].POST_CURSOR2 =
1559 lt_settings->post_cursor2 != NULL((void *)0) ?
1560 *lt_settings->post_cursor2
1561 : POST_CURSOR2_DISABLED;
1562 }
1563
1564 if (lt_settings->always_match_dpcd_with_hw_lane_settings)
1565 dp_hw_to_dpcd_lane_settings(lt_settings,
1566 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1567
1568 /* Initialize training timings */
1569 if (overrides->cr_pattern_time != NULL((void *)0))
1570 lt_settings->cr_pattern_time = *overrides->cr_pattern_time;
1571
1572 if (overrides->eq_pattern_time != NULL((void *)0))
1573 lt_settings->eq_pattern_time = *overrides->eq_pattern_time;
1574
1575 if (overrides->pattern_for_cr != NULL((void *)0))
1576 lt_settings->pattern_for_cr = *overrides->pattern_for_cr;
1577 if (overrides->pattern_for_eq != NULL((void *)0))
1578 lt_settings->pattern_for_eq = *overrides->pattern_for_eq;
1579
1580 if (overrides->enhanced_framing != NULL((void *)0))
1581 lt_settings->enhanced_framing = *overrides->enhanced_framing;
1582
1583 if (link->preferred_training_settings.fec_enable != NULL((void *)0))
1584 lt_settings->should_set_fec_ready = *link->preferred_training_settings.fec_enable;
1585
1586 #if defined(CONFIG_DRM_AMD_DC_DCN1)
1587 /* Check DP tunnel LTTPR mode debug option. */
1588 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && link->dc->debug.dpia_debug.bits.force_non_lttpr)
1589 lt_settings->lttpr_mode = LTTPR_MODE_NON_LTTPR;
1590
1591#endif
1592 dp_get_lttpr_mode_override(link, &lt_settings->lttpr_mode);
1593
1594}
1595
1596uint8_t dp_convert_to_count(uint8_t lttpr_repeater_count)
1597{
1598 switch (lttpr_repeater_count) {
1599 case 0x80: // 1 lttpr repeater
1600 return 1;
1601 case 0x40: // 2 lttpr repeaters
1602 return 2;
1603 case 0x20: // 3 lttpr repeaters
1604 return 3;
1605 case 0x10: // 4 lttpr repeaters
1606 return 4;
1607 case 0x08: // 5 lttpr repeaters
1608 return 5;
1609 case 0x04: // 6 lttpr repeaters
1610 return 6;
1611 case 0x02: // 7 lttpr repeaters
1612 return 7;
1613 case 0x01: // 8 lttpr repeaters
1614 return 8;
1615 default:
1616 break;
1617 }
1618 return 0; // invalid value
1619}
1620
1621static enum dc_status configure_lttpr_mode_transparent(struct dc_link *link)
1622{
1623 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT0x55;
1624
1625 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__)do { } while(0);
1626 return core_link_write_dpcd(link,
1627 DP_PHY_REPEATER_MODE0xf0003,
1628 (uint8_t *)&repeater_mode,
1629 sizeof(repeater_mode));
1630}
1631
1632static enum dc_status configure_lttpr_mode_non_transparent(
1633 struct dc_link *link,
1634 const struct link_training_settings *lt_settings)
1635{
1636 /* aux timeout is already set to extended */
1637 /* RESET/SET lttpr mode to enable non transparent mode */
1638 uint8_t repeater_cnt;
1639 uint32_t aux_interval_address;
1640 uint8_t repeater_id;
1641 enum dc_status result = DC_ERROR_UNEXPECTED;
1642 uint8_t repeater_mode = DP_PHY_REPEATER_MODE_TRANSPARENT0x55;
1643
1644 enum dp_link_encoding encoding = dp_get_link_encoding_format(&lt_settings->link_settings);
1645
1646 if (encoding == DP_8b_10b_ENCODING) {
1647 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Transparent Mode\n", __func__)do { } while(0);
1648 result = core_link_write_dpcd(link,
1649 DP_PHY_REPEATER_MODE0xf0003,
1650 (uint8_t *)&repeater_mode,
1651 sizeof(repeater_mode));
1652
1653 }
1654
1655 if (result == DC_OK) {
1656 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1657 }
1658
1659 if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
1660
1661 DC_LOG_HW_LINK_TRAINING("%s\n Set LTTPR to Non Transparent Mode\n", __func__)do { } while(0);
1662
1663 repeater_mode = DP_PHY_REPEATER_MODE_NON_TRANSPARENT0xaa;
1664 result = core_link_write_dpcd(link,
1665 DP_PHY_REPEATER_MODE0xf0003,
1666 (uint8_t *)&repeater_mode,
1667 sizeof(repeater_mode));
1668
1669 if (result == DC_OK) {
1670 link->dpcd_caps.lttpr_caps.mode = repeater_mode;
1671 }
1672
1673 if (encoding == DP_8b_10b_ENCODING) {
1674 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
1675
1676 /* Driver does not need to train the first hop. Skip DPCD read and clear
1677 * AUX_RD_INTERVAL for DPTX-to-DPIA hop.
1678 */
1679 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
1680 link->dpcd_caps.lttpr_caps.aux_rd_interval[--repeater_cnt] = 0;
1681
1682 for (repeater_id = repeater_cnt; repeater_id > 0; repeater_id--) {
1683 aux_interval_address = DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER10xf0020 +
1684 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (repeater_id - 1));
1685 core_link_read_dpcd(
1686 link,
1687 aux_interval_address,
1688 (uint8_t *)&link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1],
1689 sizeof(link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1]));
1690 link->dpcd_caps.lttpr_caps.aux_rd_interval[repeater_id - 1] &= 0x7F;
1691 }
1692 }
1693 }
1694
1695 return result;
1696}
1697
1698static void repeater_training_done(struct dc_link *link, uint32_t offset)
1699{
1700 union dpcd_training_pattern dpcd_pattern = {0};
1701
1702 const uint32_t dpcd_base_lt_offset =
1703 DP_TRAINING_PATTERN_SET_PHY_REPEATER10xf0010 +
1704 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
1705 /* Set training not in progress*/
1706 dpcd_pattern.v1_4.TRAINING_PATTERN_SET = DPCD_TRAINING_PATTERN_VIDEOIDLE;
1707
1708 core_link_write_dpcd(
1709 link,
1710 dpcd_base_lt_offset,
1711 &dpcd_pattern.raw,
1712 1);
1713
1714 DC_LOG_HW_LINK_TRAINING("%s\n LTTPR Id: %d 0x%X pattern = %x\n",do { } while(0)
1715 __func__,do { } while(0)
1716 offset,do { } while(0)
1717 dpcd_base_lt_offset,do { } while(0)
1718 dpcd_pattern.v1_4.TRAINING_PATTERN_SET)do { } while(0);
1719}
1720
1721static void print_status_message(
1722 struct dc_link *link,
1723 const struct link_training_settings *lt_settings,
1724 enum link_training_result status)
1725{
1726 char *link_rate = "Unknown";
1727 char *lt_result = "Unknown";
1728 char *lt_spread = "Disabled";
1729
1730 switch (lt_settings->link_settings.link_rate) {
1731 case LINK_RATE_LOW:
1732 link_rate = "RBR";
1733 break;
1734 case LINK_RATE_RATE_2:
1735 link_rate = "R2";
1736 break;
1737 case LINK_RATE_RATE_3:
1738 link_rate = "R3";
1739 break;
1740 case LINK_RATE_HIGH:
1741 link_rate = "HBR";
1742 break;
1743 case LINK_RATE_RBR2:
1744 link_rate = "RBR2";
1745 break;
1746 case LINK_RATE_RATE_6:
1747 link_rate = "R6";
1748 break;
1749 case LINK_RATE_HIGH2:
1750 link_rate = "HBR2";
1751 break;
1752 case LINK_RATE_HIGH3:
1753 link_rate = "HBR3";
1754 break;
1755 case LINK_RATE_UHBR10:
1756 link_rate = "UHBR10";
1757 break;
1758 case LINK_RATE_UHBR13_5:
1759 link_rate = "UHBR13.5";
1760 break;
1761 case LINK_RATE_UHBR20:
1762 link_rate = "UHBR20";
1763 break;
1764 default:
1765 break;
1766 }
1767
1768 switch (status) {
1769 case LINK_TRAINING_SUCCESS:
1770 lt_result = "pass";
1771 break;
1772 case LINK_TRAINING_CR_FAIL_LANE0:
1773 lt_result = "CR failed lane0";
1774 break;
1775 case LINK_TRAINING_CR_FAIL_LANE1:
1776 lt_result = "CR failed lane1";
1777 break;
1778 case LINK_TRAINING_CR_FAIL_LANE23:
1779 lt_result = "CR failed lane23";
1780 break;
1781 case LINK_TRAINING_EQ_FAIL_CR:
1782 lt_result = "CR failed in EQ";
1783 break;
1784 case LINK_TRAINING_EQ_FAIL_CR_PARTIAL:
1785 lt_result = "CR failed in EQ partially";
1786 break;
1787 case LINK_TRAINING_EQ_FAIL_EQ:
1788 lt_result = "EQ failed";
1789 break;
1790 case LINK_TRAINING_LQA_FAIL:
1791 lt_result = "LQA failed";
1792 break;
1793 case LINK_TRAINING_LINK_LOSS:
1794 lt_result = "Link loss";
1795 break;
1796 case DP_128b_132b_LT_FAILED:
1797 lt_result = "LT_FAILED received";
1798 break;
1799 case DP_128b_132b_MAX_LOOP_COUNT_REACHED:
1800 lt_result = "max loop count reached";
1801 break;
1802 case DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT:
1803 lt_result = "channel EQ timeout";
1804 break;
1805 case DP_128b_132b_CDS_DONE_TIMEOUT:
1806 lt_result = "CDS timeout";
1807 break;
1808 default:
1809 break;
1810 }
1811
1812 switch (lt_settings->link_settings.link_spread) {
1813 case LINK_SPREAD_DISABLED:
1814 lt_spread = "Disabled";
1815 break;
1816 case LINK_SPREAD_05_DOWNSPREAD_30KHZ:
1817 lt_spread = "0.5% 30KHz";
1818 break;
1819 case LINK_SPREAD_05_DOWNSPREAD_33KHZ:
1820 lt_spread = "0.5% 33KHz";
1821 break;
1822 default:
1823 break;
1824 }
1825
1826 /* Connectivity log: link training */
1827
1828 /* TODO - DP2.0 Log: add connectivity log for FFE PRESET */
1829
1830 CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d, DS=%s",do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%sx%d %s VS=%d, PE=%d, DS=%s"
, link_rate, lt_settings->link_settings.lane_count, lt_result
, lt_settings->hw_lane_settings[0].VOLTAGE_SWING, lt_settings
->hw_lane_settings[0].PRE_EMPHASIS, lt_spread); } while (0
)
1831 link_rate,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%sx%d %s VS=%d, PE=%d, DS=%s"
, link_rate, lt_settings->link_settings.lane_count, lt_result
, lt_settings->hw_lane_settings[0].VOLTAGE_SWING, lt_settings
->hw_lane_settings[0].PRE_EMPHASIS, lt_spread); } while (0
)
1832 lt_settings->link_settings.lane_count,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%sx%d %s VS=%d, PE=%d, DS=%s"
, link_rate, lt_settings->link_settings.lane_count, lt_result
, lt_settings->hw_lane_settings[0].VOLTAGE_SWING, lt_settings
->hw_lane_settings[0].PRE_EMPHASIS, lt_spread); } while (0
)
1833 lt_result,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%sx%d %s VS=%d, PE=%d, DS=%s"
, link_rate, lt_settings->link_settings.lane_count, lt_result
, lt_settings->hw_lane_settings[0].VOLTAGE_SWING, lt_settings
->hw_lane_settings[0].PRE_EMPHASIS, lt_spread); } while (0
)
1834 lt_settings->hw_lane_settings[0].VOLTAGE_SWING,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%sx%d %s VS=%d, PE=%d, DS=%s"
, link_rate, lt_settings->link_settings.lane_count, lt_result
, lt_settings->hw_lane_settings[0].VOLTAGE_SWING, lt_settings
->hw_lane_settings[0].PRE_EMPHASIS, lt_spread); } while (0
)
1835 lt_settings->hw_lane_settings[0].PRE_EMPHASIS,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%sx%d %s VS=%d, PE=%d, DS=%s"
, link_rate, lt_settings->link_settings.lane_count, lt_result
, lt_settings->hw_lane_settings[0].VOLTAGE_SWING, lt_settings
->hw_lane_settings[0].PRE_EMPHASIS, lt_spread); } while (0
)
1836 lt_spread)do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%sx%d %s VS=%d, PE=%d, DS=%s"
, link_rate, lt_settings->link_settings.lane_count, lt_result
, lt_settings->hw_lane_settings[0].VOLTAGE_SWING, lt_settings
->hw_lane_settings[0].PRE_EMPHASIS, lt_spread); } while (0
)
;
1837}
1838
1839void dc_link_dp_set_drive_settings(
1840 struct dc_link *link,
1841 const struct link_resource *link_res,
1842 struct link_training_settings *lt_settings)
1843{
1844 /* program ASIC PHY settings*/
1845 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
1846
1847 dp_hw_to_dpcd_lane_settings(lt_settings,
1848 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1849
1850 /* Notify DP sink the PHY settings from source */
1851 dpcd_set_lane_settings(link, lt_settings, DPRX);
1852}
1853
1854bool_Bool dc_link_dp_perform_link_training_skip_aux(
1855 struct dc_link *link,
1856 const struct link_resource *link_res,
1857 const struct dc_link_settings *link_setting)
1858{
1859 struct link_training_settings lt_settings = {0};
1860
1861 dp_decide_training_settings(
1862 link,
1863 link_setting,
1864 &lt_settings);
1865 override_training_settings(
1866 link,
1867 &link->preferred_training_settings,
1868 &lt_settings);
1869
1870 /* 1. Perform_clock_recovery_sequence. */
1871
1872 /* transmit training pattern for clock recovery */
1873 dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_cr, DPRX);
1874
1875 /* call HWSS to set lane settings*/
1876 dp_set_hw_lane_settings(link, link_res, &lt_settings, DPRX);
1877
1878 /* wait receiver to lock-on*/
1879 dp_wait_for_training_aux_rd_interval(link, lt_settings.cr_pattern_time);
1880
1881 /* 2. Perform_channel_equalization_sequence. */
1882
1883 /* transmit training pattern for channel equalization. */
1884 dp_set_hw_training_pattern(link, link_res, lt_settings.pattern_for_eq, DPRX);
1885
1886 /* call HWSS to set lane settings*/
1887 dp_set_hw_lane_settings(link, link_res, &lt_settings, DPRX);
1888
1889 /* wait receiver to lock-on. */
1890 dp_wait_for_training_aux_rd_interval(link, lt_settings.eq_pattern_time);
1891
1892 /* 3. Perform_link_training_int. */
1893
1894 /* Mainlink output idle pattern. */
1895 dp_set_hw_test_pattern(link, link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL((void *)0), 0);
1896
1897 print_status_message(link, &lt_settings, LINK_TRAINING_SUCCESS);
1898
1899 return true1;
1900}
1901
1902enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_training_settings *lt_settings)
1903{
1904 enum dc_status status = DC_OK;
1905
1906 if (lt_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT)
1907 status = configure_lttpr_mode_transparent(link);
1908
1909 else if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT)
1910 status = configure_lttpr_mode_non_transparent(link, lt_settings);
1911
1912 return status;
1913}
1914
1915static void dpcd_exit_training_mode(struct dc_link *link)
1916{
1917 uint8_t sink_status = 0;
1918 uint8_t i;
1919
1920 /* clear training pattern set */
1921 dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
1922
1923 /* poll for intra-hop disable */
1924 for (i = 0; i < 10; i++) {
1925 if ((core_link_read_dpcd(link, DP_SINK_STATUS0x205, &sink_status, 1) == DC_OK) &&
1926 (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION(1 << 3)) == 0)
1927 break;
1928 udelay(1000);
1929 }
1930}
1931
1932enum dc_status dpcd_configure_channel_coding(struct dc_link *link,
1933 struct link_training_settings *lt_settings)
1934{
1935 enum dp_link_encoding encoding =
1936 dp_get_link_encoding_format(
1937 &lt_settings->link_settings);
1938 enum dc_status status;
1939
1940 status = core_link_write_dpcd(
1941 link,
1942 DP_MAIN_LINK_CHANNEL_CODING_SET0x108,
1943 (uint8_t *) &encoding,
1944 1);
1945 DC_LOG_HW_LINK_TRAINING("%s:\n 0x%X MAIN_LINK_CHANNEL_CODING_SET = %x\n",do { } while(0)
1946 __func__,do { } while(0)
1947 DP_MAIN_LINK_CHANNEL_CODING_SET,do { } while(0)
1948 encoding)do { } while(0);
1949
1950 return status;
1951}
1952
1953static void dpcd_128b_132b_get_aux_rd_interval(struct dc_link *link,
1954 uint32_t *interval_in_us)
1955{
1956 union dp_128b_132b_training_aux_rd_interval dpcd_interval;
1957 uint32_t interval_unit = 0;
1958
1959 dpcd_interval.raw = 0;
1960 core_link_read_dpcd(link, DP_128b_132b_TRAINING_AUX_RD_INTERVAL0x2216,
1961 &dpcd_interval.raw, sizeof(dpcd_interval.raw));
1962 interval_unit = dpcd_interval.bits.UNIT ? 1 : 2; /* 0b = 2 ms, 1b = 1 ms */
1963 /* (128b/132b_TRAINING_AUX_RD_INTERVAL value + 1) *
1964 * INTERVAL_UNIT. The maximum is 256 ms
1965 */
1966 *interval_in_us = (dpcd_interval.bits.VALUE + 1) * interval_unit * 1000;
1967}
1968
1969static enum link_training_result dp_perform_128b_132b_channel_eq_done_sequence(
1970 struct dc_link *link,
1971 const struct link_resource *link_res,
1972 struct link_training_settings *lt_settings)
1973{
1974 uint8_t loop_count;
1975 uint32_t aux_rd_interval = 0;
1976 uint32_t wait_time = 0;
1977 union lane_align_status_updated dpcd_lane_status_updated = {0};
1978 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
1979 enum dc_status status = DC_OK;
1980 enum link_training_result result = LINK_TRAINING_SUCCESS;
1981 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
1982
1983 /* Transmit 128b/132b_TPS1 over Main-Link */
1984 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_cr, DPRX);
1985 /* Set TRAINING_PATTERN_SET to 01h */
1986 dpcd_set_training_pattern(link, lt_settings->pattern_for_cr);
1987
1988 /* Adjust TX_FFE_PRESET_VALUE and Transmit 128b/132b_TPS2 over Main-Link */
1989 dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
1990 dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
1991 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
1992 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
1993 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
1994 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
1995 dp_set_hw_training_pattern(link, link_res, lt_settings->pattern_for_eq, DPRX);
1996
1997 /* Set loop counter to start from 1 */
1998 loop_count = 1;
1999
2000 /* Set TRAINING_PATTERN_SET to 02h and TX_FFE_PRESET_VALUE in one AUX transaction */
2001 dpcd_set_lt_pattern_and_lane_settings(link, lt_settings,
2002 lt_settings->pattern_for_eq, DPRX);
2003
2004 /* poll for channel EQ done */
2005 while (result == LINK_TRAINING_SUCCESS) {
2006 dp_wait_for_training_aux_rd_interval(link, aux_rd_interval);
2007 wait_time += aux_rd_interval;
2008 status = dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2009 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2010 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2011 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2012 dpcd_128b_132b_get_aux_rd_interval(link, &aux_rd_interval);
2013 if (status != DC_OK) {
2014 result = LINK_TRAINING_ABORT;
2015 } else if (dp_is_ch_eq_done(lt_settings->link_settings.lane_count,
2016 dpcd_lane_status)) {
2017 /* pass */
2018 break;
2019 } else if (loop_count >= lt_settings->eq_loop_count_limit) {
2020 result = DP_128b_132b_MAX_LOOP_COUNT_REACHED;
2021 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2022 result = DP_128b_132b_LT_FAILED;
2023 } else {
2024 dp_set_hw_lane_settings(link, link_res, lt_settings, DPRX);
2025 dpcd_128b_132b_set_lane_settings(link, lt_settings);
2026 }
2027 loop_count++;
2028 }
2029
2030 /* poll for EQ interlane align done */
2031 while (result == LINK_TRAINING_SUCCESS) {
2032 if (status != DC_OK) {
2033 result = LINK_TRAINING_ABORT;
2034 } else if (dpcd_lane_status_updated.bits.EQ_INTERLANE_ALIGN_DONE_128b_132b) {
2035 /* pass */
2036 break;
2037 } else if (wait_time >= lt_settings->eq_wait_time_limit) {
2038 result = DP_128b_132b_CHANNEL_EQ_DONE_TIMEOUT;
2039 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2040 result = DP_128b_132b_LT_FAILED;
2041 } else {
2042 dp_wait_for_training_aux_rd_interval(link,
2043 lt_settings->eq_pattern_time);
2044 wait_time += lt_settings->eq_pattern_time;
2045 status = dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2046 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2047 }
2048 }
2049
2050 return result;
2051}
2052
2053static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
2054 struct dc_link *link,
2055 const struct link_resource *link_res,
2056 struct link_training_settings *lt_settings)
2057{
2058 /* Assumption: assume hardware has transmitted eq pattern */
2059 enum dc_status status = DC_OK;
2060 enum link_training_result result = LINK_TRAINING_SUCCESS;
2061 union lane_align_status_updated dpcd_lane_status_updated = {0};
2062 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
2063 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2064 uint32_t wait_time = 0;
2065
2066 /* initiate CDS done sequence */
2067 dpcd_set_training_pattern(link, lt_settings->pattern_for_cds);
2068
2069 /* poll for CDS interlane align done and symbol lock */
2070 while (result == LINK_TRAINING_SUCCESS) {
2071 dp_wait_for_training_aux_rd_interval(link,
2072 lt_settings->cds_pattern_time);
2073 wait_time += lt_settings->cds_pattern_time;
2074 status = dp_get_lane_status_and_lane_adjust(link, lt_settings, dpcd_lane_status,
2075 &dpcd_lane_status_updated, dpcd_lane_adjust, DPRX);
2076 if (status != DC_OK) {
2077 result = LINK_TRAINING_ABORT;
2078 } else if (dp_is_symbol_locked(lt_settings->link_settings.lane_count, dpcd_lane_status) &&
2079 dpcd_lane_status_updated.bits.CDS_INTERLANE_ALIGN_DONE_128b_132b) {
2080 /* pass */
2081 break;
2082 } else if (dpcd_lane_status_updated.bits.LT_FAILED_128b_132b) {
2083 result = DP_128b_132b_LT_FAILED;
2084 } else if (wait_time >= lt_settings->cds_wait_time_limit) {
2085 result = DP_128b_132b_CDS_DONE_TIMEOUT;
2086 }
2087 }
2088
2089 return result;
2090}
2091
2092static enum link_training_result dp_perform_8b_10b_link_training(
2093 struct dc_link *link,
2094 const struct link_resource *link_res,
2095 struct link_training_settings *lt_settings)
2096{
2097 enum link_training_result status = LINK_TRAINING_SUCCESS;
2098
2099 uint8_t repeater_cnt;
2100 uint8_t repeater_id;
2101 uint8_t lane = 0;
2102
2103 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
2104 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
2105
2106 /* 1. set link rate, lane count and spread. */
2107 dpcd_set_link_settings(link, lt_settings);
2108
2109 if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2110
2111 /* 2. perform link training (set link training done
2112 * to false is done as well)
2113 */
2114 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2115
2116 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
2117 repeater_id--) {
2118 status = perform_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
2119
2120 if (status != LINK_TRAINING_SUCCESS) {
2121 repeater_training_done(link, repeater_id);
2122 break;
2123 }
2124
2125 status = perform_channel_equalization_sequence(link,
2126 link_res,
2127 lt_settings,
2128 repeater_id);
2129
2130 repeater_training_done(link, repeater_id);
2131
2132 if (status != LINK_TRAINING_SUCCESS)
2133 break;
2134
2135 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
2136 lt_settings->dpcd_lane_settings[lane].raw = 0;
2137 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
2138 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
2139 }
2140 }
2141 }
2142
2143 if (status == LINK_TRAINING_SUCCESS) {
2144 status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
2145 if (status == LINK_TRAINING_SUCCESS) {
2146 status = perform_channel_equalization_sequence(link,
2147 link_res,
2148 lt_settings,
2149 DPRX);
2150 }
2151 }
2152
2153 return status;
2154}
2155
2156static enum link_training_result dp_perform_128b_132b_link_training(
2157 struct dc_link *link,
2158 const struct link_resource *link_res,
2159 struct link_training_settings *lt_settings)
2160{
2161 enum link_training_result result = LINK_TRAINING_SUCCESS;
2162
2163 /* TODO - DP2.0 Link: remove legacy_dp2_lt logic */
2164 if (link->dc->debug.legacy_dp2_lt) {
2165 struct link_training_settings legacy_settings;
2166
2167 decide_8b_10b_training_settings(link,
2168 &lt_settings->link_settings,
2169 &legacy_settings);
2170 return dp_perform_8b_10b_link_training(link, link_res, &legacy_settings);
2171 }
2172
2173 dpcd_set_link_settings(link, lt_settings);
2174
2175 if (result == LINK_TRAINING_SUCCESS)
2176 result = dp_perform_128b_132b_channel_eq_done_sequence(link, link_res, lt_settings);
2177
2178 if (result == LINK_TRAINING_SUCCESS)
2179 result = dp_perform_128b_132b_cds_done_sequence(link, link_res, lt_settings);
2180
2181 return result;
2182}
2183
2184static enum link_training_result perform_fixed_vs_pe_nontransparent_training_sequence(
2185 struct dc_link *link,
2186 const struct link_resource *link_res,
2187 struct link_training_settings *lt_settings)
2188{
2189 enum link_training_result status = LINK_TRAINING_SUCCESS;
2190 uint8_t lane = 0;
2191 uint8_t toggle_rate = 0x6;
2192 uint8_t target_rate = 0x6;
2193 bool_Bool apply_toggle_rate_wa = false0;
2194 uint8_t repeater_cnt;
2195 uint8_t repeater_id;
2196
2197 /* Fixed VS/PE specific: Force CR AUX RD Interval to at least 16ms */
2198 if (lt_settings->cr_pattern_time < 16000)
2199 lt_settings->cr_pattern_time = 16000;
2200
2201 /* Fixed VS/PE specific: Toggle link rate */
2202 apply_toggle_rate_wa = (link->vendor_specific_lttpr_link_rate_wa == target_rate);
2203 target_rate = get_dpcd_link_rate(&lt_settings->link_settings);
2204 toggle_rate = (target_rate == 0x6) ? 0xA : 0x6;
2205
2206 if (apply_toggle_rate_wa)
2207 lt_settings->link_settings.link_rate = toggle_rate;
2208
2209 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
2210 start_clock_recovery_pattern_early(link, link_res, lt_settings, DPRX);
2211
2212 /* 1. set link rate, lane count and spread. */
2213 dpcd_set_link_settings(link, lt_settings);
2214
2215 /* Fixed VS/PE specific: Toggle link rate back*/
2216 if (apply_toggle_rate_wa) {
2217 core_link_write_dpcd(
2218 link,
2219 DP_LINK_BW_SET0x100,
2220 &target_rate,
2221 1);
2222 }
2223
2224 link->vendor_specific_lttpr_link_rate_wa = target_rate;
2225
2226 if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2227
2228 /* 2. perform link training (set link training done
2229 * to false is done as well)
2230 */
2231 repeater_cnt = dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2232
2233 for (repeater_id = repeater_cnt; (repeater_id > 0 && status == LINK_TRAINING_SUCCESS);
2234 repeater_id--) {
2235 status = perform_clock_recovery_sequence(link, link_res, lt_settings, repeater_id);
2236
2237 if (status != LINK_TRAINING_SUCCESS) {
2238 repeater_training_done(link, repeater_id);
2239 break;
2240 }
2241
2242 status = perform_channel_equalization_sequence(link,
2243 link_res,
2244 lt_settings,
2245 repeater_id);
2246
2247 repeater_training_done(link, repeater_id);
2248
2249 if (status != LINK_TRAINING_SUCCESS)
2250 break;
2251
2252 for (lane = 0; lane < LANE_COUNT_DP_MAX; lane++) {
2253 lt_settings->dpcd_lane_settings[lane].raw = 0;
2254 lt_settings->hw_lane_settings[lane].VOLTAGE_SWING = 0;
2255 lt_settings->hw_lane_settings[lane].PRE_EMPHASIS = 0;
2256 }
2257 }
2258 }
2259
2260 if (status == LINK_TRAINING_SUCCESS) {
2261 status = perform_clock_recovery_sequence(link, link_res, lt_settings, DPRX);
2262 if (status == LINK_TRAINING_SUCCESS) {
2263 status = perform_channel_equalization_sequence(link,
2264 link_res,
2265 lt_settings,
2266 DPRX);
2267 }
2268 }
2269
2270 return status;
2271}
2272
2273static enum link_training_result dp_perform_fixed_vs_pe_training_sequence(
2274 struct dc_link *link,
2275 const struct link_resource *link_res,
2276 struct link_training_settings *lt_settings)
2277{
2278 const uint8_t vendor_lttpr_write_data_reset[4] = {0x1, 0x50, 0x63, 0xFF};
2279 const uint8_t offset = dp_convert_to_count(
2280 link->dpcd_caps.lttpr_caps.phy_repeater_cnt);
2281 const uint8_t vendor_lttpr_write_data_intercept_en[4] = {0x1, 0x55, 0x63, 0x0};
2282 const uint8_t vendor_lttpr_write_data_intercept_dis[4] = {0x1, 0x55, 0x63, 0x68};
2283 uint32_t pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa;
2284 uint8_t vendor_lttpr_write_data_vs[4] = {0x1, 0x51, 0x63, 0x0};
2285 uint8_t vendor_lttpr_write_data_pe[4] = {0x1, 0x52, 0x63, 0x0};
2286 uint32_t vendor_lttpr_write_address = 0xF004F;
2287 enum link_training_result status = LINK_TRAINING_SUCCESS;
2288 uint8_t lane = 0;
2289 union down_spread_ctrl downspread = {0};
2290 union lane_count_set lane_count_set = {0};
2291 uint8_t toggle_rate;
2292 uint8_t rate;
2293
2294 /* Only 8b/10b is supported */
2295 ASSERT(dp_get_link_encoding_format(&lt_settings->link_settings) ==do { if (({ static int __warned; int __ret = !!(!(dp_get_link_encoding_format
(&lt_settings->link_settings) == DP_8b_10b_ENCODING));
if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 2296); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
2296 DP_8b_10b_ENCODING)do { if (({ static int __warned; int __ret = !!(!(dp_get_link_encoding_format
(&lt_settings->link_settings) == DP_8b_10b_ENCODING));
if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(dp_get_link_encoding_format(&lt_settings->link_settings) == DP_8b_10b_ENCODING)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 2296); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
2297
2298 if (lt_settings->lttpr_mode == LTTPR_MODE_NON_TRANSPARENT) {
2299 status = perform_fixed_vs_pe_nontransparent_training_sequence(link, link_res, lt_settings);
2300 return status;
2301 }
2302
2303 if (offset != 0xFF) {
2304 vendor_lttpr_write_address +=
2305 ((DP_REPEATER_CONFIGURATION_AND_STATUS_SIZE0x50) * (offset - 1));
2306
2307 /* Certain display and cable configuration require extra delay */
2308 if (offset > 2)
2309 pre_disable_intercept_delay_ms = link->dc->debug.fixed_vs_aux_delay_config_wa * 2;
2310 }
2311
2312 /* Vendor specific: Reset lane settings */
2313 core_link_write_dpcd(
2314 link,
2315 vendor_lttpr_write_address,
2316 &vendor_lttpr_write_data_reset[0],
2317 sizeof(vendor_lttpr_write_data_reset));
2318 core_link_write_dpcd(
2319 link,
2320 vendor_lttpr_write_address,
2321 &vendor_lttpr_write_data_vs[0],
2322 sizeof(vendor_lttpr_write_data_vs));
2323 core_link_write_dpcd(
2324 link,
2325 vendor_lttpr_write_address,
2326 &vendor_lttpr_write_data_pe[0],
2327 sizeof(vendor_lttpr_write_data_pe));
2328
2329 /* Vendor specific: Enable intercept */
2330 core_link_write_dpcd(
2331 link,
2332 vendor_lttpr_write_address,
2333 &vendor_lttpr_write_data_intercept_en[0],
2334 sizeof(vendor_lttpr_write_data_intercept_en));
2335
2336 /* 1. set link rate, lane count and spread. */
2337
2338 downspread.raw = (uint8_t)(lt_settings->link_settings.link_spread);
2339
2340 lane_count_set.bits.LANE_COUNT_SET =
2341 lt_settings->link_settings.lane_count;
2342
2343 lane_count_set.bits.ENHANCED_FRAMING = lt_settings->enhanced_framing;
2344 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED = 0;
2345
2346
2347 if (lt_settings->pattern_for_eq < DP_TRAINING_PATTERN_SEQUENCE_4) {
2348 lane_count_set.bits.POST_LT_ADJ_REQ_GRANTED =
2349 link->dpcd_caps.max_ln_count.bits.POST_LT_ADJ_REQ_SUPPORTED;
2350 }
2351
2352 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL0x107,
2353 &downspread.raw, sizeof(downspread));
2354
2355 core_link_write_dpcd(link, DP_LANE_COUNT_SET0x101,
2356 &lane_count_set.raw, 1);
2357
2358 rate = get_dpcd_link_rate(&lt_settings->link_settings);
2359
2360 /* Vendor specific: Toggle link rate */
2361 toggle_rate = (rate == 0x6) ? 0xA : 0x6;
2362
2363 if (link->vendor_specific_lttpr_link_rate_wa == rate) {
2364 core_link_write_dpcd(
2365 link,
2366 DP_LINK_BW_SET0x100,
2367 &toggle_rate,
2368 1);
2369 }
2370
2371 link->vendor_specific_lttpr_link_rate_wa = rate;
2372
2373 core_link_write_dpcd(link, DP_LINK_BW_SET0x100, &rate, 1);
2374
2375 DC_LOG_HW_LINK_TRAINING("%s\n %x rate = %x\n %x lane = %x framing = %x\n %x spread = %x\n",do { } while(0)
2376 __func__,do { } while(0)
2377 DP_LINK_BW_SET,do { } while(0)
2378 lt_settings->link_settings.link_rate,do { } while(0)
2379 DP_LANE_COUNT_SET,do { } while(0)
2380 lt_settings->link_settings.lane_count,do { } while(0)
2381 lt_settings->enhanced_framing,do { } while(0)
2382 DP_DOWNSPREAD_CTRL,do { } while(0)
2383 lt_settings->link_settings.link_spread)do { } while(0);
2384
2385 /* 2. Perform link training */
2386
2387 /* Perform Clock Recovery Sequence */
2388 if (status == LINK_TRAINING_SUCCESS) {
2389 const uint8_t max_vendor_dpcd_retries = 10;
2390 uint32_t retries_cr;
2391 uint32_t retry_count;
2392 uint32_t wait_time_microsec;
2393 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
2394 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX];
2395 union lane_align_status_updated dpcd_lane_status_updated;
2396 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2397 enum dc_status dpcd_status = DC_OK;
2398 uint8_t i = 0;
2399
2400 retries_cr = 0;
2401 retry_count = 0;
2402
2403 memset(&dpcd_lane_status, '\0', sizeof(dpcd_lane_status))__builtin_memset((&dpcd_lane_status), ('\0'), (sizeof(dpcd_lane_status
)))
;
2404 memset(&dpcd_lane_status_updated, '\0',__builtin_memset((&dpcd_lane_status_updated), ('\0'), (sizeof
(dpcd_lane_status_updated)))
2405 sizeof(dpcd_lane_status_updated))__builtin_memset((&dpcd_lane_status_updated), ('\0'), (sizeof
(dpcd_lane_status_updated)))
;
2406
2407 while ((retries_cr < LINK_TRAINING_MAX_RETRY_COUNT) &&
2408 (retry_count < LINK_TRAINING_MAX_CR_RETRY)) {
2409
2410
2411 /* 1. call HWSS to set lane settings */
2412 dp_set_hw_lane_settings(
2413 link,
2414 link_res,
2415 lt_settings,
2416 0);
2417
2418 /* 2. update DPCD of the receiver */
2419 if (!retry_count) {
2420 /* EPR #361076 - write as a 5-byte burst,
2421 * but only for the 1-st iteration.
2422 */
2423 dpcd_set_lt_pattern_and_lane_settings(
2424 link,
2425 lt_settings,
2426 lt_settings->pattern_for_cr,
2427 0);
2428 /* Vendor specific: Disable intercept */
2429 for (i = 0; i < max_vendor_dpcd_retries; i++) {
2430 drm_msleep(pre_disable_intercept_delay_ms)mdelay(pre_disable_intercept_delay_ms);
2431 dpcd_status = core_link_write_dpcd(
2432 link,
2433 vendor_lttpr_write_address,
2434 &vendor_lttpr_write_data_intercept_dis[0],
2435 sizeof(vendor_lttpr_write_data_intercept_dis));
2436
2437 if (dpcd_status == DC_OK)
2438 break;
2439
2440 core_link_write_dpcd(
2441 link,
2442 vendor_lttpr_write_address,
2443 &vendor_lttpr_write_data_intercept_en[0],
2444 sizeof(vendor_lttpr_write_data_intercept_en));
2445 }
2446 } else {
2447 vendor_lttpr_write_data_vs[3] = 0;
2448 vendor_lttpr_write_data_pe[3] = 0;
2449
2450 for (lane = 0; lane < lane_count; lane++) {
2451 vendor_lttpr_write_data_vs[3] |=
2452 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
2453 vendor_lttpr_write_data_pe[3] |=
2454 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
2455 }
2456
2457 /* Vendor specific: Update VS and PE to DPRX requested value */
2458 core_link_write_dpcd(
2459 link,
2460 vendor_lttpr_write_address,
2461 &vendor_lttpr_write_data_vs[0],
2462 sizeof(vendor_lttpr_write_data_vs));
2463 core_link_write_dpcd(
2464 link,
2465 vendor_lttpr_write_address,
2466 &vendor_lttpr_write_data_pe[0],
2467 sizeof(vendor_lttpr_write_data_pe));
2468
2469 dpcd_set_lane_settings(
2470 link,
2471 lt_settings,
2472 0);
2473 }
2474
2475 /* 3. wait receiver to lock-on*/
2476 wait_time_microsec = lt_settings->cr_pattern_time;
2477
2478 dp_wait_for_training_aux_rd_interval(
2479 link,
2480 wait_time_microsec);
2481
2482 /* 4. Read lane status and requested drive
2483 * settings as set by the sink
2484 */
2485 dp_get_lane_status_and_lane_adjust(
2486 link,
2487 lt_settings,
2488 dpcd_lane_status,
2489 &dpcd_lane_status_updated,
2490 dpcd_lane_adjust,
2491 0);
2492
2493 /* 5. check CR done*/
2494 if (dp_is_cr_done(lane_count, dpcd_lane_status)) {
2495 status = LINK_TRAINING_SUCCESS;
Value stored to 'status' is never read
2496 break;
2497 }
2498
2499 /* 6. max VS reached*/
2500 if (dp_is_max_vs_reached(lt_settings))
2501 break;
2502
2503 /* 7. same lane settings */
2504 /* Note: settings are the same for all lanes,
2505 * so comparing first lane is sufficient
2506 */
2507 if (lt_settings->dpcd_lane_settings[0].bits.VOLTAGE_SWING_SET ==
2508 dpcd_lane_adjust[0].bits.VOLTAGE_SWING_LANE)
2509 retries_cr++;
2510 else
2511 retries_cr = 0;
2512
2513 /* 8. update VS/PE/PC2 in lt_settings*/
2514 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2515 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2516 retry_count++;
2517 }
2518
2519 if (retry_count >= LINK_TRAINING_MAX_CR_RETRY) {
2520 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 2520); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
2521 DC_LOG_ERROR("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue",__drm_err("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue"
, __func__, LINK_TRAINING_MAX_CR_RETRY)
2522 __func__,__drm_err("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue"
, __func__, LINK_TRAINING_MAX_CR_RETRY)
2523 LINK_TRAINING_MAX_CR_RETRY)__drm_err("%s: Link Training Error, could not get CR after %d tries. Possibly voltage swing issue"
, __func__, LINK_TRAINING_MAX_CR_RETRY)
;
2524
2525 }
2526
2527 status = dp_get_cr_failure(lane_count, dpcd_lane_status);
2528 }
2529
2530 /* Perform Channel EQ Sequence */
2531 if (status == LINK_TRAINING_SUCCESS) {
2532 enum dc_dp_training_pattern tr_pattern;
2533 uint32_t retries_ch_eq;
2534 uint32_t wait_time_microsec;
2535 enum dc_lane_count lane_count = lt_settings->link_settings.lane_count;
2536 union lane_align_status_updated dpcd_lane_status_updated = {0};
2537 union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {0};
2538 union lane_adjust dpcd_lane_adjust[LANE_COUNT_DP_MAX] = {0};
2539
2540 /* Note: also check that TPS4 is a supported feature*/
2541 tr_pattern = lt_settings->pattern_for_eq;
2542
2543 dp_set_hw_training_pattern(link, link_res, tr_pattern, 0);
2544
2545 status = LINK_TRAINING_EQ_FAIL_EQ;
2546
2547 for (retries_ch_eq = 0; retries_ch_eq <= LINK_TRAINING_MAX_RETRY_COUNT;
2548 retries_ch_eq++) {
2549
2550 dp_set_hw_lane_settings(link, link_res, lt_settings, 0);
2551
2552 vendor_lttpr_write_data_vs[3] = 0;
2553 vendor_lttpr_write_data_pe[3] = 0;
2554
2555 for (lane = 0; lane < lane_count; lane++) {
2556 vendor_lttpr_write_data_vs[3] |=
2557 lt_settings->dpcd_lane_settings[lane].bits.VOLTAGE_SWING_SET << (2 * lane);
2558 vendor_lttpr_write_data_pe[3] |=
2559 lt_settings->dpcd_lane_settings[lane].bits.PRE_EMPHASIS_SET << (2 * lane);
2560 }
2561
2562 /* Vendor specific: Update VS and PE to DPRX requested value */
2563 core_link_write_dpcd(
2564 link,
2565 vendor_lttpr_write_address,
2566 &vendor_lttpr_write_data_vs[0],
2567 sizeof(vendor_lttpr_write_data_vs));
2568 core_link_write_dpcd(
2569 link,
2570 vendor_lttpr_write_address,
2571 &vendor_lttpr_write_data_pe[0],
2572 sizeof(vendor_lttpr_write_data_pe));
2573
2574 /* 2. update DPCD*/
2575 if (!retries_ch_eq)
2576 /* EPR #361076 - write as a 5-byte burst,
2577 * but only for the 1-st iteration
2578 */
2579
2580 dpcd_set_lt_pattern_and_lane_settings(
2581 link,
2582 lt_settings,
2583 tr_pattern, 0);
2584 else
2585 dpcd_set_lane_settings(link, lt_settings, 0);
2586
2587 /* 3. wait for receiver to lock-on*/
2588 wait_time_microsec = lt_settings->eq_pattern_time;
2589
2590 dp_wait_for_training_aux_rd_interval(
2591 link,
2592 wait_time_microsec);
2593
2594 /* 4. Read lane status and requested
2595 * drive settings as set by the sink
2596 */
2597 dp_get_lane_status_and_lane_adjust(
2598 link,
2599 lt_settings,
2600 dpcd_lane_status,
2601 &dpcd_lane_status_updated,
2602 dpcd_lane_adjust,
2603 0);
2604
2605 /* 5. check CR done*/
2606 if (!dp_is_cr_done(lane_count, dpcd_lane_status)) {
2607 status = LINK_TRAINING_EQ_FAIL_CR;
2608 break;
2609 }
2610
2611 /* 6. check CHEQ done*/
2612 if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
2613 dp_is_symbol_locked(lane_count, dpcd_lane_status) &&
2614 dp_is_interlane_aligned(dpcd_lane_status_updated)) {
2615 status = LINK_TRAINING_SUCCESS;
2616 break;
2617 }
2618
2619 /* 7. update VS/PE/PC2 in lt_settings*/
2620 dp_decide_lane_settings(lt_settings, dpcd_lane_adjust,
2621 lt_settings->hw_lane_settings, lt_settings->dpcd_lane_settings);
2622 }
2623 }
2624
2625 return status;
2626}
2627
2628
2629enum link_training_result dc_link_dp_perform_link_training(
2630 struct dc_link *link,
2631 const struct link_resource *link_res,
2632 const struct dc_link_settings *link_settings,
2633 bool_Bool skip_video_pattern)
2634{
2635 enum link_training_result status = LINK_TRAINING_SUCCESS;
2636 struct link_training_settings lt_settings = {0};
2637 enum dp_link_encoding encoding =
2638 dp_get_link_encoding_format(link_settings);
2639
2640 /* decide training settings */
2641 dp_decide_training_settings(
2642 link,
2643 link_settings,
2644 &lt_settings);
2645
2646 override_training_settings(
2647 link,
2648 &link->preferred_training_settings,
2649 &lt_settings);
2650
2651 /* reset previous training states */
2652 dpcd_exit_training_mode(link);
2653
2654 /* configure link prior to entering training mode */
2655 dpcd_configure_lttpr_mode(link, &lt_settings);
2656 dp_set_fec_ready(link, link_res, lt_settings.should_set_fec_ready);
2657 dpcd_configure_channel_coding(link, &lt_settings);
2658
2659 /* enter training mode:
2660 * Per DP specs starting from here, DPTX device shall not issue
2661 * Non-LT AUX transactions inside training mode.
2662 */
2663 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN && encoding == DP_8b_10b_ENCODING)
2664 status = dp_perform_fixed_vs_pe_training_sequence(link, link_res, &lt_settings);
2665 else if (encoding == DP_8b_10b_ENCODING)
2666 status = dp_perform_8b_10b_link_training(link, link_res, &lt_settings);
2667 else if (encoding == DP_128b_132b_ENCODING)
2668 status = dp_perform_128b_132b_link_training(link, link_res, &lt_settings);
2669 else
2670 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 2670); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
2671
2672 /* exit training mode */
2673 dpcd_exit_training_mode(link);
2674
2675 /* switch to video idle */
2676 if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
2677 status = dp_transition_to_video_idle(link,
2678 link_res,
2679 &lt_settings,
2680 status);
2681
2682 /* dump debug data */
2683 print_status_message(link, &lt_settings, status);
2684 if (status != LINK_TRAINING_SUCCESS)
2685 link->ctx->dc->debug_data.ltFailCount++;
2686 return status;
2687}
2688
2689bool_Bool perform_link_training_with_retries(
2690 const struct dc_link_settings *link_setting,
2691 bool_Bool skip_video_pattern,
2692 int attempts,
2693 struct pipe_ctx *pipe_ctx,
2694 enum amd_signal_type signal,
2695 bool_Bool do_fallback)
2696{
2697 int j;
2698 uint8_t delay_between_attempts = LINK_TRAINING_RETRY_DELAY50;
2699 struct dc_stream_state *stream = pipe_ctx->stream;
2700 struct dc_link *link = stream->link;
2701 enum dp_panel_mode panel_mode = dp_get_panel_mode(link);
2702 enum link_training_result status = LINK_TRAINING_CR_FAIL_LANE0;
2703 struct dc_link_settings cur_link_settings = *link_setting;
2704 struct dc_link_settings max_link_settings = *link_setting;
2705 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
2706 int fail_count = 0;
2707 bool_Bool is_link_bw_low = false0; /* link bandwidth < stream bandwidth */
2708 bool_Bool is_link_bw_min = /* RBR x 1 */
2709 (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2710 (cur_link_settings.lane_count <= LANE_COUNT_ONE);
2711
2712 dp_trace_commit_lt_init(link);
2713
2714 if (dp_get_link_encoding_format(&cur_link_settings) == DP_8b_10b_ENCODING)
2715 /* We need to do this before the link training to ensure the idle
2716 * pattern in SST mode will be sent right after the link training
2717 */
2718 link_hwss->setup_stream_encoder(pipe_ctx);
2719
2720 dp_trace_set_lt_start_timestamp(link, false0);
2721 j = 0;
2722 while (j < attempts && fail_count < (attempts * 10)) {
2723
2724 DC_LOG_HW_LINK_TRAINING("%s: Beginning link(%d) training attempt %u of %d @ rate(%d) x lane(%d)\n",do { } while(0)
2725 __func__, link->link_index, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,do { } while(0)
2726 cur_link_settings.lane_count)do { } while(0);
2727
2728 dp_enable_link_phy(
2729 link,
2730 &pipe_ctx->link_res,
2731 signal,
2732 pipe_ctx->clock_source->id,
2733 &cur_link_settings);
2734
2735 if (stream->sink_patches.dppowerup_delay > 0) {
2736 int delay_dp_power_up_in_ms = stream->sink_patches.dppowerup_delay;
2737
2738 drm_msleep(delay_dp_power_up_in_ms)mdelay(delay_dp_power_up_in_ms);
2739 }
2740
2741#ifdef CONFIG_DRM_AMD_DC_HDCP
2742 if (panel_mode == DP_PANEL_MODE_EDP) {
2743 struct cp_psp *cp_psp = &stream->ctx->cp_psp;
2744
2745 if (cp_psp && cp_psp->funcs.enable_assr)
2746 /* ASSR is bound to fail with unsigned PSP
2747 * verstage used during devlopment phase.
2748 * Report and continue with eDP panel mode to
2749 * perform eDP link training with right settings
2750 */
2751 cp_psp->funcs.enable_assr(cp_psp->handle, link);
2752 }
2753#endif
2754
2755 dp_set_panel_mode(link, panel_mode);
2756
2757 if (link->aux_access_disabled) {
2758 dc_link_dp_perform_link_training_skip_aux(link, &pipe_ctx->link_res, &cur_link_settings);
2759 return true1;
2760 } else {
2761 /** @todo Consolidate USB4 DP and DPx.x training. */
2762 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
2763 status = dc_link_dpia_perform_link_training(link,
2764 &pipe_ctx->link_res,
2765 &cur_link_settings,
2766 skip_video_pattern);
2767
2768 /* Transmit idle pattern once training successful. */
2769 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low) {
2770 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, DP_TEST_PATTERN_VIDEO_MODE, NULL((void *)0), 0);
2771 /* Update verified link settings to current one
2772 * Because DPIA LT might fallback to lower link setting.
2773 */
2774 link->verified_link_cap.link_rate = link->cur_link_settings.link_rate;
2775 link->verified_link_cap.lane_count = link->cur_link_settings.lane_count;
2776 }
2777 } else {
2778 status = dc_link_dp_perform_link_training(link,
2779 &pipe_ctx->link_res,
2780 &cur_link_settings,
2781 skip_video_pattern);
2782 }
2783
2784 dp_trace_lt_total_count_increment(link, false0);
2785 dp_trace_lt_result_update(link, status, false0);
2786 dp_trace_set_lt_end_timestamp(link, false0);
2787 if (status == LINK_TRAINING_SUCCESS && !is_link_bw_low)
2788 return true1;
2789 }
2790
2791 fail_count++;
2792 dp_trace_lt_fail_count_update(link, fail_count, false0);
2793 if (link->ep_type == DISPLAY_ENDPOINT_PHY) {
2794 /* latest link training still fail or link training is aborted
2795 * skip delay and keep PHY on
2796 */
2797 if (j == (attempts - 1) || (status == LINK_TRAINING_ABORT))
2798 break;
2799 }
2800
2801 DC_LOG_WARNING("%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) : fail reason:(%d)\n",printk("\0014" "[" "drm" "] " "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) : fail reason:(%d)\n"
, __func__, link->link_index, (unsigned int)j + 1, attempts
, cur_link_settings.link_rate, cur_link_settings.lane_count, status
)
2802 __func__, link->link_index, (unsigned int)j + 1, attempts, cur_link_settings.link_rate,printk("\0014" "[" "drm" "] " "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) : fail reason:(%d)\n"
, __func__, link->link_index, (unsigned int)j + 1, attempts
, cur_link_settings.link_rate, cur_link_settings.lane_count, status
)
2803 cur_link_settings.lane_count, status)printk("\0014" "[" "drm" "] " "%s: Link(%d) training attempt %u of %d failed @ rate(%d) x lane(%d) : fail reason:(%d)\n"
, __func__, link->link_index, (unsigned int)j + 1, attempts
, cur_link_settings.link_rate, cur_link_settings.lane_count, status
)
;
2804
2805 dp_disable_link_phy(link, &pipe_ctx->link_res, signal);
2806
2807 /* Abort link training if failure due to sink being unplugged. */
2808 if (status == LINK_TRAINING_ABORT) {
2809 enum dc_connection_type type = dc_connection_none;
2810
2811 dc_link_detect_sink(link, &type);
2812 if (type == dc_connection_none) {
2813 DC_LOG_HW_LINK_TRAINING("%s: Aborting training because sink unplugged\n", __func__)do { } while(0);
2814 break;
2815 }
2816 }
2817
2818 /* Try to train again at original settings if:
2819 * - not falling back between training attempts;
2820 * - aborted previous attempt due to reasons other than sink unplug;
2821 * - successfully trained but at a link rate lower than that required by stream;
2822 * - reached minimum link bandwidth.
2823 */
2824 if (!do_fallback || (status == LINK_TRAINING_ABORT) ||
2825 (status == LINK_TRAINING_SUCCESS && is_link_bw_low) ||
2826 is_link_bw_min) {
2827 j++;
2828 cur_link_settings = *link_setting;
2829 delay_between_attempts += LINK_TRAINING_RETRY_DELAY50;
2830 is_link_bw_low = false0;
2831 is_link_bw_min = (cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2832 (cur_link_settings.lane_count <= LANE_COUNT_ONE);
2833
2834 } else if (do_fallback) { /* Try training at lower link bandwidth if doing fallback. */
2835 uint32_t req_bw;
2836 uint32_t link_bw;
2837
2838 decide_fallback_link_setting(link, &max_link_settings,
2839 &cur_link_settings, status);
2840 /* Fail link training if reduced link bandwidth no longer meets
2841 * stream requirements.
2842 */
2843 req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
2844 link_bw = dc_link_bandwidth_kbps(link, &cur_link_settings);
2845 is_link_bw_low = (req_bw > link_bw);
2846 is_link_bw_min = ((cur_link_settings.link_rate <= LINK_RATE_LOW) &&
2847 (cur_link_settings.lane_count <= LANE_COUNT_ONE));
2848 if (is_link_bw_low)
2849 DC_LOG_WARNING(printk("\0014" "[" "drm" "] " "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n"
, __func__, link->link_index, req_bw, link_bw)
2850 "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n",printk("\0014" "[" "drm" "] " "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n"
, __func__, link->link_index, req_bw, link_bw)
2851 __func__, link->link_index, req_bw, link_bw)printk("\0014" "[" "drm" "] " "%s: Link(%d) bandwidth too low after fallback req_bw(%d) > link_bw(%d)\n"
, __func__, link->link_index, req_bw, link_bw)
;
2852 }
2853
2854 drm_msleep(delay_between_attempts)mdelay(delay_between_attempts);
2855 }
2856 return false0;
2857}
2858
2859static enum clock_source_id get_clock_source_id(struct dc_link *link)
2860{
2861 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_UNDEFINED;
2862 struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source;
2863
2864 if (dp_cs != NULL((void *)0)) {
2865 dp_cs_id = dp_cs->id;
2866 } else {
2867 /*
2868 * dp clock source is not initialized for some reason.
2869 * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used
2870 */
2871 ASSERT(dp_cs)do { if (({ static int __warned; int __ret = !!(!(dp_cs)); if
(__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(dp_cs)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 2871); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
2872 }
2873
2874 return dp_cs_id;
2875}
2876
2877static void set_dp_mst_mode(struct dc_link *link, const struct link_resource *link_res,
2878 bool_Bool mst_enable)
2879{
2880 if (mst_enable == false0 &&
2881 link->type == dc_connection_mst_branch) {
2882 /* Disable MST on link. Use only local sink. */
2883 dp_disable_link_phy_mst(link, link_res, link->connector_signal);
2884
2885 link->type = dc_connection_single;
2886 link->local_sink = link->remote_sinks[0];
2887 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
2888 dc_sink_retain(link->local_sink);
2889 dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
2890 } else if (mst_enable == true1 &&
2891 link->type == dc_connection_single &&
2892 link->remote_sinks[0] != NULL((void *)0)) {
2893 /* Re-enable MST on link. */
2894 dp_disable_link_phy(link, link_res, link->connector_signal);
2895 dp_enable_mst_on_sink(link, true1);
2896
2897 link->type = dc_connection_mst_branch;
2898 link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
2899 }
2900}
2901
2902bool_Bool dc_link_dp_sync_lt_begin(struct dc_link *link)
2903{
2904 /* Begin Sync LT. During this time,
2905 * DPCD:600h must not be powered down.
2906 */
2907 link->sync_lt_in_progress = true1;
2908
2909 /*Clear any existing preferred settings.*/
2910 memset(&link->preferred_training_settings, 0,__builtin_memset((&link->preferred_training_settings),
(0), (sizeof(struct dc_link_training_overrides)))
2911 sizeof(struct dc_link_training_overrides))__builtin_memset((&link->preferred_training_settings),
(0), (sizeof(struct dc_link_training_overrides)))
;
2912 memset(&link->preferred_link_setting, 0,__builtin_memset((&link->preferred_link_setting), (0),
(sizeof(struct dc_link_settings)))
2913 sizeof(struct dc_link_settings))__builtin_memset((&link->preferred_link_setting), (0),
(sizeof(struct dc_link_settings)))
;
2914
2915 return true1;
2916}
2917
2918enum link_training_result dc_link_dp_sync_lt_attempt(
2919 struct dc_link *link,
2920 const struct link_resource *link_res,
2921 struct dc_link_settings *link_settings,
2922 struct dc_link_training_overrides *lt_overrides)
2923{
2924 struct link_training_settings lt_settings = {0};
2925 enum link_training_result lt_status = LINK_TRAINING_SUCCESS;
2926 enum dp_panel_mode panel_mode = DP_PANEL_MODE_DEFAULT;
2927 enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_EXTERNAL;
2928 bool_Bool fec_enable = false0;
2929
2930 dp_decide_training_settings(
2931 link,
2932 link_settings,
2933 &lt_settings);
2934 override_training_settings(
2935 link,
2936 lt_overrides,
2937 &lt_settings);
2938 /* Setup MST Mode */
2939 if (lt_overrides->mst_enable)
2940 set_dp_mst_mode(link, link_res, *lt_overrides->mst_enable);
2941
2942 /* Disable link */
2943 dp_disable_link_phy(link, link_res, link->connector_signal);
2944
2945 /* Enable link */
2946 dp_cs_id = get_clock_source_id(link);
2947 dp_enable_link_phy(link, link_res, link->connector_signal,
2948 dp_cs_id, link_settings);
2949
2950 /* Set FEC enable */
2951 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING) {
2952 fec_enable = lt_overrides->fec_enable && *lt_overrides->fec_enable;
2953 dp_set_fec_ready(link, NULL((void *)0), fec_enable);
2954 }
2955
2956 if (lt_overrides->alternate_scrambler_reset) {
2957 if (*lt_overrides->alternate_scrambler_reset)
2958 panel_mode = DP_PANEL_MODE_EDP;
2959 else
2960 panel_mode = DP_PANEL_MODE_DEFAULT;
2961 } else
2962 panel_mode = dp_get_panel_mode(link);
2963
2964 dp_set_panel_mode(link, panel_mode);
2965
2966 /* Attempt to train with given link training settings */
2967 if (link->ctx->dc->work_arounds.lt_early_cr_pattern)
2968 start_clock_recovery_pattern_early(link, link_res, &lt_settings, DPRX);
2969
2970 /* Set link rate, lane count and spread. */
2971 dpcd_set_link_settings(link, &lt_settings);
2972
2973 /* 2. perform link training (set link training done
2974 * to false is done as well)
2975 */
2976 lt_status = perform_clock_recovery_sequence(link, link_res, &lt_settings, DPRX);
2977 if (lt_status == LINK_TRAINING_SUCCESS) {
2978 lt_status = perform_channel_equalization_sequence(link,
2979 link_res,
2980 &lt_settings,
2981 DPRX);
2982 }
2983
2984 /* 3. Sync LT must skip TRAINING_PATTERN_SET:0 (video pattern)*/
2985 /* 4. print status message*/
2986 print_status_message(link, &lt_settings, lt_status);
2987
2988 return lt_status;
2989}
2990
2991bool_Bool dc_link_dp_sync_lt_end(struct dc_link *link, bool_Bool link_down)
2992{
2993 /* If input parameter is set, shut down phy.
2994 * Still shouldn't turn off dp_receiver (DPCD:600h)
2995 */
2996 if (link_down == true1) {
2997 struct dc_link_settings link_settings = link->cur_link_settings;
2998 dp_disable_link_phy(link, NULL((void *)0), link->connector_signal);
2999 if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING)
3000 dp_set_fec_ready(link, NULL((void *)0), false0);
3001 }
3002
3003 link->sync_lt_in_progress = false0;
3004 return true1;
3005}
3006
3007static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
3008{
3009 enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate;
3010
3011 if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20)
3012 lttpr_max_link_rate = LINK_RATE_UHBR20;
3013 else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5)
3014 lttpr_max_link_rate = LINK_RATE_UHBR13_5;
3015 else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR10)
3016 lttpr_max_link_rate = LINK_RATE_UHBR10;
3017
3018 return lttpr_max_link_rate;
3019}
3020
3021static enum dc_link_rate get_cable_max_link_rate(struct dc_link *link)
3022{
3023 enum dc_link_rate cable_max_link_rate = LINK_RATE_HIGH3;
3024
3025 if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR20(1 << 1))
3026 cable_max_link_rate = LINK_RATE_UHBR20;
3027 else if (link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY)
3028 cable_max_link_rate = LINK_RATE_UHBR13_5;
3029 else if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR10(1 << 0))
3030 cable_max_link_rate = LINK_RATE_UHBR10;
3031
3032 return cable_max_link_rate;
3033}
3034
3035bool_Bool dc_link_dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap)
3036{
3037 struct link_encoder *link_enc = NULL((void *)0);
3038
3039 if (!max_link_enc_cap) {
3040 DC_LOG_ERROR("%s: Could not return max link encoder caps", __func__)__drm_err("%s: Could not return max link encoder caps", __func__
)
;
3041 return false0;
3042 }
3043
3044 link_enc = link_enc_cfg_get_link_enc(link);
3045 ASSERT(link_enc)do { if (({ static int __warned; int __ret = !!(!(link_enc));
if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(link_enc)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 3045); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
3046
3047 if (link_enc && link_enc->funcs->get_max_link_cap) {
3048 link_enc->funcs->get_max_link_cap(link_enc, max_link_enc_cap);
3049 return true1;
3050 }
3051
3052 DC_LOG_ERROR("%s: Max link encoder caps unknown", __func__)__drm_err("%s: Max link encoder caps unknown", __func__);
3053 max_link_enc_cap->lane_count = 1;
3054 max_link_enc_cap->link_rate = 6;
3055 return false0;
3056}
3057
3058
3059struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
3060{
3061 struct dc_link_settings max_link_cap = {0};
3062 enum dc_link_rate lttpr_max_link_rate;
3063 enum dc_link_rate cable_max_link_rate;
3064 struct link_encoder *link_enc = NULL((void *)0);
3065
3066
3067 link_enc = link_enc_cfg_get_link_enc(link);
3068 ASSERT(link_enc)do { if (({ static int __warned; int __ret = !!(!(link_enc));
if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(link_enc)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 3068); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
3069
3070 /* get max link encoder capability */
3071 if (link_enc)
3072 link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap);
3073
3074 /* Lower link settings based on sink's link cap */
3075 if (link->reported_link_cap.lane_count < max_link_cap.lane_count)
3076 max_link_cap.lane_count =
3077 link->reported_link_cap.lane_count;
3078 if (link->reported_link_cap.link_rate < max_link_cap.link_rate)
3079 max_link_cap.link_rate =
3080 link->reported_link_cap.link_rate;
3081 if (link->reported_link_cap.link_spread <
3082 max_link_cap.link_spread)
3083 max_link_cap.link_spread =
3084 link->reported_link_cap.link_spread;
3085
3086 /* Lower link settings based on cable attributes */
3087 cable_max_link_rate = get_cable_max_link_rate(link);
3088
3089 if (!link->dc->debug.ignore_cable_id &&
3090 cable_max_link_rate < max_link_cap.link_rate)
3091 max_link_cap.link_rate = cable_max_link_rate;
3092
3093 /*
3094 * account for lttpr repeaters cap
3095 * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
3096 */
3097 if (dp_is_lttpr_present(link)) {
3098 if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count)
3099 max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count;
3100 lttpr_max_link_rate = get_lttpr_max_link_rate(link);
3101
3102 if (lttpr_max_link_rate < max_link_cap.link_rate)
3103 max_link_cap.link_rate = lttpr_max_link_rate;
3104
3105 DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n",do { } while(0)
3106 __func__,do { } while(0)
3107 max_link_cap.lane_count,do { } while(0)
3108 max_link_cap.link_rate)do { } while(0);
3109 }
3110
3111 if (dp_get_link_encoding_format(&max_link_cap) == DP_128b_132b_ENCODING &&
3112 link->dc->debug.disable_uhbr)
3113 max_link_cap.link_rate = LINK_RATE_HIGH3;
3114
3115 return max_link_cap;
3116}
3117
3118enum dc_status read_hpd_rx_irq_data(
3119 struct dc_link *link,
3120 union hpd_irq_data *irq_data)
3121{
3122 static enum dc_status retval;
3123
3124 /* The HW reads 16 bytes from 200h on HPD,
3125 * but if we get an AUX_DEFER, the HW cannot retry
3126 * and this causes the CTS tests 4.3.2.1 - 3.2.4 to
3127 * fail, so we now explicitly read 6 bytes which is
3128 * the req from the above mentioned test cases.
3129 *
3130 * For DP 1.4 we need to read those from 2002h range.
3131 */
3132 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
3133 retval = core_link_read_dpcd(
3134 link,
3135 DP_SINK_COUNT0x200,
3136 irq_data->raw,
3137 sizeof(union hpd_irq_data));
3138 else {
3139 /* Read 14 bytes in a single read and then copy only the required fields.
3140 * This is more efficient than doing it in two separate AUX reads. */
3141
3142 uint8_t tmp[DP_SINK_STATUS_ESI0x200f - DP_SINK_COUNT_ESI0x2002 + 1];
3143
3144 retval = core_link_read_dpcd(
3145 link,
3146 DP_SINK_COUNT_ESI0x2002,
3147 tmp,
3148 sizeof(tmp));
3149
3150 if (retval != DC_OK)
3151 return retval;
3152
3153 irq_data->bytes.sink_cnt.raw = tmp[DP_SINK_COUNT_ESI0x2002 - DP_SINK_COUNT_ESI0x2002];
3154 irq_data->bytes.device_service_irq.raw = tmp[DP_DEVICE_SERVICE_IRQ_VECTOR_ESI00x2003 - DP_SINK_COUNT_ESI0x2002];
3155 irq_data->bytes.lane01_status.raw = tmp[DP_LANE0_1_STATUS_ESI0x200c - DP_SINK_COUNT_ESI0x2002];
3156 irq_data->bytes.lane23_status.raw = tmp[DP_LANE2_3_STATUS_ESI0x200d - DP_SINK_COUNT_ESI0x2002];
3157 irq_data->bytes.lane_status_updated.raw = tmp[DP_LANE_ALIGN_STATUS_UPDATED_ESI0x200e - DP_SINK_COUNT_ESI0x2002];
3158 irq_data->bytes.sink_status.raw = tmp[DP_SINK_STATUS_ESI0x200f - DP_SINK_COUNT_ESI0x2002];
3159 }
3160
3161 return retval;
3162}
3163
3164bool_Bool hpd_rx_irq_check_link_loss_status(
3165 struct dc_link *link,
3166 union hpd_irq_data *hpd_irq_dpcd_data)
3167{
3168 uint8_t irq_reg_rx_power_state = 0;
3169 enum dc_status dpcd_result = DC_ERROR_UNEXPECTED;
3170 union lane_status lane_status;
3171 uint32_t lane;
3172 bool_Bool sink_status_changed;
3173 bool_Bool return_code;
3174
3175 sink_status_changed = false0;
3176 return_code = false0;
3177
3178 if (link->cur_link_settings.lane_count == 0)
3179 return return_code;
3180
3181 /*1. Check that Link Status changed, before re-training.*/
3182
3183 /*parse lane status*/
3184 for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) {
3185 /* check status of lanes 0,1
3186 * changed DpcdAddress_Lane01Status (0x202)
3187 */
3188 lane_status.raw = get_nibble_at_index(
3189 &hpd_irq_dpcd_data->bytes.lane01_status.raw,
3190 lane);
3191
3192 if (!lane_status.bits.CHANNEL_EQ_DONE_0 ||
3193 !lane_status.bits.CR_DONE_0 ||
3194 !lane_status.bits.SYMBOL_LOCKED_0) {
3195 /* if one of the channel equalization, clock
3196 * recovery or symbol lock is dropped
3197 * consider it as (link has been
3198 * dropped) dp sink status has changed
3199 */
3200 sink_status_changed = true1;
3201 break;
3202 }
3203 }
3204
3205 /* Check interlane align.*/
3206 if (sink_status_changed ||
3207 !hpd_irq_dpcd_data->bytes.lane_status_updated.bits.INTERLANE_ALIGN_DONE) {
3208
3209 DC_LOG_HW_HPD_IRQ("%s: Link Status changed.\n", __func__)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: Link Status changed.\n"
, __func__)
;
3210
3211 return_code = true1;
3212
3213 /*2. Check that we can handle interrupt: Not in FS DOS,
3214 * Not in "Display Timeout" state, Link is trained.
3215 */
3216 dpcd_result = core_link_read_dpcd(link,
3217 DP_SET_POWER0x600,
3218 &irq_reg_rx_power_state,
3219 sizeof(irq_reg_rx_power_state));
3220
3221 if (dpcd_result != DC_OK) {
3222 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain power state.\n",___drm_dbg(((void *)0), DRM_UT_KMS, "%s: DPCD read failed to obtain power state.\n"
, __func__)
3223 __func__)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: DPCD read failed to obtain power state.\n"
, __func__)
;
3224 } else {
3225 if (irq_reg_rx_power_state != DP_SET_POWER_D00x1)
3226 return_code = false0;
3227 }
3228 }
3229
3230 return return_code;
3231}
3232
3233static bool_Bool dp_verify_link_cap(
3234 struct dc_link *link,
3235 struct dc_link_settings *known_limit_link_setting,
3236 int *fail_count)
3237{
3238 struct dc_link_settings cur_link_settings = {0};
3239 struct dc_link_settings max_link_settings = *known_limit_link_setting;
3240 bool_Bool success = false0;
3241 bool_Bool skip_video_pattern;
3242 enum clock_source_id dp_cs_id = get_clock_source_id(link);
3243 enum link_training_result status = LINK_TRAINING_SUCCESS;
3244 union hpd_irq_data irq_data;
3245 struct link_resource link_res;
3246
3247 memset(&irq_data, 0, sizeof(irq_data))__builtin_memset((&irq_data), (0), (sizeof(irq_data)));
3248 cur_link_settings = max_link_settings;
3249
3250 /* Grant extended timeout request */
3251 if (dp_is_lttpr_present(link) && link->dpcd_caps.lttpr_caps.max_ext_timeout > 0) {
3252 uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80;
3253
3254 core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT0xf0005, &grant, sizeof(grant));
3255 }
3256
3257 do {
3258 if (!get_temp_dp_link_res(link, &link_res, &cur_link_settings))
3259 continue;
3260
3261 skip_video_pattern = cur_link_settings.link_rate != LINK_RATE_LOW;
3262 dp_enable_link_phy(
3263 link,
3264 &link_res,
3265 link->connector_signal,
3266 dp_cs_id,
3267 &cur_link_settings);
3268
3269 status = dc_link_dp_perform_link_training(
3270 link,
3271 &link_res,
3272 &cur_link_settings,
3273 skip_video_pattern);
3274
3275 if (status == LINK_TRAINING_SUCCESS) {
3276 success = true1;
3277 udelay(1000);
3278 if (read_hpd_rx_irq_data(link, &irq_data) == DC_OK &&
3279 hpd_rx_irq_check_link_loss_status(
3280 link,
3281 &irq_data))
3282 (*fail_count)++;
3283
3284 } else {
3285 (*fail_count)++;
3286 }
3287 dp_trace_lt_total_count_increment(link, true1);
3288 dp_trace_lt_result_update(link, status, true1);
3289 dp_disable_link_phy(link, &link_res, link->connector_signal);
3290 } while (!success && decide_fallback_link_setting(link,
3291 &max_link_settings, &cur_link_settings, status));
3292
3293 link->verified_link_cap = success ?
3294 cur_link_settings : fail_safe_link_settings;
3295 return success;
3296}
3297
3298static void apply_usbc_combo_phy_reset_wa(struct dc_link *link,
3299 struct dc_link_settings *link_settings)
3300{
3301 /* Temporary Renoir-specific workaround PHY will sometimes be in bad
3302 * state on hotplugging display from certain USB-C dongle, so add extra
3303 * cycle of enabling and disabling the PHY before first link training.
3304 */
3305 struct link_resource link_res = {0};
3306 enum clock_source_id dp_cs_id = get_clock_source_id(link);
3307
3308 dp_enable_link_phy(link, &link_res, link->connector_signal,
3309 dp_cs_id, link_settings);
3310 dp_disable_link_phy(link, &link_res, link->connector_signal);
3311}
3312
3313bool_Bool dp_verify_link_cap_with_retries(
3314 struct dc_link *link,
3315 struct dc_link_settings *known_limit_link_setting,
3316 int attempts)
3317{
3318 int i = 0;
3319 bool_Bool success = false0;
3320 int fail_count = 0;
3321
3322 dp_trace_detect_lt_init(link);
3323
3324 if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C &&
3325 link->dc->debug.usbc_combo_phy_reset_wa)
3326 apply_usbc_combo_phy_reset_wa(link, known_limit_link_setting);
3327
3328 dp_trace_set_lt_start_timestamp(link, false0);
3329 for (i = 0; i < attempts; i++) {
3330 enum dc_connection_type type = dc_connection_none;
3331
3332 memset(&link->verified_link_cap, 0,__builtin_memset((&link->verified_link_cap), (0), (sizeof
(struct dc_link_settings)))
3333 sizeof(struct dc_link_settings))__builtin_memset((&link->verified_link_cap), (0), (sizeof
(struct dc_link_settings)))
;
3334 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none) {
3335 link->verified_link_cap = fail_safe_link_settings;
3336 break;
3337 } else if (dp_verify_link_cap(link, known_limit_link_setting,
3338 &fail_count) && fail_count == 0) {
3339 success = true1;
3340 break;
3341 }
3342 drm_msleep(10)mdelay(10);
3343 }
3344
3345 dp_trace_lt_fail_count_update(link, fail_count, true1);
3346 dp_trace_set_lt_end_timestamp(link, true1);
3347
3348 return success;
3349}
3350
3351/* in DP compliance test, DPR-120 may have
3352 * a random value in its MAX_LINK_BW dpcd field.
3353 * We map it to the maximum supported link rate that
3354 * is smaller than MAX_LINK_BW in this case.
3355 */
3356static enum dc_link_rate get_link_rate_from_max_link_bw(
3357 uint8_t max_link_bw)
3358{
3359 enum dc_link_rate link_rate;
3360
3361 if (max_link_bw >= LINK_RATE_HIGH3) {
3362 link_rate = LINK_RATE_HIGH3;
3363 } else if (max_link_bw < LINK_RATE_HIGH3
3364 && max_link_bw >= LINK_RATE_HIGH2) {
3365 link_rate = LINK_RATE_HIGH2;
3366 } else if (max_link_bw < LINK_RATE_HIGH2
3367 && max_link_bw >= LINK_RATE_HIGH) {
3368 link_rate = LINK_RATE_HIGH;
3369 } else if (max_link_bw < LINK_RATE_HIGH
3370 && max_link_bw >= LINK_RATE_LOW) {
3371 link_rate = LINK_RATE_LOW;
3372 } else {
3373 link_rate = LINK_RATE_UNKNOWN;
3374 }
3375
3376 return link_rate;
3377}
3378
3379static inline bool_Bool reached_minimum_lane_count(enum dc_lane_count lane_count)
3380{
3381 return lane_count <= LANE_COUNT_ONE;
3382}
3383
3384static inline bool_Bool reached_minimum_link_rate(enum dc_link_rate link_rate)
3385{
3386 return link_rate <= LINK_RATE_LOW;
3387}
3388
3389static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count)
3390{
3391 switch (lane_count) {
3392 case LANE_COUNT_FOUR:
3393 return LANE_COUNT_TWO;
3394 case LANE_COUNT_TWO:
3395 return LANE_COUNT_ONE;
3396 case LANE_COUNT_ONE:
3397 return LANE_COUNT_UNKNOWN;
3398 default:
3399 return LANE_COUNT_UNKNOWN;
3400 }
3401}
3402
3403static enum dc_link_rate reduce_link_rate(enum dc_link_rate link_rate)
3404{
3405 switch (link_rate) {
3406 case LINK_RATE_UHBR20:
3407 return LINK_RATE_UHBR13_5;
3408 case LINK_RATE_UHBR13_5:
3409 return LINK_RATE_UHBR10;
3410 case LINK_RATE_UHBR10:
3411 return LINK_RATE_HIGH3;
3412 case LINK_RATE_HIGH3:
3413 return LINK_RATE_HIGH2;
3414 case LINK_RATE_HIGH2:
3415 return LINK_RATE_HIGH;
3416 case LINK_RATE_HIGH:
3417 return LINK_RATE_LOW;
3418 case LINK_RATE_LOW:
3419 return LINK_RATE_UNKNOWN;
3420 default:
3421 return LINK_RATE_UNKNOWN;
3422 }
3423}
3424
3425static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count)
3426{
3427 switch (lane_count) {
3428 case LANE_COUNT_ONE:
3429 return LANE_COUNT_TWO;
3430 case LANE_COUNT_TWO:
3431 return LANE_COUNT_FOUR;
3432 default:
3433 return LANE_COUNT_UNKNOWN;
3434 }
3435}
3436
3437static enum dc_link_rate increase_link_rate(struct dc_link *link,
3438 enum dc_link_rate link_rate)
3439{
3440 switch (link_rate) {
3441 case LINK_RATE_LOW:
3442 return LINK_RATE_HIGH;
3443 case LINK_RATE_HIGH:
3444 return LINK_RATE_HIGH2;
3445 case LINK_RATE_HIGH2:
3446 return LINK_RATE_HIGH3;
3447 case LINK_RATE_HIGH3:
3448 return LINK_RATE_UHBR10;
3449 case LINK_RATE_UHBR10:
3450 /* upto DP2.x specs UHBR13.5 is the only link rate that could be
3451 * not supported by DPRX when higher link rate is supported.
3452 * so we treat it as a special case for code simplicity. When we
3453 * have new specs with more link rates like this, we should
3454 * consider a more generic solution to handle discrete link
3455 * rate capabilities.
3456 */
3457 return link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 ?
3458 LINK_RATE_UHBR13_5 : LINK_RATE_UHBR20;
3459 case LINK_RATE_UHBR13_5:
3460 return LINK_RATE_UHBR20;
3461 default:
3462 return LINK_RATE_UNKNOWN;
3463 }
3464}
3465
3466static bool_Bool decide_fallback_link_setting_max_bw_policy(
3467 struct dc_link *link,
3468 const struct dc_link_settings *max,
3469 struct dc_link_settings *cur,
3470 enum link_training_result training_result)
3471{
3472 uint8_t cur_idx = 0, next_idx;
3473 bool_Bool found = false0;
3474
3475 if (training_result == LINK_TRAINING_ABORT)
3476 return false0;
3477
3478 while (cur_idx < ARRAY_SIZE(dp_lt_fallbacks)(sizeof((dp_lt_fallbacks)) / sizeof((dp_lt_fallbacks)[0])))
3479 /* find current index */
3480 if (dp_lt_fallbacks[cur_idx].lane_count == cur->lane_count &&
3481 dp_lt_fallbacks[cur_idx].link_rate == cur->link_rate)
3482 break;
3483 else
3484 cur_idx++;
3485
3486 next_idx = cur_idx + 1;
3487
3488 while (next_idx < ARRAY_SIZE(dp_lt_fallbacks)(sizeof((dp_lt_fallbacks)) / sizeof((dp_lt_fallbacks)[0])))
3489 /* find next index */
3490 if (dp_lt_fallbacks[next_idx].lane_count > max->lane_count ||
3491 dp_lt_fallbacks[next_idx].link_rate > max->link_rate)
3492 next_idx++;
3493 else if (dp_lt_fallbacks[next_idx].link_rate == LINK_RATE_UHBR13_5 &&
3494 link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 == 0)
3495 /* upto DP2.x specs UHBR13.5 is the only link rate that
3496 * could be not supported by DPRX when higher link rate
3497 * is supported. so we treat it as a special case for
3498 * code simplicity. When we have new specs with more
3499 * link rates like this, we should consider a more
3500 * generic solution to handle discrete link rate
3501 * capabilities.
3502 */
3503 next_idx++;
3504 else
3505 break;
3506
3507 if (next_idx < ARRAY_SIZE(dp_lt_fallbacks)(sizeof((dp_lt_fallbacks)) / sizeof((dp_lt_fallbacks)[0]))) {
3508 cur->lane_count = dp_lt_fallbacks[next_idx].lane_count;
3509 cur->link_rate = dp_lt_fallbacks[next_idx].link_rate;
3510 found = true1;
3511 }
3512
3513 return found;
3514}
3515
3516/*
3517 * function: set link rate and lane count fallback based
3518 * on current link setting and last link training result
3519 * return value:
3520 * true - link setting could be set
3521 * false - has reached minimum setting
3522 * and no further fallback could be done
3523 */
3524static bool_Bool decide_fallback_link_setting(
3525 struct dc_link *link,
3526 struct dc_link_settings *max,
3527 struct dc_link_settings *cur,
3528 enum link_training_result training_result)
3529{
3530 if (dp_get_link_encoding_format(max) == DP_128b_132b_ENCODING ||
3531 link->dc->debug.force_dp2_lt_fallback_method)
3532 return decide_fallback_link_setting_max_bw_policy(link, max, cur,
3533 training_result);
3534
3535 switch (training_result) {
3536 case LINK_TRAINING_CR_FAIL_LANE0:
3537 case LINK_TRAINING_CR_FAIL_LANE1:
3538 case LINK_TRAINING_CR_FAIL_LANE23:
3539 case LINK_TRAINING_LQA_FAIL:
3540 {
3541 if (!reached_minimum_link_rate(cur->link_rate)) {
3542 cur->link_rate = reduce_link_rate(cur->link_rate);
3543 } else if (!reached_minimum_lane_count(cur->lane_count)) {
3544 cur->link_rate = max->link_rate;
3545 if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
3546 return false0;
3547 else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
3548 cur->lane_count = LANE_COUNT_ONE;
3549 else if (training_result == LINK_TRAINING_CR_FAIL_LANE23)
3550 cur->lane_count = LANE_COUNT_TWO;
3551 else
3552 cur->lane_count = reduce_lane_count(cur->lane_count);
3553 } else {
3554 return false0;
3555 }
3556 break;
3557 }
3558 case LINK_TRAINING_EQ_FAIL_EQ:
3559 case LINK_TRAINING_EQ_FAIL_CR_PARTIAL:
3560 {
3561 if (!reached_minimum_lane_count(cur->lane_count)) {
3562 cur->lane_count = reduce_lane_count(cur->lane_count);
3563 } else if (!reached_minimum_link_rate(cur->link_rate)) {
3564 cur->link_rate = reduce_link_rate(cur->link_rate);
3565 /* Reduce max link rate to avoid potential infinite loop.
3566 * Needed so that any subsequent CR_FAIL fallback can't
3567 * re-set the link rate higher than the link rate from
3568 * the latest EQ_FAIL fallback.
3569 */
3570 max->link_rate = cur->link_rate;
3571 cur->lane_count = max->lane_count;
3572 } else {
3573 return false0;
3574 }
3575 break;
3576 }
3577 case LINK_TRAINING_EQ_FAIL_CR:
3578 {
3579 if (!reached_minimum_link_rate(cur->link_rate)) {
3580 cur->link_rate = reduce_link_rate(cur->link_rate);
3581 /* Reduce max link rate to avoid potential infinite loop.
3582 * Needed so that any subsequent CR_FAIL fallback can't
3583 * re-set the link rate higher than the link rate from
3584 * the latest EQ_FAIL fallback.
3585 */
3586 max->link_rate = cur->link_rate;
3587 cur->lane_count = max->lane_count;
3588 } else {
3589 return false0;
3590 }
3591 break;
3592 }
3593 default:
3594 return false0;
3595 }
3596 return true1;
3597}
3598
3599bool_Bool dp_validate_mode_timing(
3600 struct dc_link *link,
3601 const struct dc_crtc_timing *timing)
3602{
3603 uint32_t req_bw;
3604 uint32_t max_bw;
3605
3606 const struct dc_link_settings *link_setting;
3607
3608 /* According to spec, VSC SDP should be used if pixel format is YCbCr420 */
3609 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 &&
3610 !link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED &&
3611 dal_graphics_object_id_get_connector_id(link->link_id) != CONNECTOR_ID_VIRTUAL)
3612 return false0;
3613
3614 /*always DP fail safe mode*/
3615 if ((timing->pix_clk_100hz / 10) == (uint32_t) 25175 &&
3616 timing->h_addressable == (uint32_t) 640 &&
3617 timing->v_addressable == (uint32_t) 480)
3618 return true1;
3619
3620 link_setting = dc_link_get_link_cap(link);
3621
3622 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
3623 /*if (flags.DYNAMIC_VALIDATION == 1 &&
3624 link->verified_link_cap.lane_count != LANE_COUNT_UNKNOWN)
3625 link_setting = &link->verified_link_cap;
3626 */
3627
3628 req_bw = dc_bandwidth_in_kbps_from_timing(timing);
3629 max_bw = dc_link_bandwidth_kbps(link, link_setting);
3630
3631 if (req_bw <= max_bw) {
3632 /* remember the biggest mode here, during
3633 * initial link training (to get
3634 * verified_link_cap), LS sends event about
3635 * cannot train at reported cap to upper
3636 * layer and upper layer will re-enumerate modes.
3637 * this is not necessary if the lower
3638 * verified_link_cap is enough to drive
3639 * all the modes */
3640
3641 /* TODO: DYNAMIC_VALIDATION needs to be implemented */
3642 /* if (flags.DYNAMIC_VALIDATION == 1)
3643 dpsst->max_req_bw_for_verified_linkcap = dal_max(
3644 dpsst->max_req_bw_for_verified_linkcap, req_bw); */
3645 return true1;
3646 } else
3647 return false0;
3648}
3649
3650static bool_Bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
3651{
3652 struct dc_link_settings initial_link_setting = {
3653 LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false0, 0};
3654 struct dc_link_settings current_link_setting =
3655 initial_link_setting;
3656 uint32_t link_bw;
3657
3658 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
3659 return false0;
3660
3661 /* search for the minimum link setting that:
3662 * 1. is supported according to the link training result
3663 * 2. could support the b/w requested by the timing
3664 */
3665 while (current_link_setting.link_rate <=
3666 link->verified_link_cap.link_rate) {
3667 link_bw = dc_link_bandwidth_kbps(
3668 link,
3669 &current_link_setting);
3670 if (req_bw <= link_bw) {
3671 *link_setting = current_link_setting;
3672 return true1;
3673 }
3674
3675 if (current_link_setting.lane_count <
3676 link->verified_link_cap.lane_count) {
3677 current_link_setting.lane_count =
3678 increase_lane_count(
3679 current_link_setting.lane_count);
3680 } else {
3681 current_link_setting.link_rate =
3682 increase_link_rate(link,
3683 current_link_setting.link_rate);
3684 current_link_setting.lane_count =
3685 initial_link_setting.lane_count;
3686 }
3687 }
3688
3689 return false0;
3690}
3691
3692bool_Bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw)
3693{
3694 struct dc_link_settings initial_link_setting;
3695 struct dc_link_settings current_link_setting;
3696 uint32_t link_bw;
3697
3698 /*
3699 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
3700 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
3701 */
3702 if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
3703 link->dpcd_caps.edp_supported_link_rates_count == 0) {
3704 *link_setting = link->verified_link_cap;
3705 return true1;
3706 }
3707
3708 memset(&initial_link_setting, 0, sizeof(initial_link_setting))__builtin_memset((&initial_link_setting), (0), (sizeof(initial_link_setting
)))
;
3709 initial_link_setting.lane_count = LANE_COUNT_ONE;
3710 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
3711 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3712 initial_link_setting.use_link_rate_set = true1;
3713 initial_link_setting.link_rate_set = 0;
3714 current_link_setting = initial_link_setting;
3715
3716 /* search for the minimum link setting that:
3717 * 1. is supported according to the link training result
3718 * 2. could support the b/w requested by the timing
3719 */
3720 while (current_link_setting.link_rate <=
3721 link->verified_link_cap.link_rate) {
3722 link_bw = dc_link_bandwidth_kbps(
3723 link,
3724 &current_link_setting);
3725 if (req_bw <= link_bw) {
3726 *link_setting = current_link_setting;
3727 return true1;
3728 }
3729
3730 if (current_link_setting.lane_count <
3731 link->verified_link_cap.lane_count) {
3732 current_link_setting.lane_count =
3733 increase_lane_count(
3734 current_link_setting.lane_count);
3735 } else {
3736 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
3737 current_link_setting.link_rate_set++;
3738 current_link_setting.link_rate =
3739 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3740 current_link_setting.lane_count =
3741 initial_link_setting.lane_count;
3742 } else
3743 break;
3744 }
3745 }
3746 return false0;
3747}
3748
3749static bool_Bool decide_edp_link_settings_with_dsc(struct dc_link *link,
3750 struct dc_link_settings *link_setting,
3751 uint32_t req_bw,
3752 enum dc_link_rate max_link_rate)
3753{
3754 struct dc_link_settings initial_link_setting;
3755 struct dc_link_settings current_link_setting;
3756 uint32_t link_bw;
3757
3758 unsigned int policy = 0;
3759
3760 policy = link->panel_config.dsc.force_dsc_edp_policy;
3761 if (max_link_rate == LINK_RATE_UNKNOWN)
3762 max_link_rate = link->verified_link_cap.link_rate;
3763 /*
3764 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
3765 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
3766 */
3767 if ((link->dpcd_caps.dpcd_rev.raw < DPCD_REV_13 ||
3768 link->dpcd_caps.edp_supported_link_rates_count == 0)) {
3769 /* for DSC enabled case, we search for minimum lane count */
3770 memset(&initial_link_setting, 0, sizeof(initial_link_setting))__builtin_memset((&initial_link_setting), (0), (sizeof(initial_link_setting
)))
;
3771 initial_link_setting.lane_count = LANE_COUNT_ONE;
3772 initial_link_setting.link_rate = LINK_RATE_LOW;
3773 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3774 initial_link_setting.use_link_rate_set = false0;
3775 initial_link_setting.link_rate_set = 0;
3776 current_link_setting = initial_link_setting;
3777 if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
3778 return false0;
3779
3780 /* search for the minimum link setting that:
3781 * 1. is supported according to the link training result
3782 * 2. could support the b/w requested by the timing
3783 */
3784 while (current_link_setting.link_rate <=
3785 max_link_rate) {
3786 link_bw = dc_link_bandwidth_kbps(
3787 link,
3788 &current_link_setting);
3789 if (req_bw <= link_bw) {
3790 *link_setting = current_link_setting;
3791 return true1;
3792 }
3793 if (policy) {
3794 /* minimize lane */
3795 if (current_link_setting.link_rate < max_link_rate) {
3796 current_link_setting.link_rate =
3797 increase_link_rate(link,
3798 current_link_setting.link_rate);
3799 } else {
3800 if (current_link_setting.lane_count <
3801 link->verified_link_cap.lane_count) {
3802 current_link_setting.lane_count =
3803 increase_lane_count(
3804 current_link_setting.lane_count);
3805 current_link_setting.link_rate = initial_link_setting.link_rate;
3806 } else
3807 break;
3808 }
3809 } else {
3810 /* minimize link rate */
3811 if (current_link_setting.lane_count <
3812 link->verified_link_cap.lane_count) {
3813 current_link_setting.lane_count =
3814 increase_lane_count(
3815 current_link_setting.lane_count);
3816 } else {
3817 current_link_setting.link_rate =
3818 increase_link_rate(link,
3819 current_link_setting.link_rate);
3820 current_link_setting.lane_count =
3821 initial_link_setting.lane_count;
3822 }
3823 }
3824 }
3825 return false0;
3826 }
3827
3828 /* if optimize edp link is supported */
3829 memset(&initial_link_setting, 0, sizeof(initial_link_setting))__builtin_memset((&initial_link_setting), (0), (sizeof(initial_link_setting
)))
;
3830 initial_link_setting.lane_count = LANE_COUNT_ONE;
3831 initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0];
3832 initial_link_setting.link_spread = LINK_SPREAD_DISABLED;
3833 initial_link_setting.use_link_rate_set = true1;
3834 initial_link_setting.link_rate_set = 0;
3835 current_link_setting = initial_link_setting;
3836
3837 /* search for the minimum link setting that:
3838 * 1. is supported according to the link training result
3839 * 2. could support the b/w requested by the timing
3840 */
3841 while (current_link_setting.link_rate <=
3842 max_link_rate) {
3843 link_bw = dc_link_bandwidth_kbps(
3844 link,
3845 &current_link_setting);
3846 if (req_bw <= link_bw) {
3847 *link_setting = current_link_setting;
3848 return true1;
3849 }
3850 if (policy) {
3851 /* minimize lane */
3852 if (current_link_setting.link_rate_set <
3853 link->dpcd_caps.edp_supported_link_rates_count
3854 && current_link_setting.link_rate < max_link_rate) {
3855 current_link_setting.link_rate_set++;
3856 current_link_setting.link_rate =
3857 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3858 } else {
3859 if (current_link_setting.lane_count < link->verified_link_cap.lane_count) {
3860 current_link_setting.lane_count =
3861 increase_lane_count(
3862 current_link_setting.lane_count);
3863 current_link_setting.link_rate_set = initial_link_setting.link_rate_set;
3864 current_link_setting.link_rate =
3865 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3866 } else
3867 break;
3868 }
3869 } else {
3870 /* minimize link rate */
3871 if (current_link_setting.lane_count <
3872 link->verified_link_cap.lane_count) {
3873 current_link_setting.lane_count =
3874 increase_lane_count(
3875 current_link_setting.lane_count);
3876 } else {
3877 if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
3878 current_link_setting.link_rate_set++;
3879 current_link_setting.link_rate =
3880 link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set];
3881 current_link_setting.lane_count =
3882 initial_link_setting.lane_count;
3883 } else
3884 break;
3885 }
3886 }
3887 }
3888 return false0;
3889}
3890
3891static bool_Bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting)
3892{
3893 *link_setting = link->verified_link_cap;
3894 return true1;
3895}
3896
3897bool_Bool decide_link_settings(struct dc_stream_state *stream,
3898 struct dc_link_settings *link_setting)
3899{
3900 struct dc_link *link = stream->link;
3901 uint32_t req_bw = dc_bandwidth_in_kbps_from_timing(&stream->timing);
3902
3903 memset(link_setting, 0, sizeof(*link_setting))__builtin_memset((link_setting), (0), (sizeof(*link_setting))
)
;
3904
3905 /* if preferred is specified through AMDDP, use it, if it's enough
3906 * to drive the mode
3907 */
3908 if (link->preferred_link_setting.lane_count !=
3909 LANE_COUNT_UNKNOWN &&
3910 link->preferred_link_setting.link_rate !=
3911 LINK_RATE_UNKNOWN) {
3912 *link_setting = link->preferred_link_setting;
3913 return true1;
3914 }
3915
3916 /* MST doesn't perform link training for now
3917 * TODO: add MST specific link training routine
3918 */
3919 if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
3920 decide_mst_link_settings(link, link_setting);
3921 } else if (link->connector_signal == SIGNAL_TYPE_EDP) {
3922 /* enable edp link optimization for DSC eDP case */
3923 if (stream->timing.flags.DSC) {
3924 enum dc_link_rate max_link_rate = LINK_RATE_UNKNOWN;
3925
3926 if (link->panel_config.dsc.force_dsc_edp_policy) {
3927 /* calculate link max link rate cap*/
3928 struct dc_link_settings tmp_link_setting;
3929 struct dc_crtc_timing tmp_timing = stream->timing;
3930 uint32_t orig_req_bw;
3931
3932 tmp_link_setting.link_rate = LINK_RATE_UNKNOWN;
3933 tmp_timing.flags.DSC = 0;
3934 orig_req_bw = dc_bandwidth_in_kbps_from_timing(&tmp_timing);
3935 decide_edp_link_settings(link, &tmp_link_setting, orig_req_bw);
3936 max_link_rate = tmp_link_setting.link_rate;
3937 }
3938 decide_edp_link_settings_with_dsc(link, link_setting, req_bw, max_link_rate);
3939 } else {
3940 decide_edp_link_settings(link, link_setting, req_bw);
3941 }
3942 } else {
3943 decide_dp_link_settings(link, link_setting, req_bw);
3944 }
3945
3946 return link_setting->lane_count != LANE_COUNT_UNKNOWN &&
3947 link_setting->link_rate != LINK_RATE_UNKNOWN;
3948}
3949
3950/*************************Short Pulse IRQ***************************/
3951bool_Bool dc_link_dp_allow_hpd_rx_irq(const struct dc_link *link)
3952{
3953 /*
3954 * Don't handle RX IRQ unless one of following is met:
3955 * 1) The link is established (cur_link_settings != unknown)
3956 * 2) We know we're dealing with a branch device, SST or MST
3957 */
3958
3959 if ((link->cur_link_settings.lane_count != LANE_COUNT_UNKNOWN) ||
3960 is_dp_branch_device(link))
3961 return true1;
3962
3963 return false0;
3964}
3965
3966static bool_Bool handle_hpd_irq_psr_sink(struct dc_link *link)
3967{
3968 union dpcd_psr_configuration psr_configuration;
3969
3970 if (!link->psr_settings.psr_feature_enabled)
3971 return false0;
3972
3973 dm_helpers_dp_read_dpcd(
3974 link->ctx,
3975 link,
3976 368,/*DpcdAddress_PSR_Enable_Cfg*/
3977 &psr_configuration.raw,
3978 sizeof(psr_configuration.raw));
3979
3980 if (psr_configuration.bits.ENABLE) {
3981 unsigned char dpcdbuf[3] = {0};
3982 union psr_error_status psr_error_status;
3983 union psr_sink_psr_status psr_sink_psr_status;
3984
3985 dm_helpers_dp_read_dpcd(
3986 link->ctx,
3987 link,
3988 0x2006, /*DpcdAddress_PSR_Error_Status*/
3989 (unsigned char *) dpcdbuf,
3990 sizeof(dpcdbuf));
3991
3992 /*DPCD 2006h ERROR STATUS*/
3993 psr_error_status.raw = dpcdbuf[0];
3994 /*DPCD 2008h SINK PANEL SELF REFRESH STATUS*/
3995 psr_sink_psr_status.raw = dpcdbuf[2];
3996
3997 if (psr_error_status.bits.LINK_CRC_ERROR ||
3998 psr_error_status.bits.RFB_STORAGE_ERROR ||
3999 psr_error_status.bits.VSC_SDP_ERROR) {
4000 bool_Bool allow_active;
4001
4002 /* Acknowledge and clear error bits */
4003 dm_helpers_dp_write_dpcd(
4004 link->ctx,
4005 link,
4006 8198,/*DpcdAddress_PSR_Error_Status*/
4007 &psr_error_status.raw,
4008 sizeof(psr_error_status.raw));
4009
4010 /* PSR error, disable and re-enable PSR */
4011 if (link->psr_settings.psr_allow_active) {
4012 allow_active = false0;
4013 dc_link_set_psr_allow_active(link, &allow_active, true1, false0, NULL((void *)0));
4014 allow_active = true1;
4015 dc_link_set_psr_allow_active(link, &allow_active, true1, false0, NULL((void *)0));
4016 }
4017
4018 return true1;
4019 } else if (psr_sink_psr_status.bits.SINK_SELF_REFRESH_STATUS ==
4020 PSR_SINK_STATE_ACTIVE_DISPLAY_FROM_SINK_RFB){
4021 /* No error is detect, PSR is active.
4022 * We should return with IRQ_HPD handled without
4023 * checking for loss of sync since PSR would have
4024 * powered down main link.
4025 */
4026 return true1;
4027 }
4028 }
4029 return false0;
4030}
4031
4032static enum dc_link_rate get_link_rate_from_test_link_rate(uint8_t test_rate)
4033{
4034 switch (test_rate) {
4035 case DP_TEST_LINK_RATE_RBR:
4036 return LINK_RATE_LOW;
4037 case DP_TEST_LINK_RATE_HBR:
4038 return LINK_RATE_HIGH;
4039 case DP_TEST_LINK_RATE_HBR2:
4040 return LINK_RATE_HIGH2;
4041 case DP_TEST_LINK_RATE_HBR3:
4042 return LINK_RATE_HIGH3;
4043 case DP_TEST_LINK_RATE_UHBR10:
4044 return LINK_RATE_UHBR10;
4045 case DP_TEST_LINK_RATE_UHBR20:
4046 return LINK_RATE_UHBR20;
4047 case DP_TEST_LINK_RATE_UHBR13_5:
4048 return LINK_RATE_UHBR13_5;
4049 default:
4050 return LINK_RATE_UNKNOWN;
4051 }
4052}
4053
4054static void dp_test_send_link_training(struct dc_link *link)
4055{
4056 struct dc_link_settings link_settings = {0};
4057 uint8_t test_rate = 0;
4058
4059 core_link_read_dpcd(
4060 link,
4061 DP_TEST_LANE_COUNT0x220,
4062 (unsigned char *)(&link_settings.lane_count),
4063 1);
4064 core_link_read_dpcd(
4065 link,
4066 DP_TEST_LINK_RATE0x219,
4067 &test_rate,
4068 1);
4069 link_settings.link_rate = get_link_rate_from_test_link_rate(test_rate);
4070
4071 /* Set preferred link settings */
4072 link->verified_link_cap.lane_count = link_settings.lane_count;
4073 link->verified_link_cap.link_rate = link_settings.link_rate;
4074
4075 dp_retrain_link_dp_test(link, &link_settings, false0);
4076}
4077
4078/* TODO Raven hbr2 compliance eye output is unstable
4079 * (toggling on and off) with debugger break
4080 * This caueses intermittent PHY automation failure
4081 * Need to look into the root cause */
4082static void dp_test_send_phy_test_pattern(struct dc_link *link)
4083{
4084 union phy_test_pattern dpcd_test_pattern;
4085 union lane_adjust dpcd_lane_adjustment[2];
4086 unsigned char dpcd_post_cursor_2_adjustment = 0;
4087 unsigned char test_pattern_buffer[
4088 (DP_TEST_264BIT_CUSTOM_PATTERN_263_2560x2250 -
4089 DP_TEST_264BIT_CUSTOM_PATTERN_7_00x2230)+1] = {0};
4090 unsigned int test_pattern_size = 0;
4091 enum dp_test_pattern test_pattern;
4092 union lane_adjust dpcd_lane_adjust;
4093 unsigned int lane;
4094 struct link_training_settings link_training_settings;
4095
4096 dpcd_test_pattern.raw = 0;
4097 memset(dpcd_lane_adjustment, 0, sizeof(dpcd_lane_adjustment))__builtin_memset((dpcd_lane_adjustment), (0), (sizeof(dpcd_lane_adjustment
)))
;
4098 memset(&link_training_settings, 0, sizeof(link_training_settings))__builtin_memset((&link_training_settings), (0), (sizeof(
link_training_settings)))
;
4099
4100 /* get phy test pattern and pattern parameters from DP receiver */
4101 core_link_read_dpcd(
4102 link,
4103 DP_PHY_TEST_PATTERN0x248,
4104 &dpcd_test_pattern.raw,
4105 sizeof(dpcd_test_pattern));
4106 core_link_read_dpcd(
4107 link,
4108 DP_ADJUST_REQUEST_LANE0_10x206,
4109 &dpcd_lane_adjustment[0].raw,
4110 sizeof(dpcd_lane_adjustment));
4111
4112 /* prepare link training settings */
4113 link_training_settings.link_settings = link->cur_link_settings;
4114
4115 link_training_settings.lttpr_mode = dp_decide_lttpr_mode(link, &link->cur_link_settings);
4116
4117 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
4118 link_training_settings.lttpr_mode == LTTPR_MODE_TRANSPARENT)
4119 dp_fixed_vs_pe_read_lane_adjust(
4120 link,
4121 link_training_settings.dpcd_lane_settings);
4122
4123 /*get post cursor 2 parameters
4124 * For DP 1.1a or eariler, this DPCD register's value is 0
4125 * For DP 1.2 or later:
4126 * Bits 1:0 = POST_CURSOR2_LANE0; Bits 3:2 = POST_CURSOR2_LANE1
4127 * Bits 5:4 = POST_CURSOR2_LANE2; Bits 7:6 = POST_CURSOR2_LANE3
4128 */
4129 core_link_read_dpcd(
4130 link,
4131 DP_ADJUST_REQUEST_POST_CURSOR20x20c,
4132 &dpcd_post_cursor_2_adjustment,
4133 sizeof(dpcd_post_cursor_2_adjustment));
4134
4135 /* translate request */
4136 switch (dpcd_test_pattern.bits.PATTERN) {
4137 case PHY_TEST_PATTERN_D10_2:
4138 test_pattern = DP_TEST_PATTERN_D102;
4139 break;
4140 case PHY_TEST_PATTERN_SYMBOL_ERROR:
4141 test_pattern = DP_TEST_PATTERN_SYMBOL_ERROR;
4142 break;
4143 case PHY_TEST_PATTERN_PRBS7:
4144 test_pattern = DP_TEST_PATTERN_PRBS7;
4145 break;
4146 case PHY_TEST_PATTERN_80BIT_CUSTOM:
4147 test_pattern = DP_TEST_PATTERN_80BIT_CUSTOM;
4148 break;
4149 case PHY_TEST_PATTERN_CP2520_1:
4150 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
4151 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
4152 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4153 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
4154 break;
4155 case PHY_TEST_PATTERN_CP2520_2:
4156 /* CP2520 pattern is unstable, temporarily use TPS4 instead */
4157 test_pattern = (link->dc->caps.force_dp_tps4_for_cp2520 == 1) ?
4158 DP_TEST_PATTERN_TRAINING_PATTERN4 :
4159 DP_TEST_PATTERN_HBR2_COMPLIANCE_EYE;
4160 break;
4161 case PHY_TEST_PATTERN_CP2520_3:
4162 test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
4163 break;
4164 case PHY_TEST_PATTERN_128b_132b_TPS1:
4165 test_pattern = DP_TEST_PATTERN_128b_132b_TPS1;
4166 break;
4167 case PHY_TEST_PATTERN_128b_132b_TPS2:
4168 test_pattern = DP_TEST_PATTERN_128b_132b_TPS2;
4169 break;
4170 case PHY_TEST_PATTERN_PRBS9:
4171 test_pattern = DP_TEST_PATTERN_PRBS9;
4172 break;
4173 case PHY_TEST_PATTERN_PRBS11:
4174 test_pattern = DP_TEST_PATTERN_PRBS11;
4175 break;
4176 case PHY_TEST_PATTERN_PRBS15:
4177 test_pattern = DP_TEST_PATTERN_PRBS15;
4178 break;
4179 case PHY_TEST_PATTERN_PRBS23:
4180 test_pattern = DP_TEST_PATTERN_PRBS23;
4181 break;
4182 case PHY_TEST_PATTERN_PRBS31:
4183 test_pattern = DP_TEST_PATTERN_PRBS31;
4184 break;
4185 case PHY_TEST_PATTERN_264BIT_CUSTOM:
4186 test_pattern = DP_TEST_PATTERN_264BIT_CUSTOM;
4187 break;
4188 case PHY_TEST_PATTERN_SQUARE_PULSE:
4189 test_pattern = DP_TEST_PATTERN_SQUARE_PULSE;
4190 break;
4191 default:
4192 test_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4193 break;
4194 }
4195
4196 if (test_pattern == DP_TEST_PATTERN_80BIT_CUSTOM) {
4197 test_pattern_size = (DP_TEST_80BIT_CUSTOM_PATTERN_79_720x259 -
4198 DP_TEST_80BIT_CUSTOM_PATTERN_7_00x250) + 1;
4199 core_link_read_dpcd(
4200 link,
4201 DP_TEST_80BIT_CUSTOM_PATTERN_7_00x250,
4202 test_pattern_buffer,
4203 test_pattern_size);
4204 }
4205
4206 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE) {
4207 test_pattern_size = 1; // Square pattern data is 1 byte (DP spec)
4208 core_link_read_dpcd(
4209 link,
4210 DP_PHY_SQUARE_PATTERN0x249,
4211 test_pattern_buffer,
4212 test_pattern_size);
4213 }
4214
4215 if (test_pattern == DP_TEST_PATTERN_264BIT_CUSTOM) {
4216 test_pattern_size = (DP_TEST_264BIT_CUSTOM_PATTERN_263_2560x2250-
4217 DP_TEST_264BIT_CUSTOM_PATTERN_7_00x2230) + 1;
4218 core_link_read_dpcd(
4219 link,
4220 DP_TEST_264BIT_CUSTOM_PATTERN_7_00x2230,
4221 test_pattern_buffer,
4222 test_pattern_size);
4223 }
4224
4225 for (lane = 0; lane <
4226 (unsigned int)(link->cur_link_settings.lane_count);
4227 lane++) {
4228 dpcd_lane_adjust.raw =
4229 get_nibble_at_index(&dpcd_lane_adjustment[0].raw, lane);
4230 if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4231 DP_8b_10b_ENCODING) {
4232 link_training_settings.hw_lane_settings[lane].VOLTAGE_SWING =
4233 (enum dc_voltage_swing)
4234 (dpcd_lane_adjust.bits.VOLTAGE_SWING_LANE);
4235 link_training_settings.hw_lane_settings[lane].PRE_EMPHASIS =
4236 (enum dc_pre_emphasis)
4237 (dpcd_lane_adjust.bits.PRE_EMPHASIS_LANE);
4238 link_training_settings.hw_lane_settings[lane].POST_CURSOR2 =
4239 (enum dc_post_cursor2)
4240 ((dpcd_post_cursor_2_adjustment >> (lane * 2)) & 0x03);
4241 } else if (dp_get_link_encoding_format(&link->cur_link_settings) ==
4242 DP_128b_132b_ENCODING) {
4243 link_training_settings.hw_lane_settings[lane].FFE_PRESET.raw =
4244 dpcd_lane_adjust.tx_ffe.PRESET_VALUE;
4245 }
4246 }
4247
4248 dp_hw_to_dpcd_lane_settings(&link_training_settings,
4249 link_training_settings.hw_lane_settings,
4250 link_training_settings.dpcd_lane_settings);
4251 /*Usage: Measure DP physical lane signal
4252 * by DP SI test equipment automatically.
4253 * PHY test pattern request is generated by equipment via HPD interrupt.
4254 * HPD needs to be active all the time. HPD should be active
4255 * all the time. Do not touch it.
4256 * forward request to DS
4257 */
4258 dc_link_dp_set_test_pattern(
4259 link,
4260 test_pattern,
4261 DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED,
4262 &link_training_settings,
4263 test_pattern_buffer,
4264 test_pattern_size);
4265}
4266
4267static void dp_test_get_audio_test_data(struct dc_link *link, bool_Bool disable_video)
4268{
4269 union audio_test_mode dpcd_test_mode = {0};
4270 struct audio_test_pattern_type dpcd_pattern_type = {0};
4271 union audio_test_pattern_period dpcd_pattern_period[AUDIO_CHANNELS_COUNT] = {0};
4272 enum dp_test_pattern test_pattern = DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4273
4274 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
4275 struct pipe_ctx *pipe_ctx = &pipes[0];
4276 unsigned int channel_count;
4277 unsigned int channel = 0;
4278 unsigned int modes = 0;
4279 unsigned int sampling_rate_in_hz = 0;
4280
4281 // get audio test mode and test pattern parameters
4282 core_link_read_dpcd(
4283 link,
4284 DP_TEST_AUDIO_MODE0x271,
4285 &dpcd_test_mode.raw,
4286 sizeof(dpcd_test_mode));
4287
4288 core_link_read_dpcd(
4289 link,
4290 DP_TEST_AUDIO_PATTERN_TYPE0x272,
4291 &dpcd_pattern_type.value,
4292 sizeof(dpcd_pattern_type));
4293
4294 channel_count = min(dpcd_test_mode.bits.channel_count + 1, AUDIO_CHANNELS_COUNT)(((dpcd_test_mode.bits.channel_count + 1)<(AUDIO_CHANNELS_COUNT
))?(dpcd_test_mode.bits.channel_count + 1):(AUDIO_CHANNELS_COUNT
))
;
4295
4296 // read pattern periods for requested channels when sawTooth pattern is requested
4297 if (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH ||
4298 dpcd_pattern_type.value == AUDIO_TEST_PATTERN_OPERATOR_DEFINED) {
4299
4300 test_pattern = (dpcd_pattern_type.value == AUDIO_TEST_PATTERN_SAWTOOTH) ?
4301 DP_TEST_PATTERN_AUDIO_SAWTOOTH : DP_TEST_PATTERN_AUDIO_OPERATOR_DEFINED;
4302 // read period for each channel
4303 for (channel = 0; channel < channel_count; channel++) {
4304 core_link_read_dpcd(
4305 link,
4306 DP_TEST_AUDIO_PERIOD_CH10x273 + channel,
4307 &dpcd_pattern_period[channel].raw,
4308 sizeof(dpcd_pattern_period[channel]));
4309 }
4310 }
4311
4312 // translate sampling rate
4313 switch (dpcd_test_mode.bits.sampling_rate) {
4314 case AUDIO_SAMPLING_RATE_32KHZ:
4315 sampling_rate_in_hz = 32000;
4316 break;
4317 case AUDIO_SAMPLING_RATE_44_1KHZ:
4318 sampling_rate_in_hz = 44100;
4319 break;
4320 case AUDIO_SAMPLING_RATE_48KHZ:
4321 sampling_rate_in_hz = 48000;
4322 break;
4323 case AUDIO_SAMPLING_RATE_88_2KHZ:
4324 sampling_rate_in_hz = 88200;
4325 break;
4326 case AUDIO_SAMPLING_RATE_96KHZ:
4327 sampling_rate_in_hz = 96000;
4328 break;
4329 case AUDIO_SAMPLING_RATE_176_4KHZ:
4330 sampling_rate_in_hz = 176400;
4331 break;
4332 case AUDIO_SAMPLING_RATE_192KHZ:
4333 sampling_rate_in_hz = 192000;
4334 break;
4335 default:
4336 sampling_rate_in_hz = 0;
4337 break;
4338 }
4339
4340 link->audio_test_data.flags.test_requested = 1;
4341 link->audio_test_data.flags.disable_video = disable_video;
4342 link->audio_test_data.sampling_rate = sampling_rate_in_hz;
4343 link->audio_test_data.channel_count = channel_count;
4344 link->audio_test_data.pattern_type = test_pattern;
4345
4346 if (test_pattern == DP_TEST_PATTERN_AUDIO_SAWTOOTH) {
4347 for (modes = 0; modes < pipe_ctx->stream->audio_info.mode_count; modes++) {
4348 link->audio_test_data.pattern_period[modes] = dpcd_pattern_period[modes].bits.pattern_period;
4349 }
4350 }
4351}
4352
4353void dc_link_dp_handle_automated_test(struct dc_link *link)
4354{
4355 union test_request test_request;
4356 union test_response test_response;
4357
4358 memset(&test_request, 0, sizeof(test_request))__builtin_memset((&test_request), (0), (sizeof(test_request
)))
;
4359 memset(&test_response, 0, sizeof(test_response))__builtin_memset((&test_response), (0), (sizeof(test_response
)))
;
4360
4361 core_link_read_dpcd(
4362 link,
4363 DP_TEST_REQUEST0x218,
4364 &test_request.raw,
4365 sizeof(union test_request));
4366 if (test_request.bits.LINK_TRAINING) {
4367 /* ACK first to let DP RX test box monitor LT sequence */
4368 test_response.bits.ACK = 1;
4369 core_link_write_dpcd(
4370 link,
4371 DP_TEST_RESPONSE0x260,
4372 &test_response.raw,
4373 sizeof(test_response));
4374 dp_test_send_link_training(link);
4375 /* no acknowledge request is needed again */
4376 test_response.bits.ACK = 0;
4377 }
4378 if (test_request.bits.LINK_TEST_PATTRN) {
4379 union test_misc dpcd_test_params;
4380 union link_test_pattern dpcd_test_pattern;
4381
4382 memset(&dpcd_test_pattern, 0, sizeof(dpcd_test_pattern))__builtin_memset((&dpcd_test_pattern), (0), (sizeof(dpcd_test_pattern
)))
;
4383 memset(&dpcd_test_params, 0, sizeof(dpcd_test_params))__builtin_memset((&dpcd_test_params), (0), (sizeof(dpcd_test_params
)))
;
4384
4385 /* get link test pattern and pattern parameters */
4386 core_link_read_dpcd(
4387 link,
4388 DP_TEST_PATTERN0x221,
4389 &dpcd_test_pattern.raw,
4390 sizeof(dpcd_test_pattern));
4391 core_link_read_dpcd(
4392 link,
4393 DP_TEST_MISC00x232,
4394 &dpcd_test_params.raw,
4395 sizeof(dpcd_test_params));
4396 test_response.bits.ACK = dm_helpers_dp_handle_test_pattern_request(link->ctx, link,
4397 dpcd_test_pattern, dpcd_test_params) ? 1 : 0;
4398 }
4399
4400 if (test_request.bits.AUDIO_TEST_PATTERN) {
4401 dp_test_get_audio_test_data(link, test_request.bits.TEST_AUDIO_DISABLED_VIDEO);
4402 test_response.bits.ACK = 1;
4403 }
4404
4405 if (test_request.bits.PHY_TEST_PATTERN) {
4406 dp_test_send_phy_test_pattern(link);
4407 test_response.bits.ACK = 1;
4408 }
4409
4410 /* send request acknowledgment */
4411 if (test_response.bits.ACK)
4412 core_link_write_dpcd(
4413 link,
4414 DP_TEST_RESPONSE0x260,
4415 &test_response.raw,
4416 sizeof(test_response));
4417}
4418
4419void dc_link_dp_handle_link_loss(struct dc_link *link)
4420{
4421 int i;
4422 struct pipe_ctx *pipe_ctx;
4423
4424 for (i = 0; i < MAX_PIPES6; i++) {
4425 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4426 if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->link == link)
4427 break;
4428 }
4429
4430 if (pipe_ctx == NULL((void *)0) || pipe_ctx->stream == NULL((void *)0))
4431 return;
4432
4433 for (i = 0; i < MAX_PIPES6; i++) {
4434 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4435 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4436 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
4437 core_link_disable_stream(pipe_ctx);
4438 }
4439
4440 for (i = 0; i < MAX_PIPES6; i++) {
4441 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
4442 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
4443 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
4444 core_link_enable_stream(link->dc->current_state, pipe_ctx);
4445 }
4446}
4447
4448bool_Bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd_irq_dpcd_data, bool_Bool *out_link_loss,
4449 bool_Bool defer_handling, bool_Bool *has_left_work)
4450{
4451 union hpd_irq_data hpd_irq_dpcd_data = {0};
4452 union device_service_irq device_service_clear = {0};
4453 enum dc_status result;
4454 bool_Bool status = false0;
4455
4456 if (out_link_loss)
4457 *out_link_loss = false0;
4458
4459 if (has_left_work)
4460 *has_left_work = false0;
4461 /* For use cases related to down stream connection status change,
4462 * PSR and device auto test, refer to function handle_sst_hpd_irq
4463 * in DAL2.1*/
4464
4465 DC_LOG_HW_HPD_IRQ("%s: Got short pulse HPD on link %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "%s: Got short pulse HPD on link %d\n"
, __func__, link->link_index)
4466 __func__, link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: Got short pulse HPD on link %d\n"
, __func__, link->link_index)
;
4467
4468
4469 /* All the "handle_hpd_irq_xxx()" methods
4470 * should be called only after
4471 * dal_dpsst_ls_read_hpd_irq_data
4472 * Order of calls is important too
4473 */
4474 result = read_hpd_rx_irq_data(link, &hpd_irq_dpcd_data);
4475 if (out_hpd_irq_dpcd_data)
4476 *out_hpd_irq_dpcd_data = hpd_irq_dpcd_data;
4477
4478 if (result != DC_OK) {
4479 DC_LOG_HW_HPD_IRQ("%s: DPCD read failed to obtain irq data\n",___drm_dbg(((void *)0), DRM_UT_KMS, "%s: DPCD read failed to obtain irq data\n"
, __func__)
4480 __func__)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: DPCD read failed to obtain irq data\n"
, __func__)
;
4481 return false0;
4482 }
4483
4484 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
4485 device_service_clear.bits.AUTOMATED_TEST = 1;
4486 core_link_write_dpcd(
4487 link,
4488 DP_DEVICE_SERVICE_IRQ_VECTOR0x201,
4489 &device_service_clear.raw,
4490 sizeof(device_service_clear.raw));
4491 device_service_clear.raw = 0;
4492 if (defer_handling && has_left_work)
4493 *has_left_work = true1;
4494 else
4495 dc_link_dp_handle_automated_test(link);
4496 return false0;
4497 }
4498
4499 if (!dc_link_dp_allow_hpd_rx_irq(link)) {
4500 DC_LOG_HW_HPD_IRQ("%s: skipping HPD handling on %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "%s: skipping HPD handling on %d\n"
, __func__, link->link_index)
4501 __func__, link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: skipping HPD handling on %d\n"
, __func__, link->link_index)
;
4502 return false0;
4503 }
4504
4505 if (handle_hpd_irq_psr_sink(link))
4506 /* PSR-related error was detected and handled */
4507 return true1;
4508
4509 /* If PSR-related error handled, Main link may be off,
4510 * so do not handle as a normal sink status change interrupt.
4511 */
4512
4513 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY) {
4514 if (defer_handling && has_left_work)
4515 *has_left_work = true1;
4516 return true1;
4517 }
4518
4519 /* check if we have MST msg and return since we poll for it */
4520 if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
4521 if (defer_handling && has_left_work)
4522 *has_left_work = true1;
4523 return false0;
4524 }
4525
4526 /* For now we only handle 'Downstream port status' case.
4527 * If we got sink count changed it means
4528 * Downstream port status changed,
4529 * then DM should call DC to do the detection.
4530 * NOTE: Do not handle link loss on eDP since it is internal link*/
4531 if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
4532 hpd_rx_irq_check_link_loss_status(
4533 link,
4534 &hpd_irq_dpcd_data)) {
4535 /* Connectivity log: link loss */
4536 CONN_DATA_LINK_LOSS(link,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "Status: "
); } while (0)
4537 hpd_irq_dpcd_data.raw,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "Status: "
); } while (0)
4538 sizeof(hpd_irq_dpcd_data),do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "Status: "
); } while (0)
4539 "Status: ")do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "Status: "
); } while (0)
;
4540
4541 if (defer_handling && has_left_work)
4542 *has_left_work = true1;
4543 else
4544 dc_link_dp_handle_link_loss(link);
4545
4546 status = false0;
4547 if (out_link_loss)
4548 *out_link_loss = true1;
4549
4550 dp_trace_link_loss_increment(link);
4551 }
4552
4553 if (link->type == dc_connection_sst_branch &&
4554 hpd_irq_dpcd_data.bytes.sink_cnt.bits.SINK_COUNT
4555 != link->dpcd_sink_count)
4556 status = true1;
4557
4558 /* reasons for HPD RX:
4559 * 1. Link Loss - ie Re-train the Link
4560 * 2. MST sideband message
4561 * 3. Automated Test - ie. Internal Commit
4562 * 4. CP (copy protection) - (not interesting for DM???)
4563 * 5. DRR
4564 * 6. Downstream Port status changed
4565 * -ie. Detect - this the only one
4566 * which is interesting for DM because
4567 * it must call dc_link_detect.
4568 */
4569 return status;
4570}
4571
4572/*query dpcd for version and mst cap addresses*/
4573bool_Bool is_mst_supported(struct dc_link *link)
4574{
4575 bool_Bool mst = false0;
4576 enum dc_status st = DC_OK;
4577 union dpcd_rev rev;
4578 union mstm_cap cap;
4579
4580 if (link->preferred_training_settings.mst_enable &&
4581 *link->preferred_training_settings.mst_enable == false0) {
4582 return false0;
4583 }
4584
4585 rev.raw = 0;
4586 cap.raw = 0;
4587
4588 st = core_link_read_dpcd(link, DP_DPCD_REV0x000, &rev.raw,
4589 sizeof(rev));
4590
4591 if (st == DC_OK && rev.raw >= DPCD_REV_12) {
4592
4593 st = core_link_read_dpcd(link, DP_MSTM_CAP0x021,
4594 &cap.raw, sizeof(cap));
4595 if (st == DC_OK && cap.bits.MST_CAP == 1)
4596 mst = true1;
4597 }
4598 return mst;
4599
4600}
4601
4602bool_Bool is_dp_active_dongle(const struct dc_link *link)
4603{
4604 return (link->dpcd_caps.dongle_type >= DISPLAY_DONGLE_DP_VGA_CONVERTER) &&
4605 (link->dpcd_caps.dongle_type <= DISPLAY_DONGLE_DP_HDMI_CONVERTER);
4606}
4607
4608bool_Bool is_dp_branch_device(const struct dc_link *link)
4609{
4610 return link->dpcd_caps.is_branch_dev;
4611}
4612
4613static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc)
4614{
4615 switch (bpc) {
4616 case DOWN_STREAM_MAX_8BPC:
4617 return 8;
4618 case DOWN_STREAM_MAX_10BPC:
4619 return 10;
4620 case DOWN_STREAM_MAX_12BPC:
4621 return 12;
4622 case DOWN_STREAM_MAX_16BPC:
4623 return 16;
4624 default:
4625 break;
4626 }
4627
4628 return -1;
4629}
4630
4631#if defined(CONFIG_DRM_AMD_DC_DCN1)
4632uint32_t dc_link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw)
4633{
4634 switch (bw) {
4635 case 0b001:
4636 return 9000000;
4637 case 0b010:
4638 return 18000000;
4639 case 0b011:
4640 return 24000000;
4641 case 0b100:
4642 return 32000000;
4643 case 0b101:
4644 return 40000000;
4645 case 0b110:
4646 return 48000000;
4647 }
4648
4649 return 0;
4650}
4651
4652/*
4653 * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw.
4654 */
4655static uint32_t intersect_frl_link_bw_support(
4656 const uint32_t max_supported_frl_bw_in_kbps,
4657 const union hdmi_encoded_link_bw hdmi_encoded_link_bw)
4658{
4659 uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps;
4660
4661 // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode)
4662 if (hdmi_encoded_link_bw.bits.FRL_MODE) {
4663 if (hdmi_encoded_link_bw.bits.BW_48Gbps)
4664 supported_bw_in_kbps = 48000000;
4665 else if (hdmi_encoded_link_bw.bits.BW_40Gbps)
4666 supported_bw_in_kbps = 40000000;
4667 else if (hdmi_encoded_link_bw.bits.BW_32Gbps)
4668 supported_bw_in_kbps = 32000000;
4669 else if (hdmi_encoded_link_bw.bits.BW_24Gbps)
4670 supported_bw_in_kbps = 24000000;
4671 else if (hdmi_encoded_link_bw.bits.BW_18Gbps)
4672 supported_bw_in_kbps = 18000000;
4673 else if (hdmi_encoded_link_bw.bits.BW_9Gbps)
4674 supported_bw_in_kbps = 9000000;
4675 }
4676
4677 return supported_bw_in_kbps;
4678}
4679#endif
4680
4681static void read_dp_device_vendor_id(struct dc_link *link)
4682{
4683 struct dp_device_vendor_id dp_id;
4684
4685 /* read IEEE branch device id */
4686 core_link_read_dpcd(
4687 link,
4688 DP_BRANCH_OUI0x500,
4689 (uint8_t *)&dp_id,
4690 sizeof(dp_id));
4691
4692 link->dpcd_caps.branch_dev_id =
4693 (dp_id.ieee_oui[0] << 16) +
4694 (dp_id.ieee_oui[1] << 8) +
4695 dp_id.ieee_oui[2];
4696
4697 memmove(__builtin_memmove((link->dpcd_caps.branch_dev_name), (dp_id
.ieee_device_id), (sizeof(dp_id.ieee_device_id)))
4698 link->dpcd_caps.branch_dev_name,__builtin_memmove((link->dpcd_caps.branch_dev_name), (dp_id
.ieee_device_id), (sizeof(dp_id.ieee_device_id)))
4699 dp_id.ieee_device_id,__builtin_memmove((link->dpcd_caps.branch_dev_name), (dp_id
.ieee_device_id), (sizeof(dp_id.ieee_device_id)))
4700 sizeof(dp_id.ieee_device_id))__builtin_memmove((link->dpcd_caps.branch_dev_name), (dp_id
.ieee_device_id), (sizeof(dp_id.ieee_device_id)))
;
4701}
4702
4703
4704
4705static void get_active_converter_info(
4706 uint8_t data, struct dc_link *link)
4707{
4708 union dp_downstream_port_present ds_port = { .byte = data };
4709 memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps))__builtin_memset((&link->dpcd_caps.dongle_caps), (0), (
sizeof(link->dpcd_caps.dongle_caps)))
;
4710
4711 /* decode converter info*/
4712 if (!ds_port.fields.PORT_PRESENT) {
4713 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4714 ddc_service_set_dongle_type(link->ddc,
4715 link->dpcd_caps.dongle_type);
4716 link->dpcd_caps.is_branch_dev = false0;
4717 return;
4718 }
4719
4720 /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */
4721 link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT;
4722
4723 switch (ds_port.fields.PORT_TYPE) {
4724 case DOWNSTREAM_VGA:
4725 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER;
4726 break;
4727 case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS:
4728 /* At this point we don't know is it DVI or HDMI or DP++,
4729 * assume DVI.*/
4730 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER;
4731 break;
4732 default:
4733 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4734 break;
4735 }
4736
4737 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) {
4738 uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/
4739 union dwnstream_port_caps_byte0 *port_caps =
4740 (union dwnstream_port_caps_byte0 *)det_caps;
4741 if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_00x80,
4742 det_caps, sizeof(det_caps)) == DC_OK) {
4743
4744 switch (port_caps->bits.DWN_STRM_PORTX_TYPE) {
4745 /*Handle DP case as DONGLE_NONE*/
4746 case DOWN_STREAM_DETAILED_DP:
4747 link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE;
4748 break;
4749 case DOWN_STREAM_DETAILED_VGA:
4750 link->dpcd_caps.dongle_type =
4751 DISPLAY_DONGLE_DP_VGA_CONVERTER;
4752 break;
4753 case DOWN_STREAM_DETAILED_DVI:
4754 link->dpcd_caps.dongle_type =
4755 DISPLAY_DONGLE_DP_DVI_CONVERTER;
4756 break;
4757 case DOWN_STREAM_DETAILED_HDMI:
4758 case DOWN_STREAM_DETAILED_DP_PLUS_PLUS:
4759 /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/
4760 link->dpcd_caps.dongle_type =
4761 DISPLAY_DONGLE_DP_HDMI_CONVERTER;
4762
4763 link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type;
4764 if (ds_port.fields.DETAILED_CAPS) {
4765
4766 union dwnstream_port_caps_byte3_hdmi
4767 hdmi_caps = {.raw = det_caps[3] };
4768 union dwnstream_port_caps_byte2
4769 hdmi_color_caps = {.raw = det_caps[2] };
4770 link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz =
4771 det_caps[1] * 2500;
4772
4773 link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter =
4774 hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK;
4775 /*YCBCR capability only for HDMI case*/
4776 if (port_caps->bits.DWN_STRM_PORTX_TYPE
4777 == DOWN_STREAM_DETAILED_HDMI) {
4778 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through =
4779 hdmi_caps.bits.YCrCr422_PASS_THROUGH;
4780 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through =
4781 hdmi_caps.bits.YCrCr420_PASS_THROUGH;
4782 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter =
4783 hdmi_caps.bits.YCrCr422_CONVERSION;
4784 link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter =
4785 hdmi_caps.bits.YCrCr420_CONVERSION;
4786 }
4787
4788 link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc =
4789 translate_dpcd_max_bpc(
4790 hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT);
4791
4792#if defined(CONFIG_DRM_AMD_DC_DCN1)
4793 if (link->dc->caps.dp_hdmi21_pcon_support) {
4794 union hdmi_encoded_link_bw hdmi_encoded_link_bw;
4795
4796 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps =
4797 dc_link_bw_kbps_from_raw_frl_link_rate_data(
4798 hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT);
4799
4800 // Intersect reported max link bw support with the supported link rate post FRL link training
4801 if (core_link_read_dpcd(link, DP_PCON_HDMI_POST_FRL_STATUS0x3036,
4802 &hdmi_encoded_link_bw.raw, sizeof(hdmi_encoded_link_bw)) == DC_OK) {
4803 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = intersect_frl_link_bw_support(
4804 link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps,
4805 hdmi_encoded_link_bw);
4806 }
4807
4808 if (link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0)
4809 link->dpcd_caps.dongle_caps.extendedCapValid = true1;
4810 }
4811#endif
4812
4813 if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0)
4814 link->dpcd_caps.dongle_caps.extendedCapValid = true1;
4815 }
4816
4817 break;
4818 }
4819 }
4820 }
4821
4822 ddc_service_set_dongle_type(link->ddc, link->dpcd_caps.dongle_type);
4823
4824 {
4825 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
4826
4827 core_link_read_dpcd(
4828 link,
4829 DP_BRANCH_REVISION_START0x509,
4830 (uint8_t *)&dp_hw_fw_revision,
4831 sizeof(dp_hw_fw_revision));
4832
4833 link->dpcd_caps.branch_hw_revision =
4834 dp_hw_fw_revision.ieee_hw_rev;
4835
4836 memmove(__builtin_memmove((link->dpcd_caps.branch_fw_revision), (dp_hw_fw_revision
.ieee_fw_rev), (sizeof(dp_hw_fw_revision.ieee_fw_rev)))
4837 link->dpcd_caps.branch_fw_revision,__builtin_memmove((link->dpcd_caps.branch_fw_revision), (dp_hw_fw_revision
.ieee_fw_rev), (sizeof(dp_hw_fw_revision.ieee_fw_rev)))
4838 dp_hw_fw_revision.ieee_fw_rev,__builtin_memmove((link->dpcd_caps.branch_fw_revision), (dp_hw_fw_revision
.ieee_fw_rev), (sizeof(dp_hw_fw_revision.ieee_fw_rev)))
4839 sizeof(dp_hw_fw_revision.ieee_fw_rev))__builtin_memmove((link->dpcd_caps.branch_fw_revision), (dp_hw_fw_revision
.ieee_fw_rev), (sizeof(dp_hw_fw_revision.ieee_fw_rev)))
;
4840 }
4841 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 &&
4842 link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
4843 union dp_dfp_cap_ext dfp_cap_ext;
4844 memset(&dfp_cap_ext, '\0', sizeof (dfp_cap_ext))__builtin_memset((&dfp_cap_ext), ('\0'), (sizeof (dfp_cap_ext
)))
;
4845 core_link_read_dpcd(
4846 link,
4847 DP_DFP_CAPABILITY_EXTENSION_SUPPORT0x0a3,
4848 dfp_cap_ext.raw,
4849 sizeof(dfp_cap_ext.raw));
4850 link->dpcd_caps.dongle_caps.dfp_cap_ext.supported = dfp_cap_ext.fields.supported;
4851 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps =
4852 dfp_cap_ext.fields.max_pixel_rate_in_mps[0] +
4853 (dfp_cap_ext.fields.max_pixel_rate_in_mps[1] << 8);
4854 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width =
4855 dfp_cap_ext.fields.max_video_h_active_width[0] +
4856 (dfp_cap_ext.fields.max_video_h_active_width[1] << 8);
4857 link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height =
4858 dfp_cap_ext.fields.max_video_v_active_height[0] +
4859 (dfp_cap_ext.fields.max_video_v_active_height[1] << 8);
4860 link->dpcd_caps.dongle_caps.dfp_cap_ext.encoding_format_caps =
4861 dfp_cap_ext.fields.encoding_format_caps;
4862 link->dpcd_caps.dongle_caps.dfp_cap_ext.rgb_color_depth_caps =
4863 dfp_cap_ext.fields.rgb_color_depth_caps;
4864 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr444_color_depth_caps =
4865 dfp_cap_ext.fields.ycbcr444_color_depth_caps;
4866 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr422_color_depth_caps =
4867 dfp_cap_ext.fields.ycbcr422_color_depth_caps;
4868 link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr420_color_depth_caps =
4869 dfp_cap_ext.fields.ycbcr420_color_depth_caps;
4870 DC_LOG_DP2("DFP capability extension is read at link %d", link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "DFP capability extension is read at link %d"
, link->link_index)
;
4871 DC_LOG_DP2("\tdfp_cap_ext.supported = %s", link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true" : "false")___drm_dbg(((void *)0), DRM_UT_KMS, "\tdfp_cap_ext.supported = %s"
, link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true"
: "false")
;
4872 DC_LOG_DP2("\tdfp_cap_ext.max_pixel_rate_in_mps = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps)___drm_dbg(((void *)0), DRM_UT_KMS, "\tdfp_cap_ext.max_pixel_rate_in_mps = %d"
, link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps
)
;
4873 DC_LOG_DP2("\tdfp_cap_ext.max_video_h_active_width = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width)___drm_dbg(((void *)0), DRM_UT_KMS, "\tdfp_cap_ext.max_video_h_active_width = %d"
, link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width
)
;
4874 DC_LOG_DP2("\tdfp_cap_ext.max_video_v_active_height = %d", link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height)___drm_dbg(((void *)0), DRM_UT_KMS, "\tdfp_cap_ext.max_video_v_active_height = %d"
, link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height
)
;
4875 }
4876}
4877
4878static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
4879 int length)
4880{
4881 int retry = 0;
4882
4883 if (!link->dpcd_caps.dpcd_rev.raw) {
4884 do {
4885 dp_receiver_power_ctrl(link, true1);
4886 core_link_read_dpcd(link, DP_DPCD_REV0x000,
4887 dpcd_data, length);
4888 link->dpcd_caps.dpcd_rev.raw = dpcd_data[
4889 DP_DPCD_REV0x000 -
4890 DP_DPCD_REV0x000];
4891 } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw);
4892 }
4893
4894 if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) {
4895 switch (link->dpcd_caps.branch_dev_id) {
4896 /* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down
4897 * all internal circuits including AUX communication preventing
4898 * reading DPCD table and EDID (spec violation).
4899 * Encoder will skip DP RX power down on disable_output to
4900 * keep receiver powered all the time.*/
4901 case DP_BRANCH_DEVICE_ID_0010FA0x0010FA:
4902 case DP_BRANCH_DEVICE_ID_0080E10x0080e1:
4903 case DP_BRANCH_DEVICE_ID_00E04C0x00E04C:
4904 link->wa_flags.dp_keep_receiver_powered = true1;
4905 break;
4906
4907 /* TODO: May need work around for other dongles. */
4908 default:
4909 link->wa_flags.dp_keep_receiver_powered = false0;
4910 break;
4911 }
4912 } else
4913 link->wa_flags.dp_keep_receiver_powered = false0;
4914}
4915
4916/* Read additional sink caps defined in source specific DPCD area
4917 * This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP)
4918 */
4919static bool_Bool dpcd_read_sink_ext_caps(struct dc_link *link)
4920{
4921 uint8_t dpcd_data;
4922
4923 if (!link)
4924 return false0;
4925
4926 if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP0x317, &dpcd_data, 1) != DC_OK)
4927 return false0;
4928
4929 link->dpcd_sink_ext_caps.raw = dpcd_data;
4930 return true1;
4931}
4932
4933bool_Bool dp_retrieve_lttpr_cap(struct dc_link *link)
4934{
4935 uint8_t lttpr_dpcd_data[8];
4936 enum dc_status status = DC_ERROR_UNEXPECTED;
4937 bool_Bool is_lttpr_present = false0;
4938
4939 /* Logic to determine LTTPR support*/
4940 bool_Bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
4941
4942 if (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support)
4943 return false0;
4944
4945 /* By reading LTTPR capability, RX assumes that we will enable
4946 * LTTPR extended aux timeout if LTTPR is present.
4947 */
4948 status = core_link_read_dpcd(link,
4949 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000,
4950 lttpr_dpcd_data,
4951 sizeof(lttpr_dpcd_data));
4952
4953 link->dpcd_caps.lttpr_caps.revision.raw =
4954 lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000 -
4955 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000];
4956
4957 link->dpcd_caps.lttpr_caps.max_link_rate =
4958 lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER0xf0001 -
4959 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000];
4960
4961 link->dpcd_caps.lttpr_caps.phy_repeater_cnt =
4962 lttpr_dpcd_data[DP_PHY_REPEATER_CNT0xf0002 -
4963 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000];
4964
4965 link->dpcd_caps.lttpr_caps.max_lane_count =
4966 lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER0xf0004 -
4967 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000];
4968
4969 link->dpcd_caps.lttpr_caps.mode =
4970 lttpr_dpcd_data[DP_PHY_REPEATER_MODE0xf0003 -
4971 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000];
4972
4973 link->dpcd_caps.lttpr_caps.max_ext_timeout =
4974 lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT0xf0005 -
4975 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000];
4976 link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw =
4977 lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER0xf0006 -
4978 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000];
4979
4980 link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw =
4981 lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES0xf0007 -
4982 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000];
4983
4984 /* If this chip cap is set, at least one retimer must exist in the chain
4985 * Override count to 1 if we receive a known bad count (0 or an invalid value)
4986 */
4987 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN &&
4988 (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) {
4989 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 4989); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
4990 link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80;
4991 DC_LOG_DC("lttpr_caps forced phy_repeater_cnt = %d\n", link->dpcd_caps.lttpr_caps.phy_repeater_cnt)___drm_dbg(((void *)0), DRM_UT_KMS, "lttpr_caps forced phy_repeater_cnt = %d\n"
, link->dpcd_caps.lttpr_caps.phy_repeater_cnt)
;
4992 }
4993
4994 /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */
4995 is_lttpr_present = dp_is_lttpr_present(link);
4996
4997 if (is_lttpr_present)
4998 CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ")do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "LTTPR Caps: "
); } while (0)
;
4999
5000 DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present)___drm_dbg(((void *)0), DRM_UT_KMS, "is_lttpr_present = %d\n"
, is_lttpr_present)
;
5001 return is_lttpr_present;
5002}
5003
5004bool_Bool dp_is_lttpr_present(struct dc_link *link)
5005{
5006 return (dp_convert_to_count(link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 &&
5007 link->dpcd_caps.lttpr_caps.max_lane_count > 0 &&
5008 link->dpcd_caps.lttpr_caps.max_lane_count <= 4 &&
5009 link->dpcd_caps.lttpr_caps.revision.raw >= 0x14);
5010}
5011
5012enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, struct dc_link_settings *link_setting)
5013{
5014 enum dp_link_encoding encoding = dp_get_link_encoding_format(link_setting);
5015
5016 if (encoding == DP_8b_10b_ENCODING)
5017 return dp_decide_8b_10b_lttpr_mode(link);
5018 else if (encoding == DP_128b_132b_ENCODING)
5019 return dp_decide_128b_132b_lttpr_mode(link);
5020
5021 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 5021); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
5022 return LTTPR_MODE_NON_LTTPR;
5023}
5024
5025void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override)
5026{
5027 if (!dp_is_lttpr_present(link))
5028 return;
5029
5030 if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_TRANSPARENT) {
5031 *override = LTTPR_MODE_TRANSPARENT;
5032 } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_TRANSPARENT) {
5033 *override = LTTPR_MODE_NON_TRANSPARENT;
5034 } else if (link->dc->debug.lttpr_mode_override == LTTPR_MODE_NON_LTTPR) {
5035 *override = LTTPR_MODE_NON_LTTPR;
5036 }
5037 DC_LOG_DC("lttpr_mode_override chose LTTPR_MODE = %d\n", (uint8_t)(*override))___drm_dbg(((void *)0), DRM_UT_KMS, "lttpr_mode_override chose LTTPR_MODE = %d\n"
, (uint8_t)(*override))
;
5038}
5039
5040enum lttpr_mode dp_decide_8b_10b_lttpr_mode(struct dc_link *link)
5041{
5042 bool_Bool is_lttpr_present = dp_is_lttpr_present(link);
5043 bool_Bool vbios_lttpr_force_non_transparent = link->dc->caps.vbios_lttpr_enable;
5044 bool_Bool vbios_lttpr_aware = link->dc->caps.vbios_lttpr_aware;
5045
5046 if (!is_lttpr_present)
5047 return LTTPR_MODE_NON_LTTPR;
5048
5049 if (vbios_lttpr_aware) {
5050 if (vbios_lttpr_force_non_transparent) {
5051 DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT due to VBIOS DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n")___drm_dbg(((void *)0), DRM_UT_KMS, "chose LTTPR_MODE_NON_TRANSPARENT due to VBIOS DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n"
)
;
5052 return LTTPR_MODE_NON_TRANSPARENT;
5053 } else {
5054 DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT by default due to VBIOS not set DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n")___drm_dbg(((void *)0), DRM_UT_KMS, "chose LTTPR_MODE_NON_TRANSPARENT by default due to VBIOS not set DCE_INFO_CAPS_LTTPR_SUPPORT_ENABLE set to 1.\n"
)
;
5055 return LTTPR_MODE_TRANSPARENT;
5056 }
5057 }
5058
5059 if (link->dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A &&
5060 link->dc->caps.extended_aux_timeout_support) {
5061 DC_LOG_DC("chose LTTPR_MODE_NON_TRANSPARENT by default and dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A set to 1.\n")___drm_dbg(((void *)0), DRM_UT_KMS, "chose LTTPR_MODE_NON_TRANSPARENT by default and dc->config.allow_lttpr_non_transparent_mode.bits.DP1_4A set to 1.\n"
)
;
5062 return LTTPR_MODE_NON_TRANSPARENT;
5063 }
5064
5065 DC_LOG_DC("chose LTTPR_MODE_NON_LTTPR.\n")___drm_dbg(((void *)0), DRM_UT_KMS, "chose LTTPR_MODE_NON_LTTPR.\n"
)
;
5066 return LTTPR_MODE_NON_LTTPR;
5067}
5068
5069enum lttpr_mode dp_decide_128b_132b_lttpr_mode(struct dc_link *link)
5070{
5071 enum lttpr_mode mode = LTTPR_MODE_NON_LTTPR;
5072
5073 if (dp_is_lttpr_present(link))
5074 mode = LTTPR_MODE_NON_TRANSPARENT;
5075
5076 DC_LOG_DC("128b_132b chose LTTPR_MODE %d.\n", mode)___drm_dbg(((void *)0), DRM_UT_KMS, "128b_132b chose LTTPR_MODE %d.\n"
, mode)
;
5077 return mode;
5078}
5079
5080static bool_Bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id)
5081{
5082 union dmub_rb_cmd cmd;
5083
5084 if (!link->ctx->dmub_srv ||
5085 link->ep_type != DISPLAY_ENDPOINT_PHY ||
5086 link->link_enc->features.flags.bits.DP_IS_USB_C == 0)
5087 return false0;
5088
5089 memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd)));
5090 cmd.cable_id.header.type = DMUB_CMD_GET_USBC_CABLE_ID;
5091 cmd.cable_id.header.payload_bytes = sizeof(cmd.cable_id.data);
5092 cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx(
5093 link->dc, link->link_enc->transmitter);
5094 if (dc_dmub_srv_cmd_with_reply_data(link->ctx->dmub_srv, &cmd) &&
5095 cmd.cable_id.header.ret_status == 1) {
5096 cable_id->raw = cmd.cable_id.data.output_raw;
5097 DC_LOG_DC("usbc_cable_id = %d.\n", cable_id->raw)___drm_dbg(((void *)0), DRM_UT_KMS, "usbc_cable_id = %d.\n", cable_id
->raw)
;
5098 }
5099 return cmd.cable_id.header.ret_status == 1;
5100}
5101
5102static union dp_cable_id intersect_cable_id(
5103 union dp_cable_id *a, union dp_cable_id *b)
5104{
5105 union dp_cable_id out;
5106
5107 out.bits.UHBR10_20_CAPABILITY = MIN(a->bits.UHBR10_20_CAPABILITY,(((a->bits.UHBR10_20_CAPABILITY)<(b->bits.UHBR10_20_CAPABILITY
))?(a->bits.UHBR10_20_CAPABILITY):(b->bits.UHBR10_20_CAPABILITY
))
5108 b->bits.UHBR10_20_CAPABILITY)(((a->bits.UHBR10_20_CAPABILITY)<(b->bits.UHBR10_20_CAPABILITY
))?(a->bits.UHBR10_20_CAPABILITY):(b->bits.UHBR10_20_CAPABILITY
))
;
5109 out.bits.UHBR13_5_CAPABILITY = MIN(a->bits.UHBR13_5_CAPABILITY,(((a->bits.UHBR13_5_CAPABILITY)<(b->bits.UHBR13_5_CAPABILITY
))?(a->bits.UHBR13_5_CAPABILITY):(b->bits.UHBR13_5_CAPABILITY
))
5110 b->bits.UHBR13_5_CAPABILITY)(((a->bits.UHBR13_5_CAPABILITY)<(b->bits.UHBR13_5_CAPABILITY
))?(a->bits.UHBR13_5_CAPABILITY):(b->bits.UHBR13_5_CAPABILITY
))
;
5111 out.bits.CABLE_TYPE = MAX(a->bits.CABLE_TYPE, b->bits.CABLE_TYPE)(((a->bits.CABLE_TYPE)>(b->bits.CABLE_TYPE))?(a->
bits.CABLE_TYPE):(b->bits.CABLE_TYPE))
;
5112
5113 return out;
5114}
5115
5116static void retrieve_cable_id(struct dc_link *link)
5117{
5118 union dp_cable_id usbc_cable_id;
5119
5120 link->dpcd_caps.cable_id.raw = 0;
5121 core_link_read_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX0x2217,
5122 &link->dpcd_caps.cable_id.raw, sizeof(uint8_t));
5123
5124 if (get_usbc_cable_id(link, &usbc_cable_id))
5125 link->dpcd_caps.cable_id = intersect_cable_id(
5126 &link->dpcd_caps.cable_id, &usbc_cable_id);
5127}
5128
5129/* DPRX may take some time to respond to AUX messages after HPD asserted.
5130 * If AUX read unsuccessful, try to wake unresponsive DPRX by toggling DPCD SET_POWER (0x600).
5131 */
5132static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout_ms)
5133{
5134 enum dc_status status = DC_ERROR_UNEXPECTED;
5135 uint8_t dpcd_data = 0;
5136 uint64_t start_ts = 0;
5137 uint64_t current_ts = 0;
5138 uint64_t time_taken_ms = 0;
5139 enum dc_connection_type type = dc_connection_none;
5140 bool_Bool lttpr_present;
5141 bool_Bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
5142
5143 lttpr_present = dp_is_lttpr_present(link) ||
5144 (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support);
5145 DC_LOG_DC("lttpr_present = %d.\n", lttpr_present ? 1 : 0)___drm_dbg(((void *)0), DRM_UT_KMS, "lttpr_present = %d.\n", lttpr_present
? 1 : 0)
;
5146
5147 /* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to
5148 * be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read.
5149 */
5150 if (lttpr_present)
5151 status = core_link_read_dpcd(
5152 link,
5153 DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV0xf0000,
5154 &dpcd_data,
5155 sizeof(dpcd_data));
5156 else
5157 status = core_link_read_dpcd(
5158 link,
5159 DP_SET_POWER0x600,
5160 &dpcd_data,
5161 sizeof(dpcd_data));
5162
5163 if (status != DC_OK) {
5164 DC_LOG_WARNING("%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms.",printk("\0014" "[" "drm" "] " "%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms."
, __func__, timeout_ms)
5165 __func__,printk("\0014" "[" "drm" "] " "%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms."
, __func__, timeout_ms)
5166 timeout_ms)printk("\0014" "[" "drm" "] " "%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms."
, __func__, timeout_ms)
;
5167 start_ts = dm_get_timestamp(link->ctx);
5168
5169 do {
5170 if (!dc_link_detect_sink(link, &type) || type == dc_connection_none)
5171 break;
5172
5173 dpcd_data = DP_SET_POWER_D30x2;
5174 status = core_link_write_dpcd(
5175 link,
5176 DP_SET_POWER0x600,
5177 &dpcd_data,
5178 sizeof(dpcd_data));
5179
5180 dpcd_data = DP_SET_POWER_D00x1;
5181 status = core_link_write_dpcd(
5182 link,
5183 DP_SET_POWER0x600,
5184 &dpcd_data,
5185 sizeof(dpcd_data));
5186
5187 current_ts = dm_get_timestamp(link->ctx);
5188 time_taken_ms = div_u64(dm_get_elapse_time_in_ns(link->ctx, current_ts, start_ts), 1000000);
5189 } while (status != DC_OK && time_taken_ms < timeout_ms);
5190
5191 DC_LOG_WARNING("%s: DPCD SET_POWER %s after %lld ms%s",printk("\0014" "[" "drm" "] " "%s: DPCD SET_POWER %s after %lld ms%s"
, __func__, (status == DC_OK) ? "succeeded" : "failed", time_taken_ms
, (type == dc_connection_none) ? ". Unplugged." : ".")
5192 __func__,printk("\0014" "[" "drm" "] " "%s: DPCD SET_POWER %s after %lld ms%s"
, __func__, (status == DC_OK) ? "succeeded" : "failed", time_taken_ms
, (type == dc_connection_none) ? ". Unplugged." : ".")
5193 (status == DC_OK) ? "succeeded" : "failed",printk("\0014" "[" "drm" "] " "%s: DPCD SET_POWER %s after %lld ms%s"
, __func__, (status == DC_OK) ? "succeeded" : "failed", time_taken_ms
, (type == dc_connection_none) ? ". Unplugged." : ".")
5194 time_taken_ms,printk("\0014" "[" "drm" "] " "%s: DPCD SET_POWER %s after %lld ms%s"
, __func__, (status == DC_OK) ? "succeeded" : "failed", time_taken_ms
, (type == dc_connection_none) ? ". Unplugged." : ".")
5195 (type == dc_connection_none) ? ". Unplugged." : ".")printk("\0014" "[" "drm" "] " "%s: DPCD SET_POWER %s after %lld ms%s"
, __func__, (status == DC_OK) ? "succeeded" : "failed", time_taken_ms
, (type == dc_connection_none) ? ". Unplugged." : ".")
;
5196 }
5197
5198 return status;
5199}
5200
5201static bool_Bool retrieve_link_cap(struct dc_link *link)
5202{
5203 /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16,
5204 * which means size 16 will be good for both of those DPCD register block reads
5205 */
5206 uint8_t dpcd_data[16];
5207 /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
5208 */
5209 uint8_t dpcd_dprx_data = '\0';
5210 uint8_t dpcd_power_state = '\0';
5211
5212 struct dp_device_vendor_id sink_id;
5213 union down_stream_port_count down_strm_port_count;
5214 union edp_configuration_cap edp_config_cap;
5215 union dp_downstream_port_present ds_port = { 0 };
5216 enum dc_status status = DC_ERROR_UNEXPECTED;
5217 uint32_t read_dpcd_retry_cnt = 3;
5218 uint32_t aux_channel_retry_cnt = 0;
5219 int i;
5220 struct dp_sink_hw_fw_revision dp_hw_fw_revision;
5221 const uint32_t post_oui_delay = 30; // 30ms
5222 bool_Bool is_lttpr_present = false0;
5223
5224 memset(dpcd_data, '\0', sizeof(dpcd_data))__builtin_memset((dpcd_data), ('\0'), (sizeof(dpcd_data)));
5225 memset(&down_strm_port_count,__builtin_memset((&down_strm_port_count), ('\0'), (sizeof
(union down_stream_port_count)))
5226 '\0', sizeof(union down_stream_port_count))__builtin_memset((&down_strm_port_count), ('\0'), (sizeof
(union down_stream_port_count)))
;
5227 memset(&edp_config_cap, '\0',__builtin_memset((&edp_config_cap), ('\0'), (sizeof(union
edp_configuration_cap)))
5228 sizeof(union edp_configuration_cap))__builtin_memset((&edp_config_cap), ('\0'), (sizeof(union
edp_configuration_cap)))
;
5229
5230 /* if extended timeout is supported in hardware,
5231 * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer
5232 * CTS 4.2.1.1 regression introduced by CTS specs requirement update.
5233 */
5234 dc_link_aux_try_to_configure_timeout(link->ddc,
5235 LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD3200);
5236
5237 /* Try to ensure AUX channel active before proceeding. */
5238 if (link->dc->debug.aux_wake_wa.bits.enable_wa) {
5239 uint64_t timeout_ms = link->dc->debug.aux_wake_wa.bits.timeout_ms;
5240
5241 if (link->dc->debug.aux_wake_wa.bits.use_default_timeout)
5242 timeout_ms = LINK_AUX_WAKE_TIMEOUT_MS1500;
5243 status = wa_try_to_wake_dprx(link, timeout_ms);
5244 }
5245
5246 while (status != DC_OK && aux_channel_retry_cnt < 10) {
5247 status = core_link_read_dpcd(link, DP_SET_POWER0x600,
5248 &dpcd_power_state, sizeof(dpcd_power_state));
5249
5250 /* Delay 1 ms if AUX CH is in power down state. Based on spec
5251 * section 2.3.1.2, if AUX CH may be powered down due to
5252 * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
5253 * signal and may need up to 1 ms before being able to reply.
5254 */
5255 if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D30x2) {
5256 udelay(1000);
5257 aux_channel_retry_cnt++;
5258 }
5259 }
5260
5261 /* If aux channel is not active, return false and trigger another detect*/
5262 if (status != DC_OK) {
5263 dpcd_power_state = DP_SET_POWER_D00x1;
5264 status = core_link_write_dpcd(
5265 link,
5266 DP_SET_POWER0x600,
5267 &dpcd_power_state,
5268 sizeof(dpcd_power_state));
5269
5270 dpcd_power_state = DP_SET_POWER_D30x2;
5271 status = core_link_write_dpcd(
5272 link,
5273 DP_SET_POWER0x600,
5274 &dpcd_power_state,
5275 sizeof(dpcd_power_state));
5276 return false0;
5277 }
5278
5279 is_lttpr_present = dp_retrieve_lttpr_cap(link);
5280
5281 if (is_lttpr_present)
5282 configure_lttpr_mode_transparent(link);
5283
5284 /* Read DP tunneling information. */
5285 status = dpcd_get_tunneling_device_data(link);
5286
5287 dpcd_set_source_specific_data(link);
5288 /* Sink may need to configure internals based on vendor, so allow some
5289 * time before proceeding with possibly vendor specific transactions
5290 */
5291 drm_msleep(post_oui_delay)mdelay(post_oui_delay);
5292
5293 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5294 status = core_link_read_dpcd(
5295 link,
5296 DP_DPCD_REV0x000,
5297 dpcd_data,
5298 sizeof(dpcd_data));
5299 if (status == DC_OK)
5300 break;
5301 }
5302
5303 if (status != DC_OK) {
5304 dm_error("%s: Read receiver caps dpcd data failed.\n", __func__)__drm_err("%s: Read receiver caps dpcd data failed.\n", __func__
)
;
5305 return false0;
5306 }
5307
5308 if (!is_lttpr_present)
5309 dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD552);
5310
5311 {
5312 union training_aux_rd_interval aux_rd_interval;
5313
5314 aux_rd_interval.raw =
5315 dpcd_data[DP_TRAINING_AUX_RD_INTERVAL0x00e];
5316
5317 link->dpcd_caps.ext_receiver_cap_field_present =
5318 aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1;
5319
5320 if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) {
5321 uint8_t ext_cap_data[16];
5322
5323 memset(ext_cap_data, '\0', sizeof(ext_cap_data))__builtin_memset((ext_cap_data), ('\0'), (sizeof(ext_cap_data
)))
;
5324 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5325 status = core_link_read_dpcd(
5326 link,
5327 DP_DP13_DPCD_REV0x2200,
5328 ext_cap_data,
5329 sizeof(ext_cap_data));
5330 if (status == DC_OK) {
5331 memcpy(dpcd_data, ext_cap_data, sizeof(dpcd_data))__builtin_memcpy((dpcd_data), (ext_cap_data), (sizeof(dpcd_data
)))
;
5332 break;
5333 }
5334 }
5335 if (status != DC_OK)
5336 dm_error("%s: Read extend caps data failed, use cap from dpcd 0.\n", __func__)__drm_err("%s: Read extend caps data failed, use cap from dpcd 0.\n"
, __func__)
;
5337 }
5338 }
5339
5340 link->dpcd_caps.dpcd_rev.raw =
5341 dpcd_data[DP_DPCD_REV0x000 - DP_DPCD_REV0x000];
5342
5343 if (link->dpcd_caps.ext_receiver_cap_field_present) {
5344 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5345 status = core_link_read_dpcd(
5346 link,
5347 DP_DPRX_FEATURE_ENUMERATION_LIST0x2210,
5348 &dpcd_dprx_data,
5349 sizeof(dpcd_dprx_data));
5350 if (status == DC_OK)
5351 break;
5352 }
5353
5354 link->dpcd_caps.dprx_feature.raw = dpcd_dprx_data;
5355
5356 if (status != DC_OK)
5357 dm_error("%s: Read DPRX caps data failed.\n", __func__)__drm_err("%s: Read DPRX caps data failed.\n", __func__);
5358 }
5359
5360 else {
5361 link->dpcd_caps.dprx_feature.raw = 0;
5362 }
5363
5364
5365 /* Error condition checking...
5366 * It is impossible for Sink to report Max Lane Count = 0.
5367 * It is possible for Sink to report Max Link Rate = 0, if it is
5368 * an eDP device that is reporting specialized link rates in the
5369 * SUPPORTED_LINK_RATE table.
5370 */
5371 if (dpcd_data[DP_MAX_LANE_COUNT0x002 - DP_DPCD_REV0x000] == 0)
5372 return false0;
5373
5374 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT0x005 -
5375 DP_DPCD_REV0x000];
5376
5377 read_dp_device_vendor_id(link);
5378
5379 /* TODO - decouple raw mst capability from policy decision */
5380 link->dpcd_caps.is_mst_capable = is_mst_supported(link);
5381
5382 get_active_converter_info(ds_port.byte, link);
5383
5384 dp_wa_power_up_0010FA(link, dpcd_data, sizeof(dpcd_data));
5385
5386 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT0x007 -
5387 DP_DPCD_REV0x000];
5388
5389 link->dpcd_caps.allow_invalid_MSA_timing_param =
5390 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5391
5392 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5393 DP_MAX_LANE_COUNT0x002 - DP_DPCD_REV0x000];
5394
5395 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5396 DP_MAX_DOWNSPREAD0x003 - DP_DPCD_REV0x000];
5397
5398 link->reported_link_cap.lane_count =
5399 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5400 link->reported_link_cap.link_rate = get_link_rate_from_max_link_bw(
5401 dpcd_data[DP_MAX_LINK_RATE0x001 - DP_DPCD_REV0x000]);
5402 link->reported_link_cap.link_spread =
5403 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5404 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5405
5406 edp_config_cap.raw = dpcd_data[
5407 DP_EDP_CONFIGURATION_CAP0x00d - DP_DPCD_REV0x000];
5408 link->dpcd_caps.panel_mode_edp =
5409 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5410 link->dpcd_caps.dpcd_display_control_capable =
5411 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5412 link->dpcd_caps.channel_coding_cap.raw =
5413 dpcd_data[DP_MAIN_LINK_CHANNEL_CODING0x006 - DP_DPCD_REV0x000];
5414 link->test_pattern_enabled = false0;
5415 link->compliance_test_state.raw = 0;
5416
5417 /* read sink count */
5418 core_link_read_dpcd(link,
5419 DP_SINK_COUNT0x200,
5420 &link->dpcd_caps.sink_count.raw,
5421 sizeof(link->dpcd_caps.sink_count.raw));
5422
5423 /* read sink ieee oui */
5424 core_link_read_dpcd(link,
5425 DP_SINK_OUI0x400,
5426 (uint8_t *)(&sink_id),
5427 sizeof(sink_id));
5428
5429 link->dpcd_caps.sink_dev_id =
5430 (sink_id.ieee_oui[0] << 16) +
5431 (sink_id.ieee_oui[1] << 8) +
5432 (sink_id.ieee_oui[2]);
5433
5434 memmove(__builtin_memmove((link->dpcd_caps.sink_dev_id_str), (sink_id
.ieee_device_id), (sizeof(sink_id.ieee_device_id)))
5435 link->dpcd_caps.sink_dev_id_str,__builtin_memmove((link->dpcd_caps.sink_dev_id_str), (sink_id
.ieee_device_id), (sizeof(sink_id.ieee_device_id)))
5436 sink_id.ieee_device_id,__builtin_memmove((link->dpcd_caps.sink_dev_id_str), (sink_id
.ieee_device_id), (sizeof(sink_id.ieee_device_id)))
5437 sizeof(sink_id.ieee_device_id))__builtin_memmove((link->dpcd_caps.sink_dev_id_str), (sink_id
.ieee_device_id), (sizeof(sink_id.ieee_device_id)))
;
5438
5439 /* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
5440 {
5441 uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
5442
5443 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5444 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,__builtin_memcmp((link->dpcd_caps.sink_dev_id_str), (str_mbp_2017
), (sizeof(str_mbp_2017)))
5445 sizeof(str_mbp_2017))__builtin_memcmp((link->dpcd_caps.sink_dev_id_str), (str_mbp_2017
), (sizeof(str_mbp_2017)))
) {
5446 link->reported_link_cap.link_rate = 0x0c;
5447 }
5448 }
5449
5450 core_link_read_dpcd(
5451 link,
5452 DP_SINK_HW_REVISION_START0x409,
5453 (uint8_t *)&dp_hw_fw_revision,
5454 sizeof(dp_hw_fw_revision));
5455
5456 link->dpcd_caps.sink_hw_revision =
5457 dp_hw_fw_revision.ieee_hw_rev;
5458
5459 memmove(__builtin_memmove((link->dpcd_caps.sink_fw_revision), (dp_hw_fw_revision
.ieee_fw_rev), (sizeof(dp_hw_fw_revision.ieee_fw_rev)))
5460 link->dpcd_caps.sink_fw_revision,__builtin_memmove((link->dpcd_caps.sink_fw_revision), (dp_hw_fw_revision
.ieee_fw_rev), (sizeof(dp_hw_fw_revision.ieee_fw_rev)))
5461 dp_hw_fw_revision.ieee_fw_rev,__builtin_memmove((link->dpcd_caps.sink_fw_revision), (dp_hw_fw_revision
.ieee_fw_rev), (sizeof(dp_hw_fw_revision.ieee_fw_rev)))
5462 sizeof(dp_hw_fw_revision.ieee_fw_rev))__builtin_memmove((link->dpcd_caps.sink_fw_revision), (dp_hw_fw_revision
.ieee_fw_rev), (sizeof(dp_hw_fw_revision.ieee_fw_rev)))
;
5463
5464 /* Quirk for Apple MBP 2018 15" Retina panels: wrong DP_MAX_LINK_RATE */
5465 {
5466 uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 };
5467 uint8_t fwrev_mbp_2018[] = { 7, 4 };
5468 uint8_t fwrev_mbp_2018_vega[] = { 8, 4 };
5469
5470 /* We also check for the firmware revision as 16,1 models have an
5471 * identical device id and are incorrectly quirked otherwise.
5472 */
5473 if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
5474 !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2018,__builtin_memcmp((link->dpcd_caps.sink_dev_id_str), (str_mbp_2018
), (sizeof(str_mbp_2018)))
5475 sizeof(str_mbp_2018))__builtin_memcmp((link->dpcd_caps.sink_dev_id_str), (str_mbp_2018
), (sizeof(str_mbp_2018)))
&&
5476 (!memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018,__builtin_memcmp((link->dpcd_caps.sink_fw_revision), (fwrev_mbp_2018
), (sizeof(fwrev_mbp_2018)))
5477 sizeof(fwrev_mbp_2018))__builtin_memcmp((link->dpcd_caps.sink_fw_revision), (fwrev_mbp_2018
), (sizeof(fwrev_mbp_2018)))
||
5478 !memcmp(link->dpcd_caps.sink_fw_revision, fwrev_mbp_2018_vega,__builtin_memcmp((link->dpcd_caps.sink_fw_revision), (fwrev_mbp_2018_vega
), (sizeof(fwrev_mbp_2018_vega)))
5479 sizeof(fwrev_mbp_2018_vega))__builtin_memcmp((link->dpcd_caps.sink_fw_revision), (fwrev_mbp_2018_vega
), (sizeof(fwrev_mbp_2018_vega)))
)) {
5480 link->reported_link_cap.link_rate = LINK_RATE_RBR2;
5481 }
5482 }
5483
5484 memset(&link->dpcd_caps.dsc_caps, '\0',__builtin_memset((&link->dpcd_caps.dsc_caps), ('\0'), (
sizeof(link->dpcd_caps.dsc_caps)))
5485 sizeof(link->dpcd_caps.dsc_caps))__builtin_memset((&link->dpcd_caps.dsc_caps), ('\0'), (
sizeof(link->dpcd_caps.dsc_caps)))
;
5486 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap))__builtin_memset((&link->dpcd_caps.fec_cap), ('\0'), (
sizeof(link->dpcd_caps.fec_cap)))
;
5487 /* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */
5488 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) {
5489 status = core_link_read_dpcd(
5490 link,
5491 DP_FEC_CAPABILITY0x090,
5492 &link->dpcd_caps.fec_cap.raw,
5493 sizeof(link->dpcd_caps.fec_cap.raw));
5494 status = core_link_read_dpcd(
5495 link,
5496 DP_DSC_SUPPORT0x060,
5497 link->dpcd_caps.dsc_caps.dsc_basic_caps.raw,
5498 sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw));
5499 if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) {
5500 status = core_link_read_dpcd(
5501 link,
5502 DP_DSC_BRANCH_OVERALL_THROUGHPUT_00x0a0,
5503 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw,
5504 sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw));
5505 DC_LOG_DSC("DSC branch decoder capability is read at link %d", link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "DSC branch decoder capability is read at link %d"
, link->link_index)
;
5506 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x",___drm_dbg(((void *)0), DRM_UT_KMS, "\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x"
, link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.
BRANCH_OVERALL_THROUGHPUT_0)
5507 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_0)___drm_dbg(((void *)0), DRM_UT_KMS, "\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x"
, link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.
BRANCH_OVERALL_THROUGHPUT_0)
;
5508 DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x",___drm_dbg(((void *)0), DRM_UT_KMS, "\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x"
, link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.
BRANCH_OVERALL_THROUGHPUT_1)
5509 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_1)___drm_dbg(((void *)0), DRM_UT_KMS, "\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x"
, link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.
BRANCH_OVERALL_THROUGHPUT_1)
;
5510 DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x",___drm_dbg(((void *)0), DRM_UT_KMS, "\tBRANCH_MAX_LINE_WIDTH 0x%02x"
, link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.
BRANCH_MAX_LINE_WIDTH)
5511 link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH)___drm_dbg(((void *)0), DRM_UT_KMS, "\tBRANCH_MAX_LINE_WIDTH 0x%02x"
, link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.
BRANCH_MAX_LINE_WIDTH)
;
5512 }
5513
5514 /* Apply work around to disable FEC and DSC for USB4 tunneling in TBT3 compatibility mode
5515 * only if required.
5516 */
5517 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
5518 link->dc->debug.dpia_debug.bits.enable_force_tbt3_work_around &&
5519 link->dpcd_caps.is_branch_dev &&
5520 link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC240x90CC24 &&
5521 link->dpcd_caps.branch_hw_revision == DP_BRANCH_HW_REV_100x10 &&
5522 (link->dpcd_caps.fec_cap.bits.FEC_CAPABLE ||
5523 link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT)) {
5524 /* A TBT3 device is expected to report no support for FEC or DSC to a USB4 DPIA.
5525 * Clear FEC and DSC capabilities as a work around if that is not the case.
5526 */
5527 link->wa_flags.dpia_forced_tbt3_mode = true1;
5528 memset(&link->dpcd_caps.dsc_caps, '\0', sizeof(link->dpcd_caps.dsc_caps))__builtin_memset((&link->dpcd_caps.dsc_caps), ('\0'), (
sizeof(link->dpcd_caps.dsc_caps)))
;
5529 memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap))__builtin_memset((&link->dpcd_caps.fec_cap), ('\0'), (
sizeof(link->dpcd_caps.fec_cap)))
;
5530 DC_LOG_DSC("Clear DSC SUPPORT for USB4 link(%d) in TBT3 compatibility mode", link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "Clear DSC SUPPORT for USB4 link(%d) in TBT3 compatibility mode"
, link->link_index)
;
5531 } else
5532 link->wa_flags.dpia_forced_tbt3_mode = false0;
5533 }
5534
5535 if (!dpcd_read_sink_ext_caps(link))
5536 link->dpcd_sink_ext_caps.raw = 0;
5537
5538 if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) {
5539 DC_LOG_DP2("128b/132b encoding is supported at link %d", link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "128b/132b encoding is supported at link %d"
, link->link_index)
;
5540
5541 core_link_read_dpcd(link,
5542 DP_128b_132b_SUPPORTED_LINK_RATES0x2215,
5543 &link->dpcd_caps.dp_128b_132b_supported_link_rates.raw,
5544 sizeof(link->dpcd_caps.dp_128b_132b_supported_link_rates.raw));
5545 if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR20)
5546 link->reported_link_cap.link_rate = LINK_RATE_UHBR20;
5547 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5)
5548 link->reported_link_cap.link_rate = LINK_RATE_UHBR13_5;
5549 else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR10)
5550 link->reported_link_cap.link_rate = LINK_RATE_UHBR10;
5551 else
5552 dm_error("%s: Invalid RX 128b_132b_supported_link_rates\n", __func__)__drm_err("%s: Invalid RX 128b_132b_supported_link_rates\n", __func__
)
;
5553 DC_LOG_DP2("128b/132b supported link rates is read at link %d", link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "128b/132b supported link rates is read at link %d"
, link->link_index)
;
5554 DC_LOG_DP2("\tmax 128b/132b link rate support is %d.%d GHz",___drm_dbg(((void *)0), DRM_UT_KMS, "\tmax 128b/132b link rate support is %d.%d GHz"
, link->reported_link_cap.link_rate / 100, link->reported_link_cap
.link_rate % 100)
5555 link->reported_link_cap.link_rate / 100,___drm_dbg(((void *)0), DRM_UT_KMS, "\tmax 128b/132b link rate support is %d.%d GHz"
, link->reported_link_cap.link_rate / 100, link->reported_link_cap
.link_rate % 100)
5556 link->reported_link_cap.link_rate % 100)___drm_dbg(((void *)0), DRM_UT_KMS, "\tmax 128b/132b link rate support is %d.%d GHz"
, link->reported_link_cap.link_rate / 100, link->reported_link_cap
.link_rate % 100)
;
5557
5558 core_link_read_dpcd(link,
5559 DP_SINK_VIDEO_FALLBACK_FORMATS0x020,
5560 &link->dpcd_caps.fallback_formats.raw,
5561 sizeof(link->dpcd_caps.fallback_formats.raw));
5562 DC_LOG_DP2("sink video fallback format is read at link %d", link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "sink video fallback format is read at link %d"
, link->link_index)
;
5563 if (link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support)
5564 DC_LOG_DP2("\t1920x1080@60Hz 24bpp fallback format supported")___drm_dbg(((void *)0), DRM_UT_KMS, "\t1920x1080@60Hz 24bpp fallback format supported"
)
;
5565 if (link->dpcd_caps.fallback_formats.bits.dp_1280x720_60Hz_24bpp_support)
5566 DC_LOG_DP2("\t1280x720@60Hz 24bpp fallback format supported")___drm_dbg(((void *)0), DRM_UT_KMS, "\t1280x720@60Hz 24bpp fallback format supported"
)
;
5567 if (link->dpcd_caps.fallback_formats.bits.dp_1024x768_60Hz_24bpp_support)
5568 DC_LOG_DP2("\t1024x768@60Hz 24bpp fallback format supported")___drm_dbg(((void *)0), DRM_UT_KMS, "\t1024x768@60Hz 24bpp fallback format supported"
)
;
5569 if (link->dpcd_caps.fallback_formats.raw == 0) {
5570 DC_LOG_DP2("\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported")___drm_dbg(((void *)0), DRM_UT_KMS, "\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported"
)
;
5571 link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support = 1;
5572 }
5573
5574 core_link_read_dpcd(link,
5575 DP_FEC_CAPABILITY_10x091,
5576 &link->dpcd_caps.fec_cap1.raw,
5577 sizeof(link->dpcd_caps.fec_cap1.raw));
5578 DC_LOG_DP2("FEC CAPABILITY 1 is read at link %d", link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "FEC CAPABILITY 1 is read at link %d"
, link->link_index)
;
5579 if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE)
5580 DC_LOG_DP2("\tFEC aggregated error counters are supported")___drm_dbg(((void *)0), DRM_UT_KMS, "\tFEC aggregated error counters are supported"
)
;
5581 }
5582
5583 retrieve_cable_id(link);
5584 dpcd_write_cable_id_to_dprx(link);
5585
5586 /* Connectivity log: detection */
5587 CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: ")do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "Rx Caps: "
); } while (0)
;
5588
5589 return true1;
5590}
5591
5592bool_Bool dp_overwrite_extended_receiver_cap(struct dc_link *link)
5593{
5594 uint8_t dpcd_data[16];
5595 uint32_t read_dpcd_retry_cnt = 3;
5596 enum dc_status status = DC_ERROR_UNEXPECTED;
5597 union dp_downstream_port_present ds_port = { 0 };
5598 union down_stream_port_count down_strm_port_count;
5599 union edp_configuration_cap edp_config_cap;
5600
5601 int i;
5602
5603 for (i = 0; i < read_dpcd_retry_cnt; i++) {
5604 status = core_link_read_dpcd(
5605 link,
5606 DP_DPCD_REV0x000,
5607 dpcd_data,
5608 sizeof(dpcd_data));
5609 if (status == DC_OK)
5610 break;
5611 }
5612
5613 link->dpcd_caps.dpcd_rev.raw =
5614 dpcd_data[DP_DPCD_REV0x000 - DP_DPCD_REV0x000];
5615
5616 if (dpcd_data[DP_MAX_LANE_COUNT0x002 - DP_DPCD_REV0x000] == 0)
5617 return false0;
5618
5619 ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT0x005 -
5620 DP_DPCD_REV0x000];
5621
5622 get_active_converter_info(ds_port.byte, link);
5623
5624 down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT0x007 -
5625 DP_DPCD_REV0x000];
5626
5627 link->dpcd_caps.allow_invalid_MSA_timing_param =
5628 down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM;
5629
5630 link->dpcd_caps.max_ln_count.raw = dpcd_data[
5631 DP_MAX_LANE_COUNT0x002 - DP_DPCD_REV0x000];
5632
5633 link->dpcd_caps.max_down_spread.raw = dpcd_data[
5634 DP_MAX_DOWNSPREAD0x003 - DP_DPCD_REV0x000];
5635
5636 link->reported_link_cap.lane_count =
5637 link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT;
5638 link->reported_link_cap.link_rate = dpcd_data[
5639 DP_MAX_LINK_RATE0x001 - DP_DPCD_REV0x000];
5640 link->reported_link_cap.link_spread =
5641 link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ?
5642 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
5643
5644 edp_config_cap.raw = dpcd_data[
5645 DP_EDP_CONFIGURATION_CAP0x00d - DP_DPCD_REV0x000];
5646 link->dpcd_caps.panel_mode_edp =
5647 edp_config_cap.bits.ALT_SCRAMBLER_RESET;
5648 link->dpcd_caps.dpcd_display_control_capable =
5649 edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE;
5650
5651 return true1;
5652}
5653
5654bool_Bool detect_dp_sink_caps(struct dc_link *link)
5655{
5656 return retrieve_link_cap(link);
5657}
5658
5659static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz)
5660{
5661 enum dc_link_rate link_rate;
5662 // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation.
5663 switch (link_rate_in_khz) {
5664 case 1620000:
5665 link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane
5666 break;
5667 case 2160000:
5668 link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane
5669 break;
5670 case 2430000:
5671 link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane
5672 break;
5673 case 2700000:
5674 link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane
5675 break;
5676 case 3240000:
5677 link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2) - 3.24 Gbps/Lane
5678 break;
5679 case 4320000:
5680 link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane
5681 break;
5682 case 5400000:
5683 link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2) - 5.40 Gbps/Lane
5684 break;
5685 case 8100000:
5686 link_rate = LINK_RATE_HIGH3; // Rate_8 (HBR3) - 8.10 Gbps/Lane
5687 break;
5688 default:
5689 link_rate = LINK_RATE_UNKNOWN;
5690 break;
5691 }
5692 return link_rate;
5693}
5694
5695void detect_edp_sink_caps(struct dc_link *link)
5696{
5697 uint8_t supported_link_rates[16];
5698 uint32_t entry;
5699 uint32_t link_rate_in_khz;
5700 enum dc_link_rate link_rate = LINK_RATE_UNKNOWN;
5701 uint8_t backlight_adj_cap;
5702 uint8_t general_edp_cap;
5703
5704 retrieve_link_cap(link);
5705 link->dpcd_caps.edp_supported_link_rates_count = 0;
5706 memset(supported_link_rates, 0, sizeof(supported_link_rates))__builtin_memset((supported_link_rates), (0), (sizeof(supported_link_rates
)))
;
5707
5708 /*
5709 * edp_supported_link_rates_count is only valid for eDP v1.4 or higher.
5710 * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h"
5711 */
5712 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13 &&
5713 (link->panel_config.ilr.optimize_edp_link_rate ||
5714 link->reported_link_cap.link_rate == LINK_RATE_UNKNOWN)) {
5715 // Read DPCD 00010h - 0001Fh 16 bytes at one shot
5716 core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES0x010,
5717 supported_link_rates, sizeof(supported_link_rates));
5718
5719 for (entry = 0; entry < 16; entry += 2) {
5720 // DPCD register reports per-lane link rate = 16-bit link rate capability
5721 // value X 200 kHz. Need multiplier to find link rate in kHz.
5722 link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 +
5723 supported_link_rates[entry]) * 200;
5724
5725 if (link_rate_in_khz != 0) {
5726 link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz);
5727 link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate;
5728 link->dpcd_caps.edp_supported_link_rates_count++;
5729
5730 if (link->reported_link_cap.link_rate < link_rate)
5731 link->reported_link_cap.link_rate = link_rate;
5732 }
5733 }
5734 }
5735 core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP0x702,
5736 &backlight_adj_cap, sizeof(backlight_adj_cap));
5737
5738 link->dpcd_caps.dynamic_backlight_capable_edp =
5739 (backlight_adj_cap & DP_EDP_DYNAMIC_BACKLIGHT_CAP(1 << 6)) ? true1:false0;
5740
5741 core_link_read_dpcd(link, DP_EDP_GENERAL_CAP_10x701,
5742 &general_edp_cap, sizeof(general_edp_cap));
5743
5744 link->dpcd_caps.set_power_state_capable_edp =
5745 (general_edp_cap & DP_EDP_SET_POWER_CAP(1 << 7)) ? true1:false0;
5746
5747 dc_link_set_default_brightness_aux(link);
5748
5749 core_link_read_dpcd(link, DP_EDP_DPCD_REV0x700,
5750 &link->dpcd_caps.edp_rev,
5751 sizeof(link->dpcd_caps.edp_rev));
5752 /*
5753 * PSR is only valid for eDP v1.3 or higher.
5754 */
5755 if (link->dpcd_caps.edp_rev >= DP_EDP_130x02) {
5756 core_link_read_dpcd(link, DP_PSR_SUPPORT0x070,
5757 &link->dpcd_caps.psr_info.psr_version,
5758 sizeof(link->dpcd_caps.psr_info.psr_version));
5759 if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF80x001CF8)
5760 core_link_read_dpcd(link, DP_FORCE_PSRSU_CAPABILITY0x40F,
5761 &link->dpcd_caps.psr_info.force_psrsu_cap,
5762 sizeof(link->dpcd_caps.psr_info.force_psrsu_cap));
5763 core_link_read_dpcd(link, DP_PSR_CAPS0x071,
5764 &link->dpcd_caps.psr_info.psr_dpcd_caps.raw,
5765 sizeof(link->dpcd_caps.psr_info.psr_dpcd_caps.raw));
5766 if (link->dpcd_caps.psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED) {
5767 core_link_read_dpcd(link, DP_PSR2_SU_Y_GRANULARITY0x074,
5768 &link->dpcd_caps.psr_info.psr2_su_y_granularity_cap,
5769 sizeof(link->dpcd_caps.psr_info.psr2_su_y_granularity_cap));
5770 }
5771 }
5772
5773 /*
5774 * ALPM is only valid for eDP v1.4 or higher.
5775 */
5776 if (link->dpcd_caps.dpcd_rev.raw >= DP_EDP_140x03)
5777 core_link_read_dpcd(link, DP_RECEIVER_ALPM_CAP0x02e,
5778 &link->dpcd_caps.alpm_caps.raw,
5779 sizeof(link->dpcd_caps.alpm_caps.raw));
5780}
5781
5782void dc_link_dp_enable_hpd(const struct dc_link *link)
5783{
5784 struct link_encoder *encoder = link->link_enc;
5785
5786 if (encoder != NULL((void *)0) && encoder->funcs->enable_hpd != NULL((void *)0))
5787 encoder->funcs->enable_hpd(encoder);
5788}
5789
5790void dc_link_dp_disable_hpd(const struct dc_link *link)
5791{
5792 struct link_encoder *encoder = link->link_enc;
5793
5794 if (encoder != NULL((void *)0) && encoder->funcs->enable_hpd != NULL((void *)0))
5795 encoder->funcs->disable_hpd(encoder);
5796}
5797
5798static bool_Bool is_dp_phy_pattern(enum dp_test_pattern test_pattern)
5799{
5800 if ((DP_TEST_PATTERN_PHY_PATTERN_BEGIN <= test_pattern &&
5801 test_pattern <= DP_TEST_PATTERN_PHY_PATTERN_END) ||
5802 test_pattern == DP_TEST_PATTERN_VIDEO_MODE)
5803 return true1;
5804 else
5805 return false0;
5806}
5807
5808static void set_crtc_test_pattern(struct dc_link *link,
5809 struct pipe_ctx *pipe_ctx,
5810 enum dp_test_pattern test_pattern,
5811 enum dp_test_pattern_color_space test_pattern_color_space)
5812{
5813 enum controller_dp_test_pattern controller_test_pattern;
5814 enum dc_color_depth color_depth = pipe_ctx->
5815 stream->timing.display_color_depth;
5816 struct bit_depth_reduction_params params;
5817 struct output_pixel_processor *opp = pipe_ctx->stream_res.opp;
5818 int width = pipe_ctx->stream->timing.h_addressable +
5819 pipe_ctx->stream->timing.h_border_left +
5820 pipe_ctx->stream->timing.h_border_right;
5821 int height = pipe_ctx->stream->timing.v_addressable +
5822 pipe_ctx->stream->timing.v_border_bottom +
5823 pipe_ctx->stream->timing.v_border_top;
5824
5825 memset(&params, 0, sizeof(params))__builtin_memset((&params), (0), (sizeof(params)));
5826
5827 switch (test_pattern) {
5828 case DP_TEST_PATTERN_COLOR_SQUARES:
5829 controller_test_pattern =
5830 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES;
5831 break;
5832 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5833 controller_test_pattern =
5834 CONTROLLER_DP_TEST_PATTERN_COLORSQUARES_CEA;
5835 break;
5836 case DP_TEST_PATTERN_VERTICAL_BARS:
5837 controller_test_pattern =
5838 CONTROLLER_DP_TEST_PATTERN_VERTICALBARS;
5839 break;
5840 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5841 controller_test_pattern =
5842 CONTROLLER_DP_TEST_PATTERN_HORIZONTALBARS;
5843 break;
5844 case DP_TEST_PATTERN_COLOR_RAMP:
5845 controller_test_pattern =
5846 CONTROLLER_DP_TEST_PATTERN_COLORRAMP;
5847 break;
5848 default:
5849 controller_test_pattern =
5850 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE;
5851 break;
5852 }
5853
5854 switch (test_pattern) {
5855 case DP_TEST_PATTERN_COLOR_SQUARES:
5856 case DP_TEST_PATTERN_COLOR_SQUARES_CEA:
5857 case DP_TEST_PATTERN_VERTICAL_BARS:
5858 case DP_TEST_PATTERN_HORIZONTAL_BARS:
5859 case DP_TEST_PATTERN_COLOR_RAMP:
5860 {
5861 /* disable bit depth reduction */
5862 pipe_ctx->stream->bit_depth_params = params;
5863 opp->funcs->opp_program_bit_depth_reduction(opp, &params);
5864 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5865 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
5866 controller_test_pattern, color_depth);
5867 else if (link->dc->hwss.set_disp_pattern_generator) {
5868 struct pipe_ctx *odm_pipe;
5869 enum controller_dp_color_space controller_color_space;
5870 int opp_cnt = 1;
5871 int offset = 0;
5872 int dpg_width = width;
5873
5874 switch (test_pattern_color_space) {
5875 case DP_TEST_PATTERN_COLOR_SPACE_RGB:
5876 controller_color_space = CONTROLLER_DP_COLOR_SPACE_RGB;
5877 break;
5878 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR601:
5879 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR601;
5880 break;
5881 case DP_TEST_PATTERN_COLOR_SPACE_YCBCR709:
5882 controller_color_space = CONTROLLER_DP_COLOR_SPACE_YCBCR709;
5883 break;
5884 case DP_TEST_PATTERN_COLOR_SPACE_UNDEFINED:
5885 default:
5886 controller_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
5887 DC_LOG_ERROR("%s: Color space must be defined for test pattern", __func__)__drm_err("%s: Color space must be defined for test pattern",
__func__)
;
5888 ASSERT(0)do { if (({ static int __warned; int __ret = !!(!(0)); if (__ret
&& !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link_dp.c"
, 5888); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
5889 break;
5890 }
5891
5892 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
5893 opp_cnt++;
5894 dpg_width = width / opp_cnt;
5895 offset = dpg_width;
5896
5897 link->dc->hwss.set_disp_pattern_generator(link->dc,
5898 pipe_ctx,
5899 controller_test_pattern,
5900 controller_color_space,
5901 color_depth,
5902 NULL((void *)0),
5903 dpg_width,
5904 height,
5905 0);
5906
5907 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
5908 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
5909
5910 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
5911 link->dc->hwss.set_disp_pattern_generator(link->dc,
5912 odm_pipe,
5913 controller_test_pattern,
5914 controller_color_space,
5915 color_depth,
5916 NULL((void *)0),
5917 dpg_width,
5918 height,
5919 offset);
5920 offset += offset;
5921 }
5922 }
5923 }
5924 break;
5925 case DP_TEST_PATTERN_VIDEO_MODE:
5926 {
5927 /* restore bitdepth reduction */
5928 resource_build_bit_depth_reduction_params(pipe_ctx->stream, &params);
5929 pipe_ctx->stream->bit_depth_params = params;
5930 opp->funcs->opp_program_bit_depth_reduction(opp, &params);
5931 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
5932 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
5933 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5934 color_depth);
5935 else if (link->dc->hwss.set_disp_pattern_generator) {
5936 struct pipe_ctx *odm_pipe;
5937 int opp_cnt = 1;
5938 int dpg_width;
5939
5940 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
5941 opp_cnt++;
5942
5943 dpg_width = width / opp_cnt;
5944 for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
5945 struct output_pixel_processor *odm_opp = odm_pipe->stream_res.opp;
5946
5947 odm_opp->funcs->opp_program_bit_depth_reduction(odm_opp, &params);
5948 link->dc->hwss.set_disp_pattern_generator(link->dc,
5949 odm_pipe,
5950 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5951 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
5952 color_depth,
5953 NULL((void *)0),
5954 dpg_width,
5955 height,
5956 0);
5957 }
5958 link->dc->hwss.set_disp_pattern_generator(link->dc,
5959 pipe_ctx,
5960 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
5961 CONTROLLER_DP_COLOR_SPACE_UDEFINED,
5962 color_depth,
5963 NULL((void *)0),
5964 dpg_width,
5965 height,
5966 0);
5967 }
5968 }
5969 break;
5970
5971 default:
5972 break;
5973 }
5974}
5975
5976bool_Bool dc_link_dp_set_test_pattern(
5977 struct dc_link *link,
5978 enum dp_test_pattern test_pattern,
5979 enum dp_test_pattern_color_space test_pattern_color_space,
5980 const struct link_training_settings *p_link_settings,
5981 const unsigned char *p_custom_pattern,
5982 unsigned int cust_pattern_size)
5983{
5984 struct pipe_ctx *pipes = link->dc->current_state->res_ctx.pipe_ctx;
5985 struct pipe_ctx *pipe_ctx = NULL((void *)0);
5986 unsigned int lane;
5987 unsigned int i;
5988 unsigned char link_qual_pattern[LANE_COUNT_DP_MAX] = {0};
5989 union dpcd_training_pattern training_pattern;
5990 enum dpcd_phy_test_patterns pattern;
5991
5992 memset(&training_pattern, 0, sizeof(training_pattern))__builtin_memset((&training_pattern), (0), (sizeof(training_pattern
)))
;
5993
5994 for (i = 0; i < MAX_PIPES6; i++) {
5995 if (pipes[i].stream == NULL((void *)0))
5996 continue;
5997
5998 if (pipes[i].stream->link == link && !pipes[i].top_pipe && !pipes[i].prev_odm_pipe) {
5999 pipe_ctx = &pipes[i];
6000 break;
6001 }
6002 }
6003
6004 if (pipe_ctx == NULL((void *)0))
6005 return false0;
6006
6007 /* Reset CRTC Test Pattern if it is currently running and request is VideoMode */
6008 if (link->test_pattern_enabled && test_pattern ==
6009 DP_TEST_PATTERN_VIDEO_MODE) {
6010 /* Set CRTC Test Pattern */
6011 set_crtc_test_pattern(link, pipe_ctx, test_pattern, test_pattern_color_space);
6012 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
6013 (uint8_t *)p_custom_pattern,
6014 (uint32_t)cust_pattern_size);
6015
6016 /* Unblank Stream */
6017 link->dc->hwss.unblank_stream(
6018 pipe_ctx,
6019 &link->verified_link_cap);
6020 /* TODO:m_pHwss->MuteAudioEndpoint
6021 * (pPathMode->pDisplayPath, false);
6022 */
6023
6024 /* Reset Test Pattern state */
6025 link->test_pattern_enabled = false0;
6026
6027 return true1;
6028 }
6029
6030 /* Check for PHY Test Patterns */
6031 if (is_dp_phy_pattern(test_pattern)) {
6032 /* Set DPCD Lane Settings before running test pattern */
6033 if (p_link_settings != NULL((void *)0)) {
6034 if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) &&
6035 p_link_settings->lttpr_mode == LTTPR_MODE_TRANSPARENT) {
6036 dp_fixed_vs_pe_set_retimer_lane_settings(
6037 link,
6038 p_link_settings->dpcd_lane_settings,
6039 p_link_settings->link_settings.lane_count);
6040 } else {
6041 dp_set_hw_lane_settings(link, &pipe_ctx->link_res, p_link_settings, DPRX);
6042 }
6043 dpcd_set_lane_settings(link, p_link_settings, DPRX);
6044 }
6045
6046 /* Blank stream if running test pattern */
6047 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6048 /*TODO:
6049 * m_pHwss->
6050 * MuteAudioEndpoint(pPathMode->pDisplayPath, true);
6051 */
6052 /* Blank stream */
6053 pipes->stream_res.stream_enc->funcs->dp_blank(link, pipe_ctx->stream_res.stream_enc);
6054 }
6055
6056 dp_set_hw_test_pattern(link, &pipe_ctx->link_res, test_pattern,
6057 (uint8_t *)p_custom_pattern,
6058 (uint32_t)cust_pattern_size);
6059
6060 if (test_pattern != DP_TEST_PATTERN_VIDEO_MODE) {
6061 /* Set Test Pattern state */
6062 link->test_pattern_enabled = true1;
6063 if (p_link_settings != NULL((void *)0))
6064 dpcd_set_link_settings(link,
6065 p_link_settings);
6066 }
6067
6068 switch (test_pattern) {
6069 case DP_TEST_PATTERN_VIDEO_MODE:
6070 pattern = PHY_TEST_PATTERN_NONE;
6071 break;
6072 case DP_TEST_PATTERN_D102:
6073 pattern = PHY_TEST_PATTERN_D10_2;
6074 break;
6075 case DP_TEST_PATTERN_SYMBOL_ERROR:
6076 pattern = PHY_TEST_PATTERN_SYMBOL_ERROR;
6077 break;
6078 case DP_TEST_PATTERN_PRBS7:
6079 pattern = PHY_TEST_PATTERN_PRBS7;
6080 break;
6081 case DP_TEST_PATTERN_80BIT_CUSTOM:
6082 pattern = PHY_TEST_PATTERN_80BIT_CUSTOM;
6083 break;
6084 case DP_TEST_PATTERN_CP2520_1:
6085 pattern = PHY_TEST_PATTERN_CP2520_1;
6086 break;
6087 case DP_TEST_PATTERN_CP2520_2:
6088 pattern = PHY_TEST_PATTERN_CP2520_2;
6089 break;
6090 case DP_TEST_PATTERN_CP2520_3:
6091 pattern = PHY_TEST_PATTERN_CP2520_3;
6092 break;
6093 case DP_TEST_PATTERN_128b_132b_TPS1:
6094 pattern = PHY_TEST_PATTERN_128b_132b_TPS1;
6095 break;
6096 case DP_TEST_PATTERN_128b_132b_TPS2:
6097 pattern = PHY_TEST_PATTERN_128b_132b_TPS2;
6098 break;
6099 case DP_TEST_PATTERN_PRBS9:
6100 pattern = PHY_TEST_PATTERN_PRBS9;
6101 break;
6102 case DP_TEST_PATTERN_PRBS11:
6103 pattern = PHY_TEST_PATTERN_PRBS11;
6104 break;
6105 case DP_TEST_PATTERN_PRBS15:
6106 pattern = PHY_TEST_PATTERN_PRBS15;
6107 break;
6108 case DP_TEST_PATTERN_PRBS23:
6109 pattern = PHY_TEST_PATTERN_PRBS23;
6110 break;
6111 case DP_TEST_PATTERN_PRBS31:
6112 pattern = PHY_TEST_PATTERN_PRBS31;
6113 break;
6114 case DP_TEST_PATTERN_264BIT_CUSTOM:
6115 pattern = PHY_TEST_PATTERN_264BIT_CUSTOM;
6116 break;
6117 case DP_TEST_PATTERN_SQUARE_PULSE:
6118 pattern = PHY_TEST_PATTERN_SQUARE_PULSE;
6119 break;
6120 default:
6121 return false0;
6122 }
6123
6124 if (test_pattern == DP_TEST_PATTERN_VIDEO_MODE
6125 /*TODO:&& !pPathMode->pDisplayPath->IsTargetPoweredOn()*/)
6126 return false0;
6127
6128 if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) {
6129#if defined(CONFIG_DRM_AMD_DC_DCN1)
6130 if (test_pattern == DP_TEST_PATTERN_SQUARE_PULSE)
6131 core_link_write_dpcd(link,
6132 DP_LINK_SQUARE_PATTERN0x10F,
6133 p_custom_pattern,
6134 1);
6135
6136#endif
6137 /* tell receiver that we are sending qualification
6138 * pattern DP 1.2 or later - DP receiver's link quality
6139 * pattern is set using DPCD LINK_QUAL_LANEx_SET
6140 * register (0x10B~0x10E)\
6141 */
6142 for (la