1 | /* |
2 | * Copyright 2022 Advanced Micro Devices, Inc. |
3 | * |
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * copy of this software and associated documentation files (the "Software"), |
6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * Software is furnished to do so, subject to the following conditions: |
10 | * |
11 | * The above copyright notice and this permission notice shall be included in |
12 | * all copies or substantial portions of the Software. |
13 | * |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * |
22 | * Authors: AMD |
23 | * |
24 | */ |
25 | |
26 | /* FILE POLICY AND INTENDED USAGE: |
27 | * This file implements dp specific link capability retrieval sequence. It is |
28 | * responsible for retrieving, parsing, overriding, deciding capability obtained |
29 | * from dp link. Link capability consists of encoders, DPRXs, cables, retimers, |
30 | * usb and all other possible backend capabilities. Other components should |
31 | * include this header file in order to access link capability. Accessing link |
32 | * capability by dereferencing dc_link outside dp_link_capability is not a |
33 | * recommended method as it makes the component dependent on the underlying data |
34 | * structure used to represent link capability instead of function interfaces. |
35 | */ |
36 | |
37 | #include "link_dp_capability.h" |
38 | #include "link_ddc.h" |
39 | #include "link_dpcd.h" |
40 | #include "link_dp_dpia.h" |
41 | #include "link_dp_phy.h" |
42 | #include "link_edp_panel_control.h" |
43 | #include "link_dp_irq_handler.h" |
44 | #include "link/accessories/link_dp_trace.h" |
45 | #include "link/link_detection.h" |
46 | #include "link/link_validation.h" |
47 | #include "link_dp_training.h" |
48 | #include "atomfirmware.h" |
49 | #include "resource.h" |
50 | #include "link_enc_cfg.h" |
51 | #include "dc_dmub_srv.h" |
52 | #include "gpio_service_interface.h" |
53 | |
54 | #define DC_LOGGER \ |
55 | link->ctx->logger |
56 | #define DC_TRACE_LEVEL_MESSAGE(...) /* do nothing */ |
57 | |
58 | #ifndef MAX |
59 | #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) |
60 | #endif |
61 | #ifndef MIN |
62 | #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) |
63 | #endif |
64 | |
65 | struct dp_lt_fallback_entry { |
66 | enum dc_lane_count lane_count; |
67 | enum dc_link_rate link_rate; |
68 | }; |
69 | |
70 | static const struct dp_lt_fallback_entry dp_lt_fallbacks[] = { |
71 | /* This link training fallback array is ordered by |
72 | * link bandwidth from highest to lowest. |
73 | * DP specs makes it a normative policy to always |
74 | * choose the next highest link bandwidth during |
75 | * link training fallback. |
76 | */ |
77 | {LANE_COUNT_FOUR, LINK_RATE_UHBR20}, |
78 | {LANE_COUNT_FOUR, LINK_RATE_UHBR13_5}, |
79 | {LANE_COUNT_TWO, LINK_RATE_UHBR20}, |
80 | {LANE_COUNT_FOUR, LINK_RATE_UHBR10}, |
81 | {LANE_COUNT_TWO, LINK_RATE_UHBR13_5}, |
82 | {LANE_COUNT_FOUR, LINK_RATE_HIGH3}, |
83 | {LANE_COUNT_ONE, LINK_RATE_UHBR20}, |
84 | {LANE_COUNT_TWO, LINK_RATE_UHBR10}, |
85 | {LANE_COUNT_FOUR, LINK_RATE_HIGH2}, |
86 | {LANE_COUNT_ONE, LINK_RATE_UHBR13_5}, |
87 | {LANE_COUNT_TWO, LINK_RATE_HIGH3}, |
88 | {LANE_COUNT_ONE, LINK_RATE_UHBR10}, |
89 | {LANE_COUNT_TWO, LINK_RATE_HIGH2}, |
90 | {LANE_COUNT_FOUR, LINK_RATE_HIGH}, |
91 | {LANE_COUNT_ONE, LINK_RATE_HIGH3}, |
92 | {LANE_COUNT_FOUR, LINK_RATE_LOW}, |
93 | {LANE_COUNT_ONE, LINK_RATE_HIGH2}, |
94 | {LANE_COUNT_TWO, LINK_RATE_HIGH}, |
95 | {LANE_COUNT_TWO, LINK_RATE_LOW}, |
96 | {LANE_COUNT_ONE, LINK_RATE_HIGH}, |
97 | {LANE_COUNT_ONE, LINK_RATE_LOW}, |
98 | }; |
99 | |
100 | static const struct dc_link_settings fail_safe_link_settings = { |
101 | .lane_count = LANE_COUNT_ONE, |
102 | .link_rate = LINK_RATE_LOW, |
103 | .link_spread = LINK_SPREAD_DISABLED, |
104 | }; |
105 | |
106 | bool is_dp_active_dongle(const struct dc_link *link) |
107 | { |
108 | return (link->dpcd_caps.dongle_type >= DISPLAY_DONGLE_DP_VGA_CONVERTER) && |
109 | (link->dpcd_caps.dongle_type <= DISPLAY_DONGLE_DP_HDMI_CONVERTER); |
110 | } |
111 | |
112 | bool is_dp_branch_device(const struct dc_link *link) |
113 | { |
114 | return link->dpcd_caps.is_branch_dev; |
115 | } |
116 | |
117 | static int translate_dpcd_max_bpc(enum dpcd_downstream_port_max_bpc bpc) |
118 | { |
119 | switch (bpc) { |
120 | case DOWN_STREAM_MAX_8BPC: |
121 | return 8; |
122 | case DOWN_STREAM_MAX_10BPC: |
123 | return 10; |
124 | case DOWN_STREAM_MAX_12BPC: |
125 | return 12; |
126 | case DOWN_STREAM_MAX_16BPC: |
127 | return 16; |
128 | default: |
129 | break; |
130 | } |
131 | |
132 | return -1; |
133 | } |
134 | |
135 | uint8_t dp_parse_lttpr_repeater_count(uint8_t lttpr_repeater_count) |
136 | { |
137 | switch (lttpr_repeater_count) { |
138 | case 0x80: // 1 lttpr repeater |
139 | return 1; |
140 | case 0x40: // 2 lttpr repeaters |
141 | return 2; |
142 | case 0x20: // 3 lttpr repeaters |
143 | return 3; |
144 | case 0x10: // 4 lttpr repeaters |
145 | return 4; |
146 | case 0x08: // 5 lttpr repeaters |
147 | return 5; |
148 | case 0x04: // 6 lttpr repeaters |
149 | return 6; |
150 | case 0x02: // 7 lttpr repeaters |
151 | return 7; |
152 | case 0x01: // 8 lttpr repeaters |
153 | return 8; |
154 | default: |
155 | break; |
156 | } |
157 | return 0; // invalid value |
158 | } |
159 | |
160 | uint32_t link_bw_kbps_from_raw_frl_link_rate_data(uint8_t bw) |
161 | { |
162 | switch (bw) { |
163 | case 0b001: |
164 | return 9000000; |
165 | case 0b010: |
166 | return 18000000; |
167 | case 0b011: |
168 | return 24000000; |
169 | case 0b100: |
170 | return 32000000; |
171 | case 0b101: |
172 | return 40000000; |
173 | case 0b110: |
174 | return 48000000; |
175 | } |
176 | |
177 | return 0; |
178 | } |
179 | |
180 | static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in_khz) |
181 | { |
182 | enum dc_link_rate link_rate; |
183 | // LinkRate is normally stored as a multiplier of 0.27 Gbps per lane. Do the translation. |
184 | switch (link_rate_in_khz) { |
185 | case 1620000: |
186 | link_rate = LINK_RATE_LOW; // Rate_1 (RBR) - 1.62 Gbps/Lane |
187 | break; |
188 | case 2160000: |
189 | link_rate = LINK_RATE_RATE_2; // Rate_2 - 2.16 Gbps/Lane |
190 | break; |
191 | case 2430000: |
192 | link_rate = LINK_RATE_RATE_3; // Rate_3 - 2.43 Gbps/Lane |
193 | break; |
194 | case 2700000: |
195 | link_rate = LINK_RATE_HIGH; // Rate_4 (HBR) - 2.70 Gbps/Lane |
196 | break; |
197 | case 3240000: |
198 | link_rate = LINK_RATE_RBR2; // Rate_5 (RBR2)- 3.24 Gbps/Lane |
199 | break; |
200 | case 4320000: |
201 | link_rate = LINK_RATE_RATE_6; // Rate_6 - 4.32 Gbps/Lane |
202 | break; |
203 | case 5400000: |
204 | link_rate = LINK_RATE_HIGH2; // Rate_7 (HBR2)- 5.40 Gbps/Lane |
205 | break; |
206 | case 6750000: |
207 | link_rate = LINK_RATE_RATE_8; // Rate_8 - 6.75 Gbps/Lane |
208 | break; |
209 | case 8100000: |
210 | link_rate = LINK_RATE_HIGH3; // Rate_9 (HBR3)- 8.10 Gbps/Lane |
211 | break; |
212 | default: |
213 | link_rate = LINK_RATE_UNKNOWN; |
214 | break; |
215 | } |
216 | return link_rate; |
217 | } |
218 | |
219 | static union dp_cable_id intersect_cable_id( |
220 | union dp_cable_id *a, union dp_cable_id *b) |
221 | { |
222 | union dp_cable_id out; |
223 | |
224 | out.bits.UHBR10_20_CAPABILITY = MIN(a->bits.UHBR10_20_CAPABILITY, |
225 | b->bits.UHBR10_20_CAPABILITY); |
226 | out.bits.UHBR13_5_CAPABILITY = MIN(a->bits.UHBR13_5_CAPABILITY, |
227 | b->bits.UHBR13_5_CAPABILITY); |
228 | out.bits.CABLE_TYPE = MAX(a->bits.CABLE_TYPE, b->bits.CABLE_TYPE); |
229 | |
230 | return out; |
231 | } |
232 | |
233 | /* |
234 | * Return PCON's post FRL link training supported BW if its non-zero, otherwise return max_supported_frl_bw. |
235 | */ |
236 | static uint32_t intersect_frl_link_bw_support( |
237 | const uint32_t max_supported_frl_bw_in_kbps, |
238 | const union hdmi_encoded_link_bw hdmi_encoded_link_bw) |
239 | { |
240 | uint32_t supported_bw_in_kbps = max_supported_frl_bw_in_kbps; |
241 | |
242 | // HDMI_ENCODED_LINK_BW bits are only valid if HDMI Link Configuration bit is 1 (FRL mode) |
243 | if (hdmi_encoded_link_bw.bits.FRL_MODE) { |
244 | if (hdmi_encoded_link_bw.bits.BW_48Gbps) |
245 | supported_bw_in_kbps = 48000000; |
246 | else if (hdmi_encoded_link_bw.bits.BW_40Gbps) |
247 | supported_bw_in_kbps = 40000000; |
248 | else if (hdmi_encoded_link_bw.bits.BW_32Gbps) |
249 | supported_bw_in_kbps = 32000000; |
250 | else if (hdmi_encoded_link_bw.bits.BW_24Gbps) |
251 | supported_bw_in_kbps = 24000000; |
252 | else if (hdmi_encoded_link_bw.bits.BW_18Gbps) |
253 | supported_bw_in_kbps = 18000000; |
254 | else if (hdmi_encoded_link_bw.bits.BW_9Gbps) |
255 | supported_bw_in_kbps = 9000000; |
256 | } |
257 | |
258 | return supported_bw_in_kbps; |
259 | } |
260 | |
261 | static enum clock_source_id get_clock_source_id(struct dc_link *link) |
262 | { |
263 | enum clock_source_id dp_cs_id = CLOCK_SOURCE_ID_UNDEFINED; |
264 | struct clock_source *dp_cs = link->dc->res_pool->dp_clock_source; |
265 | |
266 | if (dp_cs != NULL) { |
267 | dp_cs_id = dp_cs->id; |
268 | } else { |
269 | /* |
270 | * dp clock source is not initialized for some reason. |
271 | * Should not happen, CLOCK_SOURCE_ID_EXTERNAL will be used |
272 | */ |
273 | ASSERT(dp_cs); |
274 | } |
275 | |
276 | return dp_cs_id; |
277 | } |
278 | |
279 | static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data, |
280 | int length) |
281 | { |
282 | int retry = 0; |
283 | |
284 | if (!link->dpcd_caps.dpcd_rev.raw) { |
285 | do { |
286 | dpcd_write_rx_power_ctrl(link, on: true); |
287 | core_link_read_dpcd(link, DP_DPCD_REV, |
288 | data: dpcd_data, size: length); |
289 | link->dpcd_caps.dpcd_rev.raw = dpcd_data[ |
290 | DP_DPCD_REV - |
291 | DP_DPCD_REV]; |
292 | } while (retry++ < 4 && !link->dpcd_caps.dpcd_rev.raw); |
293 | } |
294 | |
295 | if (link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_VGA_CONVERTER) { |
296 | switch (link->dpcd_caps.branch_dev_id) { |
297 | /* 0010FA active dongles (DP-VGA, DP-DLDVI converters) power down |
298 | * all internal circuits including AUX communication preventing |
299 | * reading DPCD table and EDID (spec violation). |
300 | * Encoder will skip DP RX power down on disable_output to |
301 | * keep receiver powered all the time.*/ |
302 | case DP_BRANCH_DEVICE_ID_0010FA: |
303 | case DP_BRANCH_DEVICE_ID_0080E1: |
304 | case DP_BRANCH_DEVICE_ID_00E04C: |
305 | link->wa_flags.dp_keep_receiver_powered = true; |
306 | break; |
307 | |
308 | /* TODO: May need work around for other dongles. */ |
309 | default: |
310 | link->wa_flags.dp_keep_receiver_powered = false; |
311 | break; |
312 | } |
313 | } else |
314 | link->wa_flags.dp_keep_receiver_powered = false; |
315 | } |
316 | |
317 | bool dp_is_fec_supported(const struct dc_link *link) |
318 | { |
319 | /* TODO - use asic cap instead of link_enc->features |
320 | * we no longer know which link enc to use for this link before commit |
321 | */ |
322 | struct link_encoder *link_enc = NULL; |
323 | |
324 | link_enc = link_enc_cfg_get_link_enc(link); |
325 | ASSERT(link_enc); |
326 | |
327 | return (dc_is_dp_signal(signal: link->connector_signal) && link_enc && |
328 | link_enc->features.fec_supported && |
329 | link->dpcd_caps.fec_cap.bits.FEC_CAPABLE); |
330 | } |
331 | |
332 | bool dp_should_enable_fec(const struct dc_link *link) |
333 | { |
334 | bool force_disable = false; |
335 | |
336 | if (link->fec_state == dc_link_fec_enabled) |
337 | force_disable = false; |
338 | else if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT_MST && |
339 | link->local_sink && |
340 | link->local_sink->edid_caps.panel_patch.disable_fec) |
341 | force_disable = true; |
342 | else if (link->connector_signal == SIGNAL_TYPE_EDP |
343 | && (link->dpcd_caps.dsc_caps.dsc_basic_caps.fields. |
344 | dsc_support.DSC_SUPPORT == false |
345 | || link->panel_config.dsc.disable_dsc_edp |
346 | || !link->dc->caps.edp_dsc_support)) |
347 | force_disable = true; |
348 | |
349 | return !force_disable && dp_is_fec_supported(link); |
350 | } |
351 | |
352 | bool dp_is_128b_132b_signal(struct pipe_ctx *pipe_ctx) |
353 | { |
354 | /* If this assert is hit then we have a link encoder dynamic management issue */ |
355 | ASSERT(pipe_ctx->stream_res.hpo_dp_stream_enc ? pipe_ctx->link_res.hpo_dp_link_enc != NULL : true); |
356 | return (pipe_ctx->stream_res.hpo_dp_stream_enc && |
357 | pipe_ctx->link_res.hpo_dp_link_enc && |
358 | dc_is_dp_signal(signal: pipe_ctx->stream->signal)); |
359 | } |
360 | |
361 | bool dp_is_lttpr_present(struct dc_link *link) |
362 | { |
363 | return (dp_parse_lttpr_repeater_count(lttpr_repeater_count: link->dpcd_caps.lttpr_caps.phy_repeater_cnt) != 0 && |
364 | link->dpcd_caps.lttpr_caps.max_lane_count > 0 && |
365 | link->dpcd_caps.lttpr_caps.max_lane_count <= 4 && |
366 | link->dpcd_caps.lttpr_caps.revision.raw >= 0x14); |
367 | } |
368 | |
369 | /* in DP compliance test, DPR-120 may have |
370 | * a random value in its MAX_LINK_BW dpcd field. |
371 | * We map it to the maximum supported link rate that |
372 | * is smaller than MAX_LINK_BW in this case. |
373 | */ |
374 | static enum dc_link_rate get_link_rate_from_max_link_bw( |
375 | uint8_t max_link_bw) |
376 | { |
377 | enum dc_link_rate link_rate; |
378 | |
379 | if (max_link_bw >= LINK_RATE_HIGH3) { |
380 | link_rate = LINK_RATE_HIGH3; |
381 | } else if (max_link_bw < LINK_RATE_HIGH3 |
382 | && max_link_bw >= LINK_RATE_HIGH2) { |
383 | link_rate = LINK_RATE_HIGH2; |
384 | } else if (max_link_bw < LINK_RATE_HIGH2 |
385 | && max_link_bw >= LINK_RATE_HIGH) { |
386 | link_rate = LINK_RATE_HIGH; |
387 | } else if (max_link_bw < LINK_RATE_HIGH |
388 | && max_link_bw >= LINK_RATE_LOW) { |
389 | link_rate = LINK_RATE_LOW; |
390 | } else { |
391 | link_rate = LINK_RATE_UNKNOWN; |
392 | } |
393 | |
394 | return link_rate; |
395 | } |
396 | |
397 | static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link) |
398 | { |
399 | enum dc_link_rate lttpr_max_link_rate = link->dpcd_caps.lttpr_caps.max_link_rate; |
400 | |
401 | if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR20) |
402 | lttpr_max_link_rate = LINK_RATE_UHBR20; |
403 | else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5) |
404 | lttpr_max_link_rate = LINK_RATE_UHBR13_5; |
405 | else if (link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR10) |
406 | lttpr_max_link_rate = LINK_RATE_UHBR10; |
407 | |
408 | return lttpr_max_link_rate; |
409 | } |
410 | |
411 | static enum dc_link_rate get_cable_max_link_rate(struct dc_link *link) |
412 | { |
413 | enum dc_link_rate cable_max_link_rate = LINK_RATE_UNKNOWN; |
414 | |
415 | if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR20) { |
416 | cable_max_link_rate = LINK_RATE_UHBR20; |
417 | } else if (link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY) { |
418 | cable_max_link_rate = LINK_RATE_UHBR13_5; |
419 | } else if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR10) { |
420 | // allow DP40 cables to do UHBR13.5 for passive or unknown cable type |
421 | if (link->dpcd_caps.cable_id.bits.CABLE_TYPE < 2) { |
422 | cable_max_link_rate = LINK_RATE_UHBR13_5; |
423 | } else { |
424 | cable_max_link_rate = LINK_RATE_UHBR10; |
425 | } |
426 | } |
427 | |
428 | return cable_max_link_rate; |
429 | } |
430 | |
431 | static inline bool reached_minimum_lane_count(enum dc_lane_count lane_count) |
432 | { |
433 | return lane_count <= LANE_COUNT_ONE; |
434 | } |
435 | |
436 | static inline bool reached_minimum_link_rate(enum dc_link_rate link_rate) |
437 | { |
438 | return link_rate <= LINK_RATE_LOW; |
439 | } |
440 | |
441 | static enum dc_lane_count reduce_lane_count(enum dc_lane_count lane_count) |
442 | { |
443 | switch (lane_count) { |
444 | case LANE_COUNT_FOUR: |
445 | return LANE_COUNT_TWO; |
446 | case LANE_COUNT_TWO: |
447 | return LANE_COUNT_ONE; |
448 | case LANE_COUNT_ONE: |
449 | return LANE_COUNT_UNKNOWN; |
450 | default: |
451 | return LANE_COUNT_UNKNOWN; |
452 | } |
453 | } |
454 | |
455 | static enum dc_link_rate reduce_link_rate(const struct dc_link *link, enum dc_link_rate link_rate) |
456 | { |
457 | // NEEDSWORK: provide some details about why this function never returns some of the |
458 | // obscure link rates such as 4.32 Gbps or 3.24 Gbps and if such behavior is intended. |
459 | // |
460 | |
461 | switch (link_rate) { |
462 | case LINK_RATE_UHBR20: |
463 | return LINK_RATE_UHBR13_5; |
464 | case LINK_RATE_UHBR13_5: |
465 | return LINK_RATE_UHBR10; |
466 | case LINK_RATE_UHBR10: |
467 | return LINK_RATE_HIGH3; |
468 | case LINK_RATE_HIGH3: |
469 | if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->debug.support_eDP1_5) |
470 | return LINK_RATE_RATE_8; |
471 | return LINK_RATE_HIGH2; |
472 | case LINK_RATE_RATE_8: |
473 | return LINK_RATE_HIGH2; |
474 | case LINK_RATE_HIGH2: |
475 | return LINK_RATE_HIGH; |
476 | case LINK_RATE_RATE_6: |
477 | case LINK_RATE_RBR2: |
478 | return LINK_RATE_HIGH; |
479 | case LINK_RATE_HIGH: |
480 | return LINK_RATE_LOW; |
481 | case LINK_RATE_RATE_3: |
482 | case LINK_RATE_RATE_2: |
483 | return LINK_RATE_LOW; |
484 | case LINK_RATE_LOW: |
485 | default: |
486 | return LINK_RATE_UNKNOWN; |
487 | } |
488 | } |
489 | |
490 | static enum dc_lane_count increase_lane_count(enum dc_lane_count lane_count) |
491 | { |
492 | switch (lane_count) { |
493 | case LANE_COUNT_ONE: |
494 | return LANE_COUNT_TWO; |
495 | case LANE_COUNT_TWO: |
496 | return LANE_COUNT_FOUR; |
497 | default: |
498 | return LANE_COUNT_UNKNOWN; |
499 | } |
500 | } |
501 | |
502 | static enum dc_link_rate increase_link_rate(struct dc_link *link, |
503 | enum dc_link_rate link_rate) |
504 | { |
505 | switch (link_rate) { |
506 | case LINK_RATE_LOW: |
507 | return LINK_RATE_HIGH; |
508 | case LINK_RATE_HIGH: |
509 | return LINK_RATE_HIGH2; |
510 | case LINK_RATE_HIGH2: |
511 | return LINK_RATE_HIGH3; |
512 | case LINK_RATE_HIGH3: |
513 | return LINK_RATE_UHBR10; |
514 | case LINK_RATE_UHBR10: |
515 | /* upto DP2.x specs UHBR13.5 is the only link rate that could be |
516 | * not supported by DPRX when higher link rate is supported. |
517 | * so we treat it as a special case for code simplicity. When we |
518 | * have new specs with more link rates like this, we should |
519 | * consider a more generic solution to handle discrete link |
520 | * rate capabilities. |
521 | */ |
522 | return link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 ? |
523 | LINK_RATE_UHBR13_5 : LINK_RATE_UHBR20; |
524 | case LINK_RATE_UHBR13_5: |
525 | return LINK_RATE_UHBR20; |
526 | default: |
527 | return LINK_RATE_UNKNOWN; |
528 | } |
529 | } |
530 | |
531 | static bool decide_fallback_link_setting_max_bw_policy( |
532 | struct dc_link *link, |
533 | const struct dc_link_settings *max, |
534 | struct dc_link_settings *cur, |
535 | enum link_training_result training_result) |
536 | { |
537 | uint8_t cur_idx = 0, next_idx; |
538 | bool found = false; |
539 | |
540 | if (training_result == LINK_TRAINING_ABORT) |
541 | return false; |
542 | |
543 | while (cur_idx < ARRAY_SIZE(dp_lt_fallbacks)) |
544 | /* find current index */ |
545 | if (dp_lt_fallbacks[cur_idx].lane_count == cur->lane_count && |
546 | dp_lt_fallbacks[cur_idx].link_rate == cur->link_rate) |
547 | break; |
548 | else |
549 | cur_idx++; |
550 | |
551 | next_idx = cur_idx + 1; |
552 | |
553 | while (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) |
554 | /* find next index */ |
555 | if (dp_lt_fallbacks[next_idx].lane_count > max->lane_count || |
556 | dp_lt_fallbacks[next_idx].link_rate > max->link_rate) |
557 | next_idx++; |
558 | else if (dp_lt_fallbacks[next_idx].link_rate == LINK_RATE_UHBR13_5 && |
559 | link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5 == 0) |
560 | /* upto DP2.x specs UHBR13.5 is the only link rate that |
561 | * could be not supported by DPRX when higher link rate |
562 | * is supported. so we treat it as a special case for |
563 | * code simplicity. When we have new specs with more |
564 | * link rates like this, we should consider a more |
565 | * generic solution to handle discrete link rate |
566 | * capabilities. |
567 | */ |
568 | next_idx++; |
569 | else |
570 | break; |
571 | |
572 | if (next_idx < ARRAY_SIZE(dp_lt_fallbacks)) { |
573 | cur->lane_count = dp_lt_fallbacks[next_idx].lane_count; |
574 | cur->link_rate = dp_lt_fallbacks[next_idx].link_rate; |
575 | found = true; |
576 | } |
577 | |
578 | return found; |
579 | } |
580 | |
581 | /* |
582 | * function: set link rate and lane count fallback based |
583 | * on current link setting and last link training result |
584 | * return value: |
585 | * true - link setting could be set |
586 | * false - has reached minimum setting |
587 | * and no further fallback could be done |
588 | */ |
589 | bool decide_fallback_link_setting( |
590 | struct dc_link *link, |
591 | struct dc_link_settings *max, |
592 | struct dc_link_settings *cur, |
593 | enum link_training_result training_result) |
594 | { |
595 | if (link_dp_get_encoding_format(link_settings: max) == DP_128b_132b_ENCODING || |
596 | link->dc->debug.force_dp2_lt_fallback_method) |
597 | return decide_fallback_link_setting_max_bw_policy(link, max, |
598 | cur, training_result); |
599 | |
600 | switch (training_result) { |
601 | case LINK_TRAINING_CR_FAIL_LANE0: |
602 | case LINK_TRAINING_CR_FAIL_LANE1: |
603 | case LINK_TRAINING_CR_FAIL_LANE23: |
604 | case LINK_TRAINING_LQA_FAIL: |
605 | { |
606 | if (!reached_minimum_link_rate(link_rate: cur->link_rate)) { |
607 | cur->link_rate = reduce_link_rate(link, link_rate: cur->link_rate); |
608 | } else if (!reached_minimum_lane_count(lane_count: cur->lane_count)) { |
609 | cur->link_rate = max->link_rate; |
610 | if (training_result == LINK_TRAINING_CR_FAIL_LANE0) |
611 | return false; |
612 | else if (training_result == LINK_TRAINING_CR_FAIL_LANE1) |
613 | cur->lane_count = LANE_COUNT_ONE; |
614 | else if (training_result == LINK_TRAINING_CR_FAIL_LANE23) |
615 | cur->lane_count = LANE_COUNT_TWO; |
616 | else |
617 | cur->lane_count = reduce_lane_count(lane_count: cur->lane_count); |
618 | } else { |
619 | return false; |
620 | } |
621 | break; |
622 | } |
623 | case LINK_TRAINING_EQ_FAIL_EQ: |
624 | case LINK_TRAINING_EQ_FAIL_CR_PARTIAL: |
625 | { |
626 | if (!reached_minimum_lane_count(lane_count: cur->lane_count)) { |
627 | cur->lane_count = reduce_lane_count(lane_count: cur->lane_count); |
628 | } else if (!reached_minimum_link_rate(link_rate: cur->link_rate)) { |
629 | cur->link_rate = reduce_link_rate(link, link_rate: cur->link_rate); |
630 | /* Reduce max link rate to avoid potential infinite loop. |
631 | * Needed so that any subsequent CR_FAIL fallback can't |
632 | * re-set the link rate higher than the link rate from |
633 | * the latest EQ_FAIL fallback. |
634 | */ |
635 | max->link_rate = cur->link_rate; |
636 | cur->lane_count = max->lane_count; |
637 | } else { |
638 | return false; |
639 | } |
640 | break; |
641 | } |
642 | case LINK_TRAINING_EQ_FAIL_CR: |
643 | { |
644 | if (!reached_minimum_link_rate(link_rate: cur->link_rate)) { |
645 | cur->link_rate = reduce_link_rate(link, link_rate: cur->link_rate); |
646 | /* Reduce max link rate to avoid potential infinite loop. |
647 | * Needed so that any subsequent CR_FAIL fallback can't |
648 | * re-set the link rate higher than the link rate from |
649 | * the latest EQ_FAIL fallback. |
650 | */ |
651 | max->link_rate = cur->link_rate; |
652 | cur->lane_count = max->lane_count; |
653 | } else { |
654 | return false; |
655 | } |
656 | break; |
657 | } |
658 | default: |
659 | return false; |
660 | } |
661 | return true; |
662 | } |
663 | static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_settings *link_setting, uint32_t req_bw) |
664 | { |
665 | struct dc_link_settings initial_link_setting = { |
666 | LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0}; |
667 | struct dc_link_settings current_link_setting = |
668 | initial_link_setting; |
669 | uint32_t link_bw; |
670 | |
671 | if (req_bw > dp_link_bandwidth_kbps(link, link_settings: &link->verified_link_cap)) |
672 | return false; |
673 | |
674 | /* search for the minimum link setting that: |
675 | * 1. is supported according to the link training result |
676 | * 2. could support the b/w requested by the timing |
677 | */ |
678 | while (current_link_setting.link_rate <= |
679 | link->verified_link_cap.link_rate) { |
680 | link_bw = dp_link_bandwidth_kbps( |
681 | link, |
682 | link_settings: ¤t_link_setting); |
683 | if (req_bw <= link_bw) { |
684 | *link_setting = current_link_setting; |
685 | return true; |
686 | } |
687 | |
688 | if (current_link_setting.lane_count < |
689 | link->verified_link_cap.lane_count) { |
690 | current_link_setting.lane_count = |
691 | increase_lane_count( |
692 | lane_count: current_link_setting.lane_count); |
693 | } else { |
694 | current_link_setting.link_rate = |
695 | increase_link_rate(link, |
696 | link_rate: current_link_setting.link_rate); |
697 | current_link_setting.lane_count = |
698 | initial_link_setting.lane_count; |
699 | } |
700 | } |
701 | |
702 | return false; |
703 | } |
704 | |
705 | bool edp_decide_link_settings(struct dc_link *link, |
706 | struct dc_link_settings *link_setting, uint32_t req_bw) |
707 | { |
708 | struct dc_link_settings initial_link_setting; |
709 | struct dc_link_settings current_link_setting; |
710 | uint32_t link_bw; |
711 | |
712 | /* |
713 | * edp_supported_link_rates_count is only valid for eDP v1.4 or higher. |
714 | * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h" |
715 | */ |
716 | if (!edp_is_ilr_optimization_enabled(link)) { |
717 | *link_setting = link->verified_link_cap; |
718 | return true; |
719 | } |
720 | |
721 | memset(&initial_link_setting, 0, sizeof(initial_link_setting)); |
722 | initial_link_setting.lane_count = LANE_COUNT_ONE; |
723 | initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0]; |
724 | initial_link_setting.link_spread = LINK_SPREAD_DISABLED; |
725 | initial_link_setting.use_link_rate_set = true; |
726 | initial_link_setting.link_rate_set = 0; |
727 | current_link_setting = initial_link_setting; |
728 | |
729 | /* search for the minimum link setting that: |
730 | * 1. is supported according to the link training result |
731 | * 2. could support the b/w requested by the timing |
732 | */ |
733 | while (current_link_setting.link_rate <= |
734 | link->verified_link_cap.link_rate) { |
735 | link_bw = dp_link_bandwidth_kbps( |
736 | link, |
737 | link_settings: ¤t_link_setting); |
738 | if (req_bw <= link_bw) { |
739 | *link_setting = current_link_setting; |
740 | return true; |
741 | } |
742 | |
743 | if (current_link_setting.lane_count < |
744 | link->verified_link_cap.lane_count) { |
745 | current_link_setting.lane_count = |
746 | increase_lane_count( |
747 | lane_count: current_link_setting.lane_count); |
748 | } else { |
749 | if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) { |
750 | current_link_setting.link_rate_set++; |
751 | current_link_setting.link_rate = |
752 | link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set]; |
753 | current_link_setting.lane_count = |
754 | initial_link_setting.lane_count; |
755 | } else |
756 | break; |
757 | } |
758 | } |
759 | return false; |
760 | } |
761 | |
762 | bool decide_edp_link_settings_with_dsc(struct dc_link *link, |
763 | struct dc_link_settings *link_setting, |
764 | uint32_t req_bw, |
765 | enum dc_link_rate max_link_rate) |
766 | { |
767 | struct dc_link_settings initial_link_setting; |
768 | struct dc_link_settings current_link_setting; |
769 | uint32_t link_bw; |
770 | |
771 | unsigned int policy = 0; |
772 | |
773 | policy = link->panel_config.dsc.force_dsc_edp_policy; |
774 | if (max_link_rate == LINK_RATE_UNKNOWN) |
775 | max_link_rate = link->verified_link_cap.link_rate; |
776 | /* |
777 | * edp_supported_link_rates_count is only valid for eDP v1.4 or higher. |
778 | * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h" |
779 | */ |
780 | if (!edp_is_ilr_optimization_enabled(link)) { |
781 | /* for DSC enabled case, we search for minimum lane count */ |
782 | memset(&initial_link_setting, 0, sizeof(initial_link_setting)); |
783 | initial_link_setting.lane_count = LANE_COUNT_ONE; |
784 | initial_link_setting.link_rate = LINK_RATE_LOW; |
785 | initial_link_setting.link_spread = LINK_SPREAD_DISABLED; |
786 | initial_link_setting.use_link_rate_set = false; |
787 | initial_link_setting.link_rate_set = 0; |
788 | current_link_setting = initial_link_setting; |
789 | if (req_bw > dp_link_bandwidth_kbps(link, link_settings: &link->verified_link_cap)) |
790 | return false; |
791 | |
792 | /* search for the minimum link setting that: |
793 | * 1. is supported according to the link training result |
794 | * 2. could support the b/w requested by the timing |
795 | */ |
796 | while (current_link_setting.link_rate <= |
797 | max_link_rate) { |
798 | link_bw = dp_link_bandwidth_kbps( |
799 | link, |
800 | link_settings: ¤t_link_setting); |
801 | if (req_bw <= link_bw) { |
802 | *link_setting = current_link_setting; |
803 | return true; |
804 | } |
805 | if (policy) { |
806 | /* minimize lane */ |
807 | if (current_link_setting.link_rate < max_link_rate) { |
808 | current_link_setting.link_rate = |
809 | increase_link_rate(link, |
810 | link_rate: current_link_setting.link_rate); |
811 | } else { |
812 | if (current_link_setting.lane_count < |
813 | link->verified_link_cap.lane_count) { |
814 | current_link_setting.lane_count = |
815 | increase_lane_count( |
816 | lane_count: current_link_setting.lane_count); |
817 | current_link_setting.link_rate = initial_link_setting.link_rate; |
818 | } else |
819 | break; |
820 | } |
821 | } else { |
822 | /* minimize link rate */ |
823 | if (current_link_setting.lane_count < |
824 | link->verified_link_cap.lane_count) { |
825 | current_link_setting.lane_count = |
826 | increase_lane_count( |
827 | lane_count: current_link_setting.lane_count); |
828 | } else { |
829 | current_link_setting.link_rate = |
830 | increase_link_rate(link, |
831 | link_rate: current_link_setting.link_rate); |
832 | current_link_setting.lane_count = |
833 | initial_link_setting.lane_count; |
834 | } |
835 | } |
836 | } |
837 | return false; |
838 | } |
839 | |
840 | /* if optimize edp link is supported */ |
841 | memset(&initial_link_setting, 0, sizeof(initial_link_setting)); |
842 | initial_link_setting.lane_count = LANE_COUNT_ONE; |
843 | initial_link_setting.link_rate = link->dpcd_caps.edp_supported_link_rates[0]; |
844 | initial_link_setting.link_spread = LINK_SPREAD_DISABLED; |
845 | initial_link_setting.use_link_rate_set = true; |
846 | initial_link_setting.link_rate_set = 0; |
847 | current_link_setting = initial_link_setting; |
848 | |
849 | /* search for the minimum link setting that: |
850 | * 1. is supported according to the link training result |
851 | * 2. could support the b/w requested by the timing |
852 | */ |
853 | while (current_link_setting.link_rate <= |
854 | max_link_rate) { |
855 | link_bw = dp_link_bandwidth_kbps( |
856 | link, |
857 | link_settings: ¤t_link_setting); |
858 | if (req_bw <= link_bw) { |
859 | *link_setting = current_link_setting; |
860 | return true; |
861 | } |
862 | if (policy) { |
863 | /* minimize lane */ |
864 | if (current_link_setting.link_rate_set < |
865 | link->dpcd_caps.edp_supported_link_rates_count |
866 | && current_link_setting.link_rate < max_link_rate) { |
867 | current_link_setting.link_rate_set++; |
868 | current_link_setting.link_rate = |
869 | link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set]; |
870 | } else { |
871 | if (current_link_setting.lane_count < link->verified_link_cap.lane_count) { |
872 | current_link_setting.lane_count = |
873 | increase_lane_count( |
874 | lane_count: current_link_setting.lane_count); |
875 | current_link_setting.link_rate_set = initial_link_setting.link_rate_set; |
876 | current_link_setting.link_rate = |
877 | link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set]; |
878 | } else |
879 | break; |
880 | } |
881 | } else { |
882 | /* minimize link rate */ |
883 | if (current_link_setting.lane_count < |
884 | link->verified_link_cap.lane_count) { |
885 | current_link_setting.lane_count = |
886 | increase_lane_count( |
887 | lane_count: current_link_setting.lane_count); |
888 | } else { |
889 | if (current_link_setting.link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) { |
890 | current_link_setting.link_rate_set++; |
891 | current_link_setting.link_rate = |
892 | link->dpcd_caps.edp_supported_link_rates[current_link_setting.link_rate_set]; |
893 | current_link_setting.lane_count = |
894 | initial_link_setting.lane_count; |
895 | } else |
896 | break; |
897 | } |
898 | } |
899 | } |
900 | return false; |
901 | } |
902 | |
903 | static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting) |
904 | { |
905 | *link_setting = link->verified_link_cap; |
906 | return true; |
907 | } |
908 | |
909 | bool link_decide_link_settings(struct dc_stream_state *stream, |
910 | struct dc_link_settings *link_setting) |
911 | { |
912 | struct dc_link *link = stream->link; |
913 | uint32_t req_bw = dc_bandwidth_in_kbps_from_timing(timing: &stream->timing, link_encoding: dc_link_get_highest_encoding_format(link)); |
914 | |
915 | memset(link_setting, 0, sizeof(*link_setting)); |
916 | |
917 | /* if preferred is specified through AMDDP, use it, if it's enough |
918 | * to drive the mode |
919 | */ |
920 | if (link->preferred_link_setting.lane_count != |
921 | LANE_COUNT_UNKNOWN && |
922 | link->preferred_link_setting.link_rate != |
923 | LINK_RATE_UNKNOWN) { |
924 | *link_setting = link->preferred_link_setting; |
925 | return true; |
926 | } |
927 | |
928 | /* MST doesn't perform link training for now |
929 | * TODO: add MST specific link training routine |
930 | */ |
931 | if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { |
932 | decide_mst_link_settings(link, link_setting); |
933 | } else if (link->connector_signal == SIGNAL_TYPE_EDP) { |
934 | /* enable edp link optimization for DSC eDP case */ |
935 | if (stream->timing.flags.DSC) { |
936 | enum dc_link_rate max_link_rate = LINK_RATE_UNKNOWN; |
937 | |
938 | if (link->panel_config.dsc.force_dsc_edp_policy) { |
939 | /* calculate link max link rate cap*/ |
940 | struct dc_link_settings tmp_link_setting; |
941 | struct dc_crtc_timing tmp_timing = stream->timing; |
942 | uint32_t orig_req_bw; |
943 | |
944 | tmp_link_setting.link_rate = LINK_RATE_UNKNOWN; |
945 | tmp_timing.flags.DSC = 0; |
946 | orig_req_bw = dc_bandwidth_in_kbps_from_timing(timing: &tmp_timing, |
947 | link_encoding: dc_link_get_highest_encoding_format(link)); |
948 | edp_decide_link_settings(link, link_setting: &tmp_link_setting, req_bw: orig_req_bw); |
949 | max_link_rate = tmp_link_setting.link_rate; |
950 | } |
951 | decide_edp_link_settings_with_dsc(link, link_setting, req_bw, max_link_rate); |
952 | } else { |
953 | edp_decide_link_settings(link, link_setting, req_bw); |
954 | } |
955 | } else { |
956 | decide_dp_link_settings(link, link_setting, req_bw); |
957 | } |
958 | |
959 | return link_setting->lane_count != LANE_COUNT_UNKNOWN && |
960 | link_setting->link_rate != LINK_RATE_UNKNOWN; |
961 | } |
962 | |
963 | enum dp_link_encoding link_dp_get_encoding_format(const struct dc_link_settings *link_settings) |
964 | { |
965 | if ((link_settings->link_rate >= LINK_RATE_LOW) && |
966 | (link_settings->link_rate <= LINK_RATE_HIGH3)) |
967 | return DP_8b_10b_ENCODING; |
968 | else if ((link_settings->link_rate >= LINK_RATE_UHBR10) && |
969 | (link_settings->link_rate <= LINK_RATE_UHBR20)) |
970 | return DP_128b_132b_ENCODING; |
971 | return DP_UNKNOWN_ENCODING; |
972 | } |
973 | |
974 | enum dp_link_encoding mst_decide_link_encoding_format(const struct dc_link *link) |
975 | { |
976 | struct dc_link_settings link_settings = {0}; |
977 | |
978 | if (!dc_is_dp_signal(signal: link->connector_signal)) |
979 | return DP_UNKNOWN_ENCODING; |
980 | |
981 | if (link->preferred_link_setting.lane_count != |
982 | LANE_COUNT_UNKNOWN && |
983 | link->preferred_link_setting.link_rate != |
984 | LINK_RATE_UNKNOWN) { |
985 | link_settings = link->preferred_link_setting; |
986 | } else { |
987 | decide_mst_link_settings(link, link_setting: &link_settings); |
988 | } |
989 | |
990 | return link_dp_get_encoding_format(link_settings: &link_settings); |
991 | } |
992 | |
993 | static void read_dp_device_vendor_id(struct dc_link *link) |
994 | { |
995 | struct dp_device_vendor_id dp_id; |
996 | |
997 | /* read IEEE branch device id */ |
998 | core_link_read_dpcd( |
999 | link, |
1000 | DP_BRANCH_OUI, |
1001 | data: (uint8_t *)&dp_id, |
1002 | size: sizeof(dp_id)); |
1003 | |
1004 | link->dpcd_caps.branch_dev_id = |
1005 | (dp_id.ieee_oui[0] << 16) + |
1006 | (dp_id.ieee_oui[1] << 8) + |
1007 | dp_id.ieee_oui[2]; |
1008 | |
1009 | memmove( |
1010 | link->dpcd_caps.branch_dev_name, |
1011 | dp_id.ieee_device_id, |
1012 | sizeof(dp_id.ieee_device_id)); |
1013 | } |
1014 | |
1015 | static enum dc_status wake_up_aux_channel(struct dc_link *link) |
1016 | { |
1017 | enum dc_status status = DC_ERROR_UNEXPECTED; |
1018 | uint32_t aux_channel_retry_cnt = 0; |
1019 | uint8_t dpcd_power_state = '\0'; |
1020 | |
1021 | while (status != DC_OK && aux_channel_retry_cnt < 10) { |
1022 | status = core_link_read_dpcd(link, DP_SET_POWER, |
1023 | data: &dpcd_power_state, size: sizeof(dpcd_power_state)); |
1024 | |
1025 | /* Delay 1 ms if AUX CH is in power down state. Based on spec |
1026 | * section 2.3.1.2, if AUX CH may be powered down due to |
1027 | * write to DPCD 600h = 2. Sink AUX CH is monitoring differential |
1028 | * signal and may need up to 1 ms before being able to reply. |
1029 | */ |
1030 | if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) { |
1031 | fsleep(usecs: 1000); |
1032 | aux_channel_retry_cnt++; |
1033 | } |
1034 | } |
1035 | |
1036 | if (status != DC_OK) { |
1037 | dpcd_power_state = DP_SET_POWER_D0; |
1038 | status = core_link_write_dpcd( |
1039 | link, |
1040 | DP_SET_POWER, |
1041 | data: &dpcd_power_state, |
1042 | size: sizeof(dpcd_power_state)); |
1043 | |
1044 | dpcd_power_state = DP_SET_POWER_D3; |
1045 | status = core_link_write_dpcd( |
1046 | link, |
1047 | DP_SET_POWER, |
1048 | data: &dpcd_power_state, |
1049 | size: sizeof(dpcd_power_state)); |
1050 | DC_LOG_DC("%s: Failed to power up sink\n" , __func__); |
1051 | return DC_ERROR_UNEXPECTED; |
1052 | } |
1053 | |
1054 | return DC_OK; |
1055 | } |
1056 | |
1057 | static void get_active_converter_info( |
1058 | uint8_t data, struct dc_link *link) |
1059 | { |
1060 | union dp_downstream_port_present ds_port = { .byte = data }; |
1061 | memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps)); |
1062 | |
1063 | /* decode converter info*/ |
1064 | if (!ds_port.fields.PORT_PRESENT) { |
1065 | link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; |
1066 | set_dongle_type(ddc: link->ddc, |
1067 | dongle_type: link->dpcd_caps.dongle_type); |
1068 | link->dpcd_caps.is_branch_dev = false; |
1069 | return; |
1070 | } |
1071 | |
1072 | /* DPCD 0x5 bit 0 = 1, it indicate it's branch device */ |
1073 | link->dpcd_caps.is_branch_dev = ds_port.fields.PORT_PRESENT; |
1074 | |
1075 | switch (ds_port.fields.PORT_TYPE) { |
1076 | case DOWNSTREAM_VGA: |
1077 | link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_VGA_CONVERTER; |
1078 | break; |
1079 | case DOWNSTREAM_DVI_HDMI_DP_PLUS_PLUS: |
1080 | /* At this point we don't know is it DVI or HDMI or DP++, |
1081 | * assume DVI.*/ |
1082 | link->dpcd_caps.dongle_type = DISPLAY_DONGLE_DP_DVI_CONVERTER; |
1083 | break; |
1084 | default: |
1085 | link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; |
1086 | break; |
1087 | } |
1088 | |
1089 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_11) { |
1090 | uint8_t det_caps[16]; /* CTS 4.2.2.7 expects source to read Detailed Capabilities Info : 00080h-0008F.*/ |
1091 | union dwnstream_port_caps_byte0 *port_caps = |
1092 | (union dwnstream_port_caps_byte0 *)det_caps; |
1093 | if (core_link_read_dpcd(link, DP_DOWNSTREAM_PORT_0, |
1094 | data: det_caps, size: sizeof(det_caps)) == DC_OK) { |
1095 | |
1096 | switch (port_caps->bits.DWN_STRM_PORTX_TYPE) { |
1097 | /*Handle DP case as DONGLE_NONE*/ |
1098 | case DOWN_STREAM_DETAILED_DP: |
1099 | link->dpcd_caps.dongle_type = DISPLAY_DONGLE_NONE; |
1100 | break; |
1101 | case DOWN_STREAM_DETAILED_VGA: |
1102 | link->dpcd_caps.dongle_type = |
1103 | DISPLAY_DONGLE_DP_VGA_CONVERTER; |
1104 | break; |
1105 | case DOWN_STREAM_DETAILED_DVI: |
1106 | link->dpcd_caps.dongle_type = |
1107 | DISPLAY_DONGLE_DP_DVI_CONVERTER; |
1108 | break; |
1109 | case DOWN_STREAM_DETAILED_HDMI: |
1110 | case DOWN_STREAM_DETAILED_DP_PLUS_PLUS: |
1111 | /*Handle DP++ active converter case, process DP++ case as HDMI case according DP1.4 spec*/ |
1112 | link->dpcd_caps.dongle_type = |
1113 | DISPLAY_DONGLE_DP_HDMI_CONVERTER; |
1114 | |
1115 | link->dpcd_caps.dongle_caps.dongle_type = link->dpcd_caps.dongle_type; |
1116 | if (ds_port.fields.DETAILED_CAPS) { |
1117 | |
1118 | union dwnstream_port_caps_byte3_hdmi |
1119 | hdmi_caps = {.raw = det_caps[3] }; |
1120 | union dwnstream_port_caps_byte2 |
1121 | hdmi_color_caps = {.raw = det_caps[2] }; |
1122 | link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz = |
1123 | det_caps[1] * 2500; |
1124 | |
1125 | link->dpcd_caps.dongle_caps.is_dp_hdmi_s3d_converter = |
1126 | hdmi_caps.bits.FRAME_SEQ_TO_FRAME_PACK; |
1127 | /*YCBCR capability only for HDMI case*/ |
1128 | if (port_caps->bits.DWN_STRM_PORTX_TYPE |
1129 | == DOWN_STREAM_DETAILED_HDMI) { |
1130 | link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_pass_through = |
1131 | hdmi_caps.bits.YCrCr422_PASS_THROUGH; |
1132 | link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_pass_through = |
1133 | hdmi_caps.bits.YCrCr420_PASS_THROUGH; |
1134 | link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr422_converter = |
1135 | hdmi_caps.bits.YCrCr422_CONVERSION; |
1136 | link->dpcd_caps.dongle_caps.is_dp_hdmi_ycbcr420_converter = |
1137 | hdmi_caps.bits.YCrCr420_CONVERSION; |
1138 | } |
1139 | |
1140 | link->dpcd_caps.dongle_caps.dp_hdmi_max_bpc = |
1141 | translate_dpcd_max_bpc( |
1142 | bpc: hdmi_color_caps.bits.MAX_BITS_PER_COLOR_COMPONENT); |
1143 | |
1144 | if (link->dc->caps.dp_hdmi21_pcon_support) { |
1145 | union hdmi_encoded_link_bw hdmi_encoded_link_bw; |
1146 | |
1147 | link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = |
1148 | link_bw_kbps_from_raw_frl_link_rate_data( |
1149 | bw: hdmi_color_caps.bits.MAX_ENCODED_LINK_BW_SUPPORT); |
1150 | |
1151 | // Intersect reported max link bw support with the supported link rate post FRL link training |
1152 | if (core_link_read_dpcd(link, DP_PCON_HDMI_POST_FRL_STATUS, |
1153 | data: &hdmi_encoded_link_bw.raw, size: sizeof(hdmi_encoded_link_bw)) == DC_OK) { |
1154 | link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps = intersect_frl_link_bw_support( |
1155 | max_supported_frl_bw_in_kbps: link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps, |
1156 | hdmi_encoded_link_bw); |
1157 | } |
1158 | |
1159 | if (link->dpcd_caps.dongle_caps.dp_hdmi_frl_max_link_bw_in_kbps > 0) |
1160 | link->dpcd_caps.dongle_caps.extendedCapValid = true; |
1161 | } |
1162 | |
1163 | if (link->dpcd_caps.dongle_caps.dp_hdmi_max_pixel_clk_in_khz != 0) |
1164 | link->dpcd_caps.dongle_caps.extendedCapValid = true; |
1165 | } |
1166 | |
1167 | break; |
1168 | } |
1169 | } |
1170 | } |
1171 | |
1172 | set_dongle_type(ddc: link->ddc, dongle_type: link->dpcd_caps.dongle_type); |
1173 | |
1174 | { |
1175 | struct dp_sink_hw_fw_revision dp_hw_fw_revision; |
1176 | |
1177 | core_link_read_dpcd( |
1178 | link, |
1179 | DP_BRANCH_REVISION_START, |
1180 | data: (uint8_t *)&dp_hw_fw_revision, |
1181 | size: sizeof(dp_hw_fw_revision)); |
1182 | |
1183 | link->dpcd_caps.branch_hw_revision = |
1184 | dp_hw_fw_revision.ieee_hw_rev; |
1185 | |
1186 | memmove( |
1187 | link->dpcd_caps.branch_fw_revision, |
1188 | dp_hw_fw_revision.ieee_fw_rev, |
1189 | sizeof(dp_hw_fw_revision.ieee_fw_rev)); |
1190 | } |
1191 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14 && |
1192 | link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) { |
1193 | union dp_dfp_cap_ext dfp_cap_ext; |
1194 | memset(&dfp_cap_ext, '\0', sizeof (dfp_cap_ext)); |
1195 | core_link_read_dpcd( |
1196 | link, |
1197 | DP_DFP_CAPABILITY_EXTENSION_SUPPORT, |
1198 | data: dfp_cap_ext.raw, |
1199 | size: sizeof(dfp_cap_ext.raw)); |
1200 | link->dpcd_caps.dongle_caps.dfp_cap_ext.supported = dfp_cap_ext.fields.supported; |
1201 | link->dpcd_caps.dongle_caps.dfp_cap_ext.max_pixel_rate_in_mps = |
1202 | dfp_cap_ext.fields.max_pixel_rate_in_mps[0] + |
1203 | (dfp_cap_ext.fields.max_pixel_rate_in_mps[1] << 8); |
1204 | link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_h_active_width = |
1205 | dfp_cap_ext.fields.max_video_h_active_width[0] + |
1206 | (dfp_cap_ext.fields.max_video_h_active_width[1] << 8); |
1207 | link->dpcd_caps.dongle_caps.dfp_cap_ext.max_video_v_active_height = |
1208 | dfp_cap_ext.fields.max_video_v_active_height[0] + |
1209 | (dfp_cap_ext.fields.max_video_v_active_height[1] << 8); |
1210 | link->dpcd_caps.dongle_caps.dfp_cap_ext.encoding_format_caps = |
1211 | dfp_cap_ext.fields.encoding_format_caps; |
1212 | link->dpcd_caps.dongle_caps.dfp_cap_ext.rgb_color_depth_caps = |
1213 | dfp_cap_ext.fields.rgb_color_depth_caps; |
1214 | link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr444_color_depth_caps = |
1215 | dfp_cap_ext.fields.ycbcr444_color_depth_caps; |
1216 | link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr422_color_depth_caps = |
1217 | dfp_cap_ext.fields.ycbcr422_color_depth_caps; |
1218 | link->dpcd_caps.dongle_caps.dfp_cap_ext.ycbcr420_color_depth_caps = |
1219 | dfp_cap_ext.fields.ycbcr420_color_depth_caps; |
1220 | DC_LOG_DP2("DFP capability extension is read at link %d" , link->link_index); |
1221 | DC_LOG_DP2("\tdfp_cap_ext.supported = %s" , link->dpcd_caps.dongle_caps.dfp_cap_ext.supported ? "true" : "false" ); |
1222 | 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); |
1223 | 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); |
1224 | 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); |
1225 | } |
1226 | } |
1227 | |
1228 | static void apply_usbc_combo_phy_reset_wa(struct dc_link *link, |
1229 | struct dc_link_settings *link_settings) |
1230 | { |
1231 | /* Temporary Renoir-specific workaround PHY will sometimes be in bad |
1232 | * state on hotplugging display from certain USB-C dongle, so add extra |
1233 | * cycle of enabling and disabling the PHY before first link training. |
1234 | */ |
1235 | struct link_resource link_res = {0}; |
1236 | enum clock_source_id dp_cs_id = get_clock_source_id(link); |
1237 | |
1238 | dp_enable_link_phy(link, link_res: &link_res, signal: link->connector_signal, |
1239 | clock_source: dp_cs_id, link_settings); |
1240 | dp_disable_link_phy(link, link_res: &link_res, signal: link->connector_signal); |
1241 | } |
1242 | |
1243 | bool dp_overwrite_extended_receiver_cap(struct dc_link *link) |
1244 | { |
1245 | uint8_t dpcd_data[16]; |
1246 | uint32_t read_dpcd_retry_cnt = 3; |
1247 | enum dc_status status = DC_ERROR_UNEXPECTED; |
1248 | union dp_downstream_port_present ds_port = { 0 }; |
1249 | union down_stream_port_count down_strm_port_count; |
1250 | union edp_configuration_cap edp_config_cap; |
1251 | |
1252 | int i; |
1253 | |
1254 | for (i = 0; i < read_dpcd_retry_cnt; i++) { |
1255 | status = core_link_read_dpcd( |
1256 | link, |
1257 | DP_DPCD_REV, |
1258 | data: dpcd_data, |
1259 | size: sizeof(dpcd_data)); |
1260 | if (status == DC_OK) |
1261 | break; |
1262 | } |
1263 | |
1264 | link->dpcd_caps.dpcd_rev.raw = |
1265 | dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; |
1266 | |
1267 | if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0) |
1268 | return false; |
1269 | |
1270 | ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT - |
1271 | DP_DPCD_REV]; |
1272 | |
1273 | get_active_converter_info(data: ds_port.byte, link); |
1274 | |
1275 | down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT - |
1276 | DP_DPCD_REV]; |
1277 | |
1278 | link->dpcd_caps.allow_invalid_MSA_timing_param = |
1279 | down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM; |
1280 | |
1281 | link->dpcd_caps.max_ln_count.raw = dpcd_data[ |
1282 | DP_MAX_LANE_COUNT - DP_DPCD_REV]; |
1283 | |
1284 | link->dpcd_caps.max_down_spread.raw = dpcd_data[ |
1285 | DP_MAX_DOWNSPREAD - DP_DPCD_REV]; |
1286 | |
1287 | link->reported_link_cap.lane_count = |
1288 | link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; |
1289 | link->reported_link_cap.link_rate = dpcd_data[ |
1290 | DP_MAX_LINK_RATE - DP_DPCD_REV]; |
1291 | link->reported_link_cap.link_spread = |
1292 | link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? |
1293 | LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; |
1294 | |
1295 | edp_config_cap.raw = dpcd_data[ |
1296 | DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV]; |
1297 | link->dpcd_caps.panel_mode_edp = |
1298 | edp_config_cap.bits.ALT_SCRAMBLER_RESET; |
1299 | link->dpcd_caps.dpcd_display_control_capable = |
1300 | edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE; |
1301 | |
1302 | return true; |
1303 | } |
1304 | |
1305 | void dpcd_set_source_specific_data(struct dc_link *link) |
1306 | { |
1307 | if (!link->dc->vendor_signature.is_valid) { |
1308 | enum dc_status __maybe_unused result_write_min_hblank = DC_NOT_SUPPORTED; |
1309 | struct dpcd_amd_signature amd_signature = {0}; |
1310 | struct dpcd_amd_device_id amd_device_id = {0}; |
1311 | |
1312 | amd_device_id.device_id_byte1 = |
1313 | (uint8_t)(link->ctx->asic_id.chip_id); |
1314 | amd_device_id.device_id_byte2 = |
1315 | (uint8_t)(link->ctx->asic_id.chip_id >> 8); |
1316 | amd_device_id.dce_version = |
1317 | (uint8_t)(link->ctx->dce_version); |
1318 | amd_device_id.dal_version_byte1 = 0x0; // needed? where to get? |
1319 | amd_device_id.dal_version_byte2 = 0x0; // needed? where to get? |
1320 | |
1321 | core_link_read_dpcd(link, DP_SOURCE_OUI, |
1322 | data: (uint8_t *)(&amd_signature), |
1323 | size: sizeof(amd_signature)); |
1324 | |
1325 | if (!((amd_signature.AMD_IEEE_TxSignature_byte1 == 0x0) && |
1326 | (amd_signature.AMD_IEEE_TxSignature_byte2 == 0x0) && |
1327 | (amd_signature.AMD_IEEE_TxSignature_byte3 == 0x1A))) { |
1328 | |
1329 | amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0; |
1330 | amd_signature.AMD_IEEE_TxSignature_byte2 = 0x0; |
1331 | amd_signature.AMD_IEEE_TxSignature_byte3 = 0x1A; |
1332 | |
1333 | core_link_write_dpcd(link, DP_SOURCE_OUI, |
1334 | data: (uint8_t *)(&amd_signature), |
1335 | size: sizeof(amd_signature)); |
1336 | } |
1337 | |
1338 | core_link_write_dpcd(link, DP_SOURCE_OUI+0x03, |
1339 | data: (uint8_t *)(&amd_device_id), |
1340 | size: sizeof(amd_device_id)); |
1341 | |
1342 | if (link->ctx->dce_version >= DCN_VERSION_2_0 && |
1343 | link->dc->caps.min_horizontal_blanking_period != 0) { |
1344 | |
1345 | uint8_t hblank_size = (uint8_t)link->dc->caps.min_horizontal_blanking_period; |
1346 | |
1347 | result_write_min_hblank = core_link_write_dpcd(link, |
1348 | DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, data: (uint8_t *)(&hblank_size), |
1349 | size: sizeof(hblank_size)); |
1350 | } |
1351 | DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, |
1352 | WPP_BIT_FLAG_DC_DETECTION_DP_CAPS, |
1353 | "result=%u link_index=%u enum dce_version=%d DPCD=0x%04X min_hblank=%u branch_dev_id=0x%x branch_dev_name='%c%c%c%c%c%c'" , |
1354 | result_write_min_hblank, |
1355 | link->link_index, |
1356 | link->ctx->dce_version, |
1357 | DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, |
1358 | link->dc->caps.min_horizontal_blanking_period, |
1359 | link->dpcd_caps.branch_dev_id, |
1360 | link->dpcd_caps.branch_dev_name[0], |
1361 | link->dpcd_caps.branch_dev_name[1], |
1362 | link->dpcd_caps.branch_dev_name[2], |
1363 | link->dpcd_caps.branch_dev_name[3], |
1364 | link->dpcd_caps.branch_dev_name[4], |
1365 | link->dpcd_caps.branch_dev_name[5]); |
1366 | } else { |
1367 | core_link_write_dpcd(link, DP_SOURCE_OUI, |
1368 | data: link->dc->vendor_signature.data.raw, |
1369 | size: sizeof(link->dc->vendor_signature.data.raw)); |
1370 | } |
1371 | } |
1372 | |
1373 | void dpcd_write_cable_id_to_dprx(struct dc_link *link) |
1374 | { |
1375 | if (!link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED || |
1376 | link->dpcd_caps.cable_id.raw == 0 || |
1377 | link->dprx_states.cable_id_written) |
1378 | return; |
1379 | |
1380 | core_link_write_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPTX, |
1381 | data: &link->dpcd_caps.cable_id.raw, |
1382 | size: sizeof(link->dpcd_caps.cable_id.raw)); |
1383 | |
1384 | link->dprx_states.cable_id_written = 1; |
1385 | } |
1386 | |
1387 | static bool get_usbc_cable_id(struct dc_link *link, union dp_cable_id *cable_id) |
1388 | { |
1389 | union dmub_rb_cmd cmd; |
1390 | |
1391 | if (!link->ctx->dmub_srv || |
1392 | link->ep_type != DISPLAY_ENDPOINT_PHY || |
1393 | link->link_enc->features.flags.bits.DP_IS_USB_C == 0) |
1394 | return false; |
1395 | |
1396 | memset(&cmd, 0, sizeof(cmd)); |
1397 | cmd.cable_id.header.type = DMUB_CMD_GET_USBC_CABLE_ID; |
1398 | cmd.cable_id.header.payload_bytes = sizeof(cmd.cable_id.data); |
1399 | cmd.cable_id.data.input.phy_inst = resource_transmitter_to_phy_idx( |
1400 | dc: link->dc, transmitter: link->link_enc->transmitter); |
1401 | if (dc_wake_and_execute_dmub_cmd(ctx: link->dc->ctx, cmd: &cmd, wait_type: DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY) && |
1402 | cmd.cable_id.header.ret_status == 1) { |
1403 | cable_id->raw = cmd.cable_id.data.output_raw; |
1404 | DC_LOG_DC("usbc_cable_id = %d.\n" , cable_id->raw); |
1405 | } |
1406 | return cmd.cable_id.header.ret_status == 1; |
1407 | } |
1408 | |
1409 | static void retrieve_cable_id(struct dc_link *link) |
1410 | { |
1411 | union dp_cable_id usbc_cable_id; |
1412 | |
1413 | link->dpcd_caps.cable_id.raw = 0; |
1414 | core_link_read_dpcd(link, DP_CABLE_ATTRIBUTES_UPDATED_BY_DPRX, |
1415 | data: &link->dpcd_caps.cable_id.raw, size: sizeof(uint8_t)); |
1416 | |
1417 | if (get_usbc_cable_id(link, cable_id: &usbc_cable_id)) |
1418 | link->dpcd_caps.cable_id = intersect_cable_id( |
1419 | a: &link->dpcd_caps.cable_id, b: &usbc_cable_id); |
1420 | } |
1421 | |
1422 | bool read_is_mst_supported(struct dc_link *link) |
1423 | { |
1424 | bool mst = false; |
1425 | enum dc_status st = DC_OK; |
1426 | union dpcd_rev rev; |
1427 | union mstm_cap cap; |
1428 | |
1429 | if (link->preferred_training_settings.mst_enable && |
1430 | *link->preferred_training_settings.mst_enable == false) { |
1431 | return false; |
1432 | } |
1433 | |
1434 | rev.raw = 0; |
1435 | cap.raw = 0; |
1436 | |
1437 | st = core_link_read_dpcd(link, DP_DPCD_REV, data: &rev.raw, |
1438 | size: sizeof(rev)); |
1439 | |
1440 | if (st == DC_OK && rev.raw >= DPCD_REV_12) { |
1441 | |
1442 | st = core_link_read_dpcd(link, DP_MSTM_CAP, |
1443 | data: &cap.raw, size: sizeof(cap)); |
1444 | if (st == DC_OK && cap.bits.MST_CAP == 1) |
1445 | mst = true; |
1446 | } |
1447 | return mst; |
1448 | |
1449 | } |
1450 | |
1451 | /* Read additional sink caps defined in source specific DPCD area |
1452 | * This function currently only reads from SinkCapability address (DP_SOURCE_SINK_CAP) |
1453 | * TODO: Add FS caps and read from DP_SOURCE_SINK_FS_CAP as well |
1454 | */ |
1455 | static bool dpcd_read_sink_ext_caps(struct dc_link *link) |
1456 | { |
1457 | uint8_t dpcd_data = 0; |
1458 | uint8_t edp_general_cap2 = 0; |
1459 | |
1460 | if (!link) |
1461 | return false; |
1462 | |
1463 | if (core_link_read_dpcd(link, DP_SOURCE_SINK_CAP, data: &dpcd_data, size: 1) != DC_OK) |
1464 | return false; |
1465 | |
1466 | link->dpcd_sink_ext_caps.raw = dpcd_data; |
1467 | |
1468 | if (core_link_read_dpcd(link, DP_EDP_GENERAL_CAP_2, data: &edp_general_cap2, size: 1) != DC_OK) |
1469 | return false; |
1470 | |
1471 | link->dpcd_caps.panel_luminance_control = (edp_general_cap2 & DP_EDP_PANEL_LUMINANCE_CONTROL_CAPABLE) != 0; |
1472 | |
1473 | return true; |
1474 | } |
1475 | |
1476 | enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link) |
1477 | { |
1478 | uint8_t lttpr_dpcd_data[8]; |
1479 | enum dc_status status; |
1480 | bool is_lttpr_present; |
1481 | |
1482 | /* Logic to determine LTTPR support*/ |
1483 | bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware; |
1484 | |
1485 | if (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support) |
1486 | return DC_NOT_SUPPORTED; |
1487 | |
1488 | /* By reading LTTPR capability, RX assumes that we will enable |
1489 | * LTTPR extended aux timeout if LTTPR is present. |
1490 | */ |
1491 | status = core_link_read_dpcd( |
1492 | link, |
1493 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, |
1494 | data: lttpr_dpcd_data, |
1495 | size: sizeof(lttpr_dpcd_data)); |
1496 | |
1497 | link->dpcd_caps.lttpr_caps.revision.raw = |
1498 | lttpr_dpcd_data[DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV - |
1499 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
1500 | |
1501 | link->dpcd_caps.lttpr_caps.max_link_rate = |
1502 | lttpr_dpcd_data[DP_MAX_LINK_RATE_PHY_REPEATER - |
1503 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
1504 | |
1505 | link->dpcd_caps.lttpr_caps.phy_repeater_cnt = |
1506 | lttpr_dpcd_data[DP_PHY_REPEATER_CNT - |
1507 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
1508 | |
1509 | link->dpcd_caps.lttpr_caps.max_lane_count = |
1510 | lttpr_dpcd_data[DP_MAX_LANE_COUNT_PHY_REPEATER - |
1511 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
1512 | |
1513 | link->dpcd_caps.lttpr_caps.mode = |
1514 | lttpr_dpcd_data[DP_PHY_REPEATER_MODE - |
1515 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
1516 | |
1517 | link->dpcd_caps.lttpr_caps.max_ext_timeout = |
1518 | lttpr_dpcd_data[DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT - |
1519 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
1520 | link->dpcd_caps.lttpr_caps.main_link_channel_coding.raw = |
1521 | lttpr_dpcd_data[DP_MAIN_LINK_CHANNEL_CODING_PHY_REPEATER - |
1522 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
1523 | |
1524 | link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.raw = |
1525 | lttpr_dpcd_data[DP_PHY_REPEATER_128B132B_RATES - |
1526 | DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV]; |
1527 | |
1528 | /* If this chip cap is set, at least one retimer must exist in the chain |
1529 | * Override count to 1 if we receive a known bad count (0 or an invalid value) */ |
1530 | if ((link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) && |
1531 | (dp_parse_lttpr_repeater_count(lttpr_repeater_count: link->dpcd_caps.lttpr_caps.phy_repeater_cnt) == 0)) { |
1532 | ASSERT(0); |
1533 | link->dpcd_caps.lttpr_caps.phy_repeater_cnt = 0x80; |
1534 | DC_LOG_DC("lttpr_caps forced phy_repeater_cnt = %d\n" , link->dpcd_caps.lttpr_caps.phy_repeater_cnt); |
1535 | } |
1536 | |
1537 | /* Attempt to train in LTTPR transparent mode if repeater count exceeds 8. */ |
1538 | is_lttpr_present = dp_is_lttpr_present(link); |
1539 | |
1540 | if (is_lttpr_present) |
1541 | CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: " ); |
1542 | |
1543 | DC_LOG_DC("is_lttpr_present = %d\n" , is_lttpr_present); |
1544 | return status; |
1545 | } |
1546 | |
1547 | static bool retrieve_link_cap(struct dc_link *link) |
1548 | { |
1549 | /* DP_ADAPTER_CAP - DP_DPCD_REV + 1 == 16 and also DP_DSC_BITS_PER_PIXEL_INC - DP_DSC_SUPPORT + 1 == 16, |
1550 | * which means size 16 will be good for both of those DPCD register block reads |
1551 | */ |
1552 | uint8_t dpcd_data[16]; |
1553 | /*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST. |
1554 | */ |
1555 | uint8_t dpcd_dprx_data = '\0'; |
1556 | |
1557 | struct dp_device_vendor_id sink_id; |
1558 | union down_stream_port_count down_strm_port_count; |
1559 | union edp_configuration_cap edp_config_cap; |
1560 | union dp_downstream_port_present ds_port = { 0 }; |
1561 | enum dc_status status = DC_ERROR_UNEXPECTED; |
1562 | uint32_t read_dpcd_retry_cnt = 3; |
1563 | int i; |
1564 | struct dp_sink_hw_fw_revision dp_hw_fw_revision; |
1565 | const uint32_t post_oui_delay = 30; // 30ms |
1566 | bool is_fec_supported = false; |
1567 | bool is_dsc_basic_supported = false; |
1568 | bool is_dsc_passthrough_supported = false; |
1569 | |
1570 | memset(dpcd_data, '\0', sizeof(dpcd_data)); |
1571 | memset(&down_strm_port_count, |
1572 | '\0', sizeof(union down_stream_port_count)); |
1573 | memset(&edp_config_cap, '\0', |
1574 | sizeof(union edp_configuration_cap)); |
1575 | |
1576 | /* if extended timeout is supported in hardware, |
1577 | * default to LTTPR timeout (3.2ms) first as a W/A for DP link layer |
1578 | * CTS 4.2.1.1 regression introduced by CTS specs requirement update. |
1579 | */ |
1580 | try_to_configure_aux_timeout(ddc: link->ddc, |
1581 | LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD); |
1582 | |
1583 | status = dp_retrieve_lttpr_cap(link); |
1584 | |
1585 | if (status != DC_OK) { |
1586 | status = wake_up_aux_channel(link); |
1587 | if (status == DC_OK) |
1588 | dp_retrieve_lttpr_cap(link); |
1589 | else |
1590 | return false; |
1591 | } |
1592 | |
1593 | if (dp_is_lttpr_present(link)) |
1594 | configure_lttpr_mode_transparent(link); |
1595 | |
1596 | /* Read DP tunneling information. */ |
1597 | status = dpcd_get_tunneling_device_data(link); |
1598 | |
1599 | dpcd_set_source_specific_data(link); |
1600 | /* Sink may need to configure internals based on vendor, so allow some |
1601 | * time before proceeding with possibly vendor specific transactions |
1602 | */ |
1603 | msleep(msecs: post_oui_delay); |
1604 | |
1605 | for (i = 0; i < read_dpcd_retry_cnt; i++) { |
1606 | status = core_link_read_dpcd( |
1607 | link, |
1608 | DP_DPCD_REV, |
1609 | data: dpcd_data, |
1610 | size: sizeof(dpcd_data)); |
1611 | if (status == DC_OK) |
1612 | break; |
1613 | } |
1614 | |
1615 | |
1616 | if (status != DC_OK) { |
1617 | dm_error("%s: Read receiver caps dpcd data failed.\n" , __func__); |
1618 | return false; |
1619 | } |
1620 | |
1621 | if (!dp_is_lttpr_present(link)) |
1622 | try_to_configure_aux_timeout(ddc: link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD); |
1623 | |
1624 | |
1625 | { |
1626 | union training_aux_rd_interval aux_rd_interval; |
1627 | |
1628 | aux_rd_interval.raw = |
1629 | dpcd_data[DP_TRAINING_AUX_RD_INTERVAL]; |
1630 | |
1631 | link->dpcd_caps.ext_receiver_cap_field_present = |
1632 | aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1; |
1633 | |
1634 | if (aux_rd_interval.bits.EXT_RECEIVER_CAP_FIELD_PRESENT == 1) { |
1635 | uint8_t ext_cap_data[16]; |
1636 | |
1637 | memset(ext_cap_data, '\0', sizeof(ext_cap_data)); |
1638 | for (i = 0; i < read_dpcd_retry_cnt; i++) { |
1639 | status = core_link_read_dpcd( |
1640 | link, |
1641 | DP_DP13_DPCD_REV, |
1642 | data: ext_cap_data, |
1643 | size: sizeof(ext_cap_data)); |
1644 | if (status == DC_OK) { |
1645 | memcpy(dpcd_data, ext_cap_data, sizeof(dpcd_data)); |
1646 | break; |
1647 | } |
1648 | } |
1649 | if (status != DC_OK) |
1650 | dm_error("%s: Read extend caps data failed, use cap from dpcd 0.\n" , __func__); |
1651 | } |
1652 | } |
1653 | |
1654 | link->dpcd_caps.dpcd_rev.raw = |
1655 | dpcd_data[DP_DPCD_REV - DP_DPCD_REV]; |
1656 | |
1657 | if (link->dpcd_caps.ext_receiver_cap_field_present) { |
1658 | for (i = 0; i < read_dpcd_retry_cnt; i++) { |
1659 | status = core_link_read_dpcd( |
1660 | link, |
1661 | DP_DPRX_FEATURE_ENUMERATION_LIST, |
1662 | data: &dpcd_dprx_data, |
1663 | size: sizeof(dpcd_dprx_data)); |
1664 | if (status == DC_OK) |
1665 | break; |
1666 | } |
1667 | |
1668 | link->dpcd_caps.dprx_feature.raw = dpcd_dprx_data; |
1669 | |
1670 | if (status != DC_OK) |
1671 | dm_error("%s: Read DPRX caps data failed.\n" , __func__); |
1672 | |
1673 | /* AdaptiveSyncCapability */ |
1674 | dpcd_dprx_data = 0; |
1675 | for (i = 0; i < read_dpcd_retry_cnt; i++) { |
1676 | status = core_link_read_dpcd( |
1677 | link, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1, |
1678 | data: &dpcd_dprx_data, size: sizeof(dpcd_dprx_data)); |
1679 | if (status == DC_OK) |
1680 | break; |
1681 | } |
1682 | |
1683 | link->dpcd_caps.adaptive_sync_caps.dp_adap_sync_caps.raw = dpcd_dprx_data; |
1684 | |
1685 | if (status != DC_OK) |
1686 | dm_error("%s: Read DPRX caps data failed. Addr:%#x\n" , |
1687 | __func__, DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1); |
1688 | } |
1689 | |
1690 | else { |
1691 | link->dpcd_caps.dprx_feature.raw = 0; |
1692 | } |
1693 | |
1694 | |
1695 | /* Error condition checking... |
1696 | * It is impossible for Sink to report Max Lane Count = 0. |
1697 | * It is possible for Sink to report Max Link Rate = 0, if it is |
1698 | * an eDP device that is reporting specialized link rates in the |
1699 | * SUPPORTED_LINK_RATE table. |
1700 | */ |
1701 | if (dpcd_data[DP_MAX_LANE_COUNT - DP_DPCD_REV] == 0) |
1702 | return false; |
1703 | |
1704 | ds_port.byte = dpcd_data[DP_DOWNSTREAMPORT_PRESENT - |
1705 | DP_DPCD_REV]; |
1706 | |
1707 | read_dp_device_vendor_id(link); |
1708 | |
1709 | /* TODO - decouple raw mst capability from policy decision */ |
1710 | link->dpcd_caps.is_mst_capable = read_is_mst_supported(link); |
1711 | DC_LOG_DC("%s: MST_Support: %s\n" , __func__, str_yes_no(link->dpcd_caps.is_mst_capable)); |
1712 | |
1713 | get_active_converter_info(data: ds_port.byte, link); |
1714 | |
1715 | dp_wa_power_up_0010FA(link, dpcd_data, length: sizeof(dpcd_data)); |
1716 | |
1717 | down_strm_port_count.raw = dpcd_data[DP_DOWN_STREAM_PORT_COUNT - |
1718 | DP_DPCD_REV]; |
1719 | |
1720 | link->dpcd_caps.allow_invalid_MSA_timing_param = |
1721 | down_strm_port_count.bits.IGNORE_MSA_TIMING_PARAM; |
1722 | |
1723 | link->dpcd_caps.max_ln_count.raw = dpcd_data[ |
1724 | DP_MAX_LANE_COUNT - DP_DPCD_REV]; |
1725 | |
1726 | link->dpcd_caps.max_down_spread.raw = dpcd_data[ |
1727 | DP_MAX_DOWNSPREAD - DP_DPCD_REV]; |
1728 | |
1729 | link->reported_link_cap.lane_count = |
1730 | link->dpcd_caps.max_ln_count.bits.MAX_LANE_COUNT; |
1731 | link->reported_link_cap.link_rate = get_link_rate_from_max_link_bw( |
1732 | max_link_bw: dpcd_data[DP_MAX_LINK_RATE - DP_DPCD_REV]); |
1733 | link->reported_link_cap.link_spread = |
1734 | link->dpcd_caps.max_down_spread.bits.MAX_DOWN_SPREAD ? |
1735 | LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED; |
1736 | |
1737 | edp_config_cap.raw = dpcd_data[ |
1738 | DP_EDP_CONFIGURATION_CAP - DP_DPCD_REV]; |
1739 | link->dpcd_caps.panel_mode_edp = |
1740 | edp_config_cap.bits.ALT_SCRAMBLER_RESET; |
1741 | link->dpcd_caps.dpcd_display_control_capable = |
1742 | edp_config_cap.bits.DPCD_DISPLAY_CONTROL_CAPABLE; |
1743 | link->dpcd_caps.channel_coding_cap.raw = |
1744 | dpcd_data[DP_MAIN_LINK_CHANNEL_CODING - DP_DPCD_REV]; |
1745 | link->test_pattern_enabled = false; |
1746 | link->compliance_test_state.raw = 0; |
1747 | |
1748 | /* read sink count */ |
1749 | core_link_read_dpcd(link, |
1750 | DP_SINK_COUNT, |
1751 | data: &link->dpcd_caps.sink_count.raw, |
1752 | size: sizeof(link->dpcd_caps.sink_count.raw)); |
1753 | |
1754 | /* read sink ieee oui */ |
1755 | core_link_read_dpcd(link, |
1756 | DP_SINK_OUI, |
1757 | data: (uint8_t *)(&sink_id), |
1758 | size: sizeof(sink_id)); |
1759 | |
1760 | link->dpcd_caps.sink_dev_id = |
1761 | (sink_id.ieee_oui[0] << 16) + |
1762 | (sink_id.ieee_oui[1] << 8) + |
1763 | (sink_id.ieee_oui[2]); |
1764 | |
1765 | memmove( |
1766 | link->dpcd_caps.sink_dev_id_str, |
1767 | sink_id.ieee_device_id, |
1768 | sizeof(sink_id.ieee_device_id)); |
1769 | |
1770 | core_link_read_dpcd( |
1771 | link, |
1772 | DP_SINK_HW_REVISION_START, |
1773 | data: (uint8_t *)&dp_hw_fw_revision, |
1774 | size: sizeof(dp_hw_fw_revision)); |
1775 | |
1776 | link->dpcd_caps.sink_hw_revision = |
1777 | dp_hw_fw_revision.ieee_hw_rev; |
1778 | |
1779 | memmove( |
1780 | link->dpcd_caps.sink_fw_revision, |
1781 | dp_hw_fw_revision.ieee_fw_rev, |
1782 | sizeof(dp_hw_fw_revision.ieee_fw_rev)); |
1783 | |
1784 | /* Quirk for Retina panels: wrong DP_MAX_LINK_RATE */ |
1785 | { |
1786 | uint8_t str_mbp_2018[] = { 101, 68, 21, 103, 98, 97 }; |
1787 | uint8_t fwrev_mbp_2018[] = { 7, 4 }; |
1788 | uint8_t fwrev_mbp_2018_vega[] = { 8, 4 }; |
1789 | |
1790 | /* We also check for the firmware revision as 16,1 models have an |
1791 | * identical device id and are incorrectly quirked otherwise. |
1792 | */ |
1793 | if ((link->dpcd_caps.sink_dev_id == 0x0010fa) && |
1794 | !memcmp(p: link->dpcd_caps.sink_dev_id_str, q: str_mbp_2018, |
1795 | size: sizeof(str_mbp_2018)) && |
1796 | (!memcmp(p: link->dpcd_caps.sink_fw_revision, q: fwrev_mbp_2018, |
1797 | size: sizeof(fwrev_mbp_2018)) || |
1798 | !memcmp(p: link->dpcd_caps.sink_fw_revision, q: fwrev_mbp_2018_vega, |
1799 | size: sizeof(fwrev_mbp_2018_vega)))) { |
1800 | link->reported_link_cap.link_rate = LINK_RATE_RBR2; |
1801 | } |
1802 | } |
1803 | |
1804 | memset(&link->dpcd_caps.dsc_caps, '\0', |
1805 | sizeof(link->dpcd_caps.dsc_caps)); |
1806 | memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap)); |
1807 | /* Read DSC and FEC sink capabilities if DP revision is 1.4 and up */ |
1808 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_14) { |
1809 | status = core_link_read_dpcd( |
1810 | link, |
1811 | DP_FEC_CAPABILITY, |
1812 | data: &link->dpcd_caps.fec_cap.raw, |
1813 | size: sizeof(link->dpcd_caps.fec_cap.raw)); |
1814 | status = core_link_read_dpcd( |
1815 | link, |
1816 | DP_DSC_SUPPORT, |
1817 | data: link->dpcd_caps.dsc_caps.dsc_basic_caps.raw, |
1818 | size: sizeof(link->dpcd_caps.dsc_caps.dsc_basic_caps.raw)); |
1819 | if (status == DC_OK) { |
1820 | is_fec_supported = link->dpcd_caps.fec_cap.bits.FEC_CAPABLE; |
1821 | is_dsc_basic_supported = link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT; |
1822 | is_dsc_passthrough_supported = link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT; |
1823 | DC_LOG_DC("%s: FEC_Sink_Support: %s\n" , __func__, |
1824 | str_yes_no(is_fec_supported)); |
1825 | DC_LOG_DC("%s: DSC_Basic_Sink_Support: %s\n" , __func__, |
1826 | str_yes_no(is_dsc_basic_supported)); |
1827 | DC_LOG_DC("%s: DSC_Passthrough_Sink_Support: %s\n" , __func__, |
1828 | str_yes_no(is_dsc_passthrough_supported)); |
1829 | } |
1830 | if (link->dpcd_caps.dongle_type != DISPLAY_DONGLE_NONE) { |
1831 | status = core_link_read_dpcd( |
1832 | link, |
1833 | DP_DSC_BRANCH_OVERALL_THROUGHPUT_0, |
1834 | data: link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw, |
1835 | size: sizeof(link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.raw)); |
1836 | DC_LOG_DSC("DSC branch decoder capability is read at link %d" , link->link_index); |
1837 | DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_0 = 0x%02x" , |
1838 | link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_0); |
1839 | DC_LOG_DSC("\tBRANCH_OVERALL_THROUGHPUT_1 = 0x%02x" , |
1840 | link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_OVERALL_THROUGHPUT_1); |
1841 | DC_LOG_DSC("\tBRANCH_MAX_LINE_WIDTH 0x%02x" , |
1842 | link->dpcd_caps.dsc_caps.dsc_branch_decoder_caps.fields.BRANCH_MAX_LINE_WIDTH); |
1843 | } |
1844 | |
1845 | /* Apply work around to disable FEC and DSC for USB4 tunneling in TBT3 compatibility mode |
1846 | * only if required. |
1847 | */ |
1848 | if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA && |
1849 | link->dc->debug.dpia_debug.bits.enable_force_tbt3_work_around && |
1850 | link->dpcd_caps.is_branch_dev && |
1851 | link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC24 && |
1852 | link->dpcd_caps.branch_hw_revision == DP_BRANCH_HW_REV_10 && |
1853 | (link->dpcd_caps.fec_cap.bits.FEC_CAPABLE || |
1854 | link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT)) { |
1855 | /* A TBT3 device is expected to report no support for FEC or DSC to a USB4 DPIA. |
1856 | * Clear FEC and DSC capabilities as a work around if that is not the case. |
1857 | */ |
1858 | link->wa_flags.dpia_forced_tbt3_mode = true; |
1859 | memset(&link->dpcd_caps.dsc_caps, '\0', sizeof(link->dpcd_caps.dsc_caps)); |
1860 | memset(&link->dpcd_caps.fec_cap, '\0', sizeof(link->dpcd_caps.fec_cap)); |
1861 | DC_LOG_DSC("Clear DSC SUPPORT for USB4 link(%d) in TBT3 compatibility mode" , link->link_index); |
1862 | } else |
1863 | link->wa_flags.dpia_forced_tbt3_mode = false; |
1864 | } |
1865 | |
1866 | if (!dpcd_read_sink_ext_caps(link)) |
1867 | link->dpcd_sink_ext_caps.raw = 0; |
1868 | |
1869 | if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED) { |
1870 | DC_LOG_DP2("128b/132b encoding is supported at link %d" , link->link_index); |
1871 | |
1872 | core_link_read_dpcd(link, |
1873 | DP_128B132B_SUPPORTED_LINK_RATES, |
1874 | data: &link->dpcd_caps.dp_128b_132b_supported_link_rates.raw, |
1875 | size: sizeof(link->dpcd_caps.dp_128b_132b_supported_link_rates.raw)); |
1876 | if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR20) |
1877 | link->reported_link_cap.link_rate = LINK_RATE_UHBR20; |
1878 | else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5) |
1879 | link->reported_link_cap.link_rate = LINK_RATE_UHBR13_5; |
1880 | else if (link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR10) |
1881 | link->reported_link_cap.link_rate = LINK_RATE_UHBR10; |
1882 | else |
1883 | dm_error("%s: Invalid RX 128b_132b_supported_link_rates\n" , __func__); |
1884 | DC_LOG_DP2("128b/132b supported link rates is read at link %d" , link->link_index); |
1885 | DC_LOG_DP2("\tmax 128b/132b link rate support is %d.%d GHz" , |
1886 | link->reported_link_cap.link_rate / 100, |
1887 | link->reported_link_cap.link_rate % 100); |
1888 | |
1889 | core_link_read_dpcd(link, |
1890 | DP_SINK_VIDEO_FALLBACK_FORMATS, |
1891 | data: &link->dpcd_caps.fallback_formats.raw, |
1892 | size: sizeof(link->dpcd_caps.fallback_formats.raw)); |
1893 | DC_LOG_DP2("sink video fallback format is read at link %d" , link->link_index); |
1894 | if (link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support) |
1895 | DC_LOG_DP2("\t1920x1080@60Hz 24bpp fallback format supported" ); |
1896 | if (link->dpcd_caps.fallback_formats.bits.dp_1280x720_60Hz_24bpp_support) |
1897 | DC_LOG_DP2("\t1280x720@60Hz 24bpp fallback format supported" ); |
1898 | if (link->dpcd_caps.fallback_formats.bits.dp_1024x768_60Hz_24bpp_support) |
1899 | DC_LOG_DP2("\t1024x768@60Hz 24bpp fallback format supported" ); |
1900 | if (link->dpcd_caps.fallback_formats.raw == 0) { |
1901 | DC_LOG_DP2("\tno supported fallback formats, assume 1920x1080@60Hz 24bpp is supported" ); |
1902 | link->dpcd_caps.fallback_formats.bits.dp_1920x1080_60Hz_24bpp_support = 1; |
1903 | } |
1904 | |
1905 | core_link_read_dpcd(link, |
1906 | DP_FEC_CAPABILITY_1, |
1907 | data: &link->dpcd_caps.fec_cap1.raw, |
1908 | size: sizeof(link->dpcd_caps.fec_cap1.raw)); |
1909 | DC_LOG_DP2("FEC CAPABILITY 1 is read at link %d" , link->link_index); |
1910 | if (link->dpcd_caps.fec_cap1.bits.AGGREGATED_ERROR_COUNTERS_CAPABLE) |
1911 | DC_LOG_DP2("\tFEC aggregated error counters are supported" ); |
1912 | } |
1913 | |
1914 | retrieve_cable_id(link); |
1915 | dpcd_write_cable_id_to_dprx(link); |
1916 | |
1917 | /* Connectivity log: detection */ |
1918 | CONN_DATA_DETECT(link, dpcd_data, sizeof(dpcd_data), "Rx Caps: " ); |
1919 | |
1920 | return true; |
1921 | } |
1922 | |
1923 | bool detect_dp_sink_caps(struct dc_link *link) |
1924 | { |
1925 | return retrieve_link_cap(link); |
1926 | } |
1927 | |
1928 | void detect_edp_sink_caps(struct dc_link *link) |
1929 | { |
1930 | uint8_t supported_link_rates[16]; |
1931 | uint32_t entry; |
1932 | uint32_t link_rate_in_khz; |
1933 | enum dc_link_rate link_rate = LINK_RATE_UNKNOWN; |
1934 | uint8_t backlight_adj_cap; |
1935 | uint8_t general_edp_cap; |
1936 | |
1937 | retrieve_link_cap(link); |
1938 | link->dpcd_caps.edp_supported_link_rates_count = 0; |
1939 | memset(supported_link_rates, 0, sizeof(supported_link_rates)); |
1940 | |
1941 | /* |
1942 | * edp_supported_link_rates_count is only valid for eDP v1.4 or higher. |
1943 | * Per VESA eDP spec, "The DPCD revision for eDP v1.4 is 13h" |
1944 | */ |
1945 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_13) { |
1946 | // Read DPCD 00010h - 0001Fh 16 bytes at one shot |
1947 | core_link_read_dpcd(link, DP_SUPPORTED_LINK_RATES, |
1948 | data: supported_link_rates, size: sizeof(supported_link_rates)); |
1949 | |
1950 | for (entry = 0; entry < 16; entry += 2) { |
1951 | // DPCD register reports per-lane link rate = 16-bit link rate capability |
1952 | // value X 200 kHz. Need multiplier to find link rate in kHz. |
1953 | link_rate_in_khz = (supported_link_rates[entry+1] * 0x100 + |
1954 | supported_link_rates[entry]) * 200; |
1955 | |
1956 | DC_LOG_DC("%s: eDP v1.4 supported sink rates: [%d] %d kHz\n" , __func__, |
1957 | entry / 2, link_rate_in_khz); |
1958 | |
1959 | if (link_rate_in_khz != 0) { |
1960 | link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz); |
1961 | link->dpcd_caps.edp_supported_link_rates[link->dpcd_caps.edp_supported_link_rates_count] = link_rate; |
1962 | link->dpcd_caps.edp_supported_link_rates_count++; |
1963 | } |
1964 | } |
1965 | } |
1966 | |
1967 | core_link_read_dpcd(link, DP_EDP_BACKLIGHT_ADJUSTMENT_CAP, |
1968 | data: &backlight_adj_cap, size: sizeof(backlight_adj_cap)); |
1969 | |
1970 | link->dpcd_caps.dynamic_backlight_capable_edp = |
1971 | (backlight_adj_cap & DP_EDP_DYNAMIC_BACKLIGHT_CAP) ? true:false; |
1972 | |
1973 | core_link_read_dpcd(link, DP_EDP_GENERAL_CAP_1, |
1974 | data: &general_edp_cap, size: sizeof(general_edp_cap)); |
1975 | |
1976 | link->dpcd_caps.set_power_state_capable_edp = |
1977 | (general_edp_cap & DP_EDP_SET_POWER_CAP) ? true:false; |
1978 | |
1979 | set_default_brightness_aux(link); |
1980 | |
1981 | core_link_read_dpcd(link, DP_EDP_DPCD_REV, |
1982 | data: &link->dpcd_caps.edp_rev, |
1983 | size: sizeof(link->dpcd_caps.edp_rev)); |
1984 | /* |
1985 | * PSR is only valid for eDP v1.3 or higher. |
1986 | */ |
1987 | if (link->dpcd_caps.edp_rev >= DP_EDP_13) { |
1988 | core_link_read_dpcd(link, DP_PSR_SUPPORT, |
1989 | data: &link->dpcd_caps.psr_info.psr_version, |
1990 | size: sizeof(link->dpcd_caps.psr_info.psr_version)); |
1991 | if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8) |
1992 | core_link_read_dpcd(link, DP_FORCE_PSRSU_CAPABILITY, |
1993 | data: &link->dpcd_caps.psr_info.force_psrsu_cap, |
1994 | size: sizeof(link->dpcd_caps.psr_info.force_psrsu_cap)); |
1995 | core_link_read_dpcd(link, DP_PSR_CAPS, |
1996 | data: &link->dpcd_caps.psr_info.psr_dpcd_caps.raw, |
1997 | size: sizeof(link->dpcd_caps.psr_info.psr_dpcd_caps.raw)); |
1998 | if (link->dpcd_caps.psr_info.psr_dpcd_caps.bits.Y_COORDINATE_REQUIRED) { |
1999 | core_link_read_dpcd(link, DP_PSR2_SU_Y_GRANULARITY, |
2000 | data: &link->dpcd_caps.psr_info.psr2_su_y_granularity_cap, |
2001 | size: sizeof(link->dpcd_caps.psr_info.psr2_su_y_granularity_cap)); |
2002 | } |
2003 | } |
2004 | |
2005 | /* |
2006 | * ALPM is only valid for eDP v1.4 or higher. |
2007 | */ |
2008 | if (link->dpcd_caps.dpcd_rev.raw >= DP_EDP_14) |
2009 | core_link_read_dpcd(link, DP_RECEIVER_ALPM_CAP, |
2010 | data: &link->dpcd_caps.alpm_caps.raw, |
2011 | size: sizeof(link->dpcd_caps.alpm_caps.raw)); |
2012 | |
2013 | /* |
2014 | * Read REPLAY info |
2015 | */ |
2016 | core_link_read_dpcd(link, DP_SINK_PR_PIXEL_DEVIATION_PER_LINE, |
2017 | data: &link->dpcd_caps.pr_info.pixel_deviation_per_line, |
2018 | size: sizeof(link->dpcd_caps.pr_info.pixel_deviation_per_line)); |
2019 | core_link_read_dpcd(link, DP_SINK_PR_MAX_NUMBER_OF_DEVIATION_LINE, |
2020 | data: &link->dpcd_caps.pr_info.max_deviation_line, |
2021 | size: sizeof(link->dpcd_caps.pr_info.max_deviation_line)); |
2022 | } |
2023 | |
2024 | bool dp_get_max_link_enc_cap(const struct dc_link *link, struct dc_link_settings *max_link_enc_cap) |
2025 | { |
2026 | struct link_encoder *link_enc = NULL; |
2027 | |
2028 | if (!max_link_enc_cap) { |
2029 | DC_LOG_ERROR("%s: Could not return max link encoder caps" , __func__); |
2030 | return false; |
2031 | } |
2032 | |
2033 | link_enc = link_enc_cfg_get_link_enc(link); |
2034 | ASSERT(link_enc); |
2035 | |
2036 | if (link_enc && link_enc->funcs->get_max_link_cap) { |
2037 | link_enc->funcs->get_max_link_cap(link_enc, max_link_enc_cap); |
2038 | return true; |
2039 | } |
2040 | |
2041 | DC_LOG_ERROR("%s: Max link encoder caps unknown" , __func__); |
2042 | max_link_enc_cap->lane_count = 1; |
2043 | max_link_enc_cap->link_rate = 6; |
2044 | return false; |
2045 | } |
2046 | |
2047 | const struct dc_link_settings *dp_get_verified_link_cap( |
2048 | const struct dc_link *link) |
2049 | { |
2050 | if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN && |
2051 | link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN) |
2052 | return &link->preferred_link_setting; |
2053 | return &link->verified_link_cap; |
2054 | } |
2055 | |
2056 | struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) |
2057 | { |
2058 | struct dc_link_settings max_link_cap = {0}; |
2059 | enum dc_link_rate lttpr_max_link_rate; |
2060 | enum dc_link_rate cable_max_link_rate; |
2061 | struct link_encoder *link_enc = NULL; |
2062 | |
2063 | |
2064 | link_enc = link_enc_cfg_get_link_enc(link); |
2065 | ASSERT(link_enc); |
2066 | |
2067 | /* get max link encoder capability */ |
2068 | if (link_enc) |
2069 | link_enc->funcs->get_max_link_cap(link_enc, &max_link_cap); |
2070 | |
2071 | /* Lower link settings based on sink's link cap */ |
2072 | if (link->reported_link_cap.lane_count < max_link_cap.lane_count) |
2073 | max_link_cap.lane_count = |
2074 | link->reported_link_cap.lane_count; |
2075 | if (link->reported_link_cap.link_rate < max_link_cap.link_rate) |
2076 | max_link_cap.link_rate = |
2077 | link->reported_link_cap.link_rate; |
2078 | if (link->reported_link_cap.link_spread < |
2079 | max_link_cap.link_spread) |
2080 | max_link_cap.link_spread = |
2081 | link->reported_link_cap.link_spread; |
2082 | |
2083 | /* Lower link settings based on cable attributes |
2084 | * Cable ID is a DP2 feature to identify max certified link rate that |
2085 | * a cable can carry. The cable identification method requires both |
2086 | * cable and display hardware support. Since the specs comes late, it is |
2087 | * anticipated that the first round of DP2 cables and displays may not |
2088 | * be fully compatible to reliably return cable ID data. Therefore the |
2089 | * decision of our cable id policy is that if the cable can return non |
2090 | * zero cable id data, we will take cable's link rate capability into |
2091 | * account. However if we get zero data, the cable link rate capability |
2092 | * is considered inconclusive. In this case, we will not take cable's |
2093 | * capability into account to avoid of over limiting hardware capability |
2094 | * from users. The max overall link rate capability is still determined |
2095 | * after actual dp pre-training. Cable id is considered as an auxiliary |
2096 | * method of determining max link bandwidth capability. |
2097 | */ |
2098 | cable_max_link_rate = get_cable_max_link_rate(link); |
2099 | |
2100 | if (!link->dc->debug.ignore_cable_id && |
2101 | cable_max_link_rate != LINK_RATE_UNKNOWN && |
2102 | cable_max_link_rate < max_link_cap.link_rate) |
2103 | max_link_cap.link_rate = cable_max_link_rate; |
2104 | |
2105 | /* account for lttpr repeaters cap |
2106 | * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3). |
2107 | */ |
2108 | if (dp_is_lttpr_present(link)) { |
2109 | if (link->dpcd_caps.lttpr_caps.max_lane_count < max_link_cap.lane_count) |
2110 | max_link_cap.lane_count = link->dpcd_caps.lttpr_caps.max_lane_count; |
2111 | lttpr_max_link_rate = get_lttpr_max_link_rate(link); |
2112 | |
2113 | if (lttpr_max_link_rate < max_link_cap.link_rate) |
2114 | max_link_cap.link_rate = lttpr_max_link_rate; |
2115 | |
2116 | DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n" , |
2117 | __func__, |
2118 | max_link_cap.lane_count, |
2119 | max_link_cap.link_rate); |
2120 | } |
2121 | |
2122 | if (link_dp_get_encoding_format(link_settings: &max_link_cap) == DP_128b_132b_ENCODING && |
2123 | link->dc->debug.disable_uhbr) |
2124 | max_link_cap.link_rate = LINK_RATE_HIGH3; |
2125 | |
2126 | return max_link_cap; |
2127 | } |
2128 | |
2129 | static bool dp_verify_link_cap( |
2130 | struct dc_link *link, |
2131 | struct dc_link_settings *known_limit_link_setting, |
2132 | int *fail_count) |
2133 | { |
2134 | struct dc_link_settings cur_link_settings = {0}; |
2135 | struct dc_link_settings max_link_settings = *known_limit_link_setting; |
2136 | bool success = false; |
2137 | bool skip_video_pattern; |
2138 | enum clock_source_id dp_cs_id = get_clock_source_id(link); |
2139 | enum link_training_result status = LINK_TRAINING_SUCCESS; |
2140 | union hpd_irq_data irq_data; |
2141 | struct link_resource link_res; |
2142 | |
2143 | memset(&irq_data, 0, sizeof(irq_data)); |
2144 | cur_link_settings = max_link_settings; |
2145 | |
2146 | /* Grant extended timeout request */ |
2147 | if (dp_is_lttpr_present(link) && link->dpcd_caps.lttpr_caps.max_ext_timeout > 0) { |
2148 | uint8_t grant = link->dpcd_caps.lttpr_caps.max_ext_timeout & 0x80; |
2149 | |
2150 | core_link_write_dpcd(link, DP_PHY_REPEATER_EXTENDED_WAIT_TIMEOUT, data: &grant, size: sizeof(grant)); |
2151 | } |
2152 | |
2153 | do { |
2154 | if (!get_temp_dp_link_res(link, link_res: &link_res, link_settings: &cur_link_settings)) |
2155 | continue; |
2156 | |
2157 | skip_video_pattern = cur_link_settings.link_rate != LINK_RATE_LOW; |
2158 | dp_enable_link_phy( |
2159 | link, |
2160 | link_res: &link_res, |
2161 | signal: link->connector_signal, |
2162 | clock_source: dp_cs_id, |
2163 | link_settings: &cur_link_settings); |
2164 | |
2165 | status = dp_perform_link_training( |
2166 | link, |
2167 | link_res: &link_res, |
2168 | link_settings: &cur_link_settings, |
2169 | skip_video_pattern); |
2170 | |
2171 | if (status == LINK_TRAINING_SUCCESS) { |
2172 | success = true; |
2173 | fsleep(usecs: 1000); |
2174 | if (dp_read_hpd_rx_irq_data(link, irq_data: &irq_data) == DC_OK && |
2175 | dp_parse_link_loss_status( |
2176 | link, |
2177 | hpd_irq_dpcd_data: &irq_data)) |
2178 | (*fail_count)++; |
2179 | } else if (status == LINK_TRAINING_LINK_LOSS) { |
2180 | success = true; |
2181 | (*fail_count)++; |
2182 | } else { |
2183 | (*fail_count)++; |
2184 | } |
2185 | dp_trace_lt_total_count_increment(link, in_detection: true); |
2186 | dp_trace_lt_result_update(link, result: status, in_detection: true); |
2187 | dp_disable_link_phy(link, link_res: &link_res, signal: link->connector_signal); |
2188 | } while (!success && decide_fallback_link_setting(link, |
2189 | max: &max_link_settings, cur: &cur_link_settings, training_result: status)); |
2190 | |
2191 | link->verified_link_cap = success ? |
2192 | cur_link_settings : fail_safe_link_settings; |
2193 | return success; |
2194 | } |
2195 | |
2196 | bool dp_verify_link_cap_with_retries( |
2197 | struct dc_link *link, |
2198 | struct dc_link_settings *known_limit_link_setting, |
2199 | int attempts) |
2200 | { |
2201 | int i = 0; |
2202 | bool success = false; |
2203 | int fail_count = 0; |
2204 | struct dc_link_settings last_verified_link_cap = fail_safe_link_settings; |
2205 | |
2206 | dp_trace_detect_lt_init(link); |
2207 | |
2208 | if (link->link_enc && link->link_enc->features.flags.bits.DP_IS_USB_C && |
2209 | link->dc->debug.usbc_combo_phy_reset_wa) |
2210 | apply_usbc_combo_phy_reset_wa(link, link_settings: known_limit_link_setting); |
2211 | |
2212 | dp_trace_set_lt_start_timestamp(link, in_detection: false); |
2213 | for (i = 0; i < attempts; i++) { |
2214 | enum dc_connection_type type = dc_connection_none; |
2215 | |
2216 | memset(&link->verified_link_cap, 0, |
2217 | sizeof(struct dc_link_settings)); |
2218 | if (!link_detect_connection_type(link, type: &type) || type == dc_connection_none) { |
2219 | link->verified_link_cap = fail_safe_link_settings; |
2220 | break; |
2221 | } else if (dp_verify_link_cap(link, known_limit_link_setting, fail_count: &fail_count)) { |
2222 | last_verified_link_cap = link->verified_link_cap; |
2223 | if (fail_count == 0) { |
2224 | success = true; |
2225 | break; |
2226 | } |
2227 | } else { |
2228 | link->verified_link_cap = last_verified_link_cap; |
2229 | } |
2230 | fsleep(usecs: 10 * 1000); |
2231 | } |
2232 | |
2233 | dp_trace_lt_fail_count_update(link, fail_count, in_detection: true); |
2234 | dp_trace_set_lt_end_timestamp(link, in_detection: true); |
2235 | |
2236 | return success; |
2237 | } |
2238 | |
2239 | /* |
2240 | * Check if there is a native DP or passive DP-HDMI dongle connected |
2241 | */ |
2242 | bool dp_is_sink_present(struct dc_link *link) |
2243 | { |
2244 | enum gpio_result gpio_result; |
2245 | uint32_t clock_pin = 0; |
2246 | uint8_t retry = 0; |
2247 | struct ddc *ddc; |
2248 | |
2249 | enum connector_id connector_id = |
2250 | dal_graphics_object_id_get_connector_id(id: link->link_id); |
2251 | |
2252 | bool present = |
2253 | ((connector_id == CONNECTOR_ID_DISPLAY_PORT) || |
2254 | (connector_id == CONNECTOR_ID_EDP) || |
2255 | (connector_id == CONNECTOR_ID_USBC)); |
2256 | |
2257 | ddc = get_ddc_pin(ddc_service: link->ddc); |
2258 | |
2259 | if (!ddc) { |
2260 | BREAK_TO_DEBUGGER(); |
2261 | return present; |
2262 | } |
2263 | |
2264 | /* Open GPIO and set it to I2C mode */ |
2265 | /* Note: this GpioMode_Input will be converted |
2266 | * to GpioConfigType_I2cAuxDualMode in GPIO component, |
2267 | * which indicates we need additional delay |
2268 | */ |
2269 | |
2270 | if (dal_ddc_open(ddc, mode: GPIO_MODE_INPUT, |
2271 | config_type: GPIO_DDC_CONFIG_TYPE_MODE_I2C) != GPIO_RESULT_OK) { |
2272 | dal_ddc_close(ddc); |
2273 | |
2274 | return present; |
2275 | } |
2276 | |
2277 | /* |
2278 | * Read GPIO: DP sink is present if both clock and data pins are zero |
2279 | * |
2280 | * [W/A] plug-unplug DP cable, sometimes customer board has |
2281 | * one short pulse on clk_pin(1V, < 1ms). DP will be config to HDMI/DVI |
2282 | * then monitor can't br light up. Add retry 3 times |
2283 | * But in real passive dongle, it need additional 3ms to detect |
2284 | */ |
2285 | do { |
2286 | gpio_result = dal_gpio_get_value(gpio: ddc->pin_clock, value: &clock_pin); |
2287 | ASSERT(gpio_result == GPIO_RESULT_OK); |
2288 | if (clock_pin) |
2289 | fsleep(usecs: 1000); |
2290 | else |
2291 | break; |
2292 | } while (retry++ < 3); |
2293 | |
2294 | present = (gpio_result == GPIO_RESULT_OK) && !clock_pin; |
2295 | |
2296 | dal_ddc_close(ddc); |
2297 | |
2298 | return present; |
2299 | } |
2300 | |