Bug Summary

File:dev/pci/drm/amd/display/dc/core/dc_link.c
Warning:line 4485, column 7
Dereference of null pointer

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.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.c
1/*
2 * Copyright 2012-15 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#include <linux/slab.h>
27
28#include "dm_services.h"
29#include "atomfirmware.h"
30#include "dm_helpers.h"
31#include "dc.h"
32#include "grph_object_id.h"
33#include "gpio_service_interface.h"
34#include "core_status.h"
35#include "dc_link_dp.h"
36#include "dc_link_dpia.h"
37#include "dc_link_ddc.h"
38#include "link_hwss.h"
39#include "opp.h"
40
41#include "link_encoder.h"
42#include "hw_sequencer.h"
43#include "resource.h"
44#include "abm.h"
45#include "fixed31_32.h"
46#include "dpcd_defs.h"
47#include "dmcu.h"
48#include "hw/clk_mgr.h"
49#include "dce/dmub_psr.h"
50#include "dmub/dmub_srv.h"
51#include "inc/hw/panel_cntl.h"
52#include "inc/link_enc_cfg.h"
53#include "inc/link_dpcd.h"
54#include "link/link_dp_trace.h"
55
56#include "dc/dcn30/dcn30_vpg.h"
57
58#define DC_LOGGER_INIT(logger)
59
60#define LINK_INFO(...)___drm_dbg(((void *)0), DRM_UT_KMS, ...) \
61 DC_LOG_HW_HOTPLUG( \___drm_dbg(((void *)0), DRM_UT_KMS, __VA_ARGS__)
62 __VA_ARGS__)___drm_dbg(((void *)0), DRM_UT_KMS, __VA_ARGS__)
63
64#define RETIMER_REDRIVER_INFO(...)___drm_dbg(((void *)0), DRM_UT_KMS, ...) \
65 DC_LOG_RETIMER_REDRIVER( \___drm_dbg(((void *)0), DRM_UT_KMS, __VA_ARGS__)
66 __VA_ARGS__)___drm_dbg(((void *)0), DRM_UT_KMS, __VA_ARGS__)
67
68/*******************************************************************************
69 * Private functions
70 ******************************************************************************/
71static void dc_link_destruct(struct dc_link *link)
72{
73 int i;
74
75 if (link->hpd_gpio) {
76 dal_gpio_destroy_irq(&link->hpd_gpio);
77 link->hpd_gpio = NULL((void *)0);
78 }
79
80 if (link->ddc)
81 dal_ddc_service_destroy(&link->ddc);
82
83 if (link->panel_cntl)
84 link->panel_cntl->funcs->destroy(&link->panel_cntl);
85
86 if (link->link_enc) {
87 /* Update link encoder resource tracking variables. These are used for
88 * the dynamic assignment of link encoders to streams. Virtual links
89 * are not assigned encoder resources on creation.
90 */
91 if (link->link_id.id != CONNECTOR_ID_VIRTUAL) {
92 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = NULL((void *)0);
93 link->dc->res_pool->dig_link_enc_count--;
94 }
95 link->link_enc->funcs->destroy(&link->link_enc);
96 }
97
98 if (link->local_sink)
99 dc_sink_release(link->local_sink);
100
101 for (i = 0; i < link->sink_count; ++i)
102 dc_sink_release(link->remote_sinks[i]);
103}
104
105struct gpio *get_hpd_gpio(struct dc_bios *dcb,
106 struct graphics_object_id link_id,
107 struct gpio_service *gpio_service)
108{
109 enum bp_result bp_result;
110 struct graphics_object_hpd_info hpd_info;
111 struct gpio_pin_info pin_info;
112
113 if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK)
114 return NULL((void *)0);
115
116 bp_result = dcb->funcs->get_gpio_pin_info(dcb,
117 hpd_info.hpd_int_gpio_uid, &pin_info);
118
119 if (bp_result != BP_RESULT_OK) {
120 ASSERT(bp_result == BP_RESULT_NORECORD)do { if (({ static int __warned; int __ret = !!(!(bp_result ==
BP_RESULT_NORECORD)); if (__ret && !__warned) { printf
("WARNING %s failed at %s:%d\n", "!(bp_result == BP_RESULT_NORECORD)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c", 120
); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while
(0); } while (0)
;
121 return NULL((void *)0);
122 }
123
124 return dal_gpio_service_create_irq(gpio_service,
125 pin_info.offset,
126 pin_info.mask);
127}
128
129/*
130 * Function: program_hpd_filter
131 *
132 * @brief
133 * Programs HPD filter on associated HPD line
134 *
135 * @param [in] delay_on_connect_in_ms: Connect filter timeout
136 * @param [in] delay_on_disconnect_in_ms: Disconnect filter timeout
137 *
138 * @return
139 * true on success, false otherwise
140 */
141static bool_Bool program_hpd_filter(const struct dc_link *link)
142{
143 bool_Bool result = false0;
144 struct gpio *hpd;
145 int delay_on_connect_in_ms = 0;
146 int delay_on_disconnect_in_ms = 0;
147
148 if (link->is_hpd_filter_disabled)
149 return false0;
150 /* Verify feature is supported */
151 switch (link->connector_signal) {
152 case SIGNAL_TYPE_DVI_SINGLE_LINK:
153 case SIGNAL_TYPE_DVI_DUAL_LINK:
154 case SIGNAL_TYPE_HDMI_TYPE_A:
155 /* Program hpd filter */
156 delay_on_connect_in_ms = 500;
157 delay_on_disconnect_in_ms = 100;
158 break;
159 case SIGNAL_TYPE_DISPLAY_PORT:
160 case SIGNAL_TYPE_DISPLAY_PORT_MST:
161 /* Program hpd filter to allow DP signal to settle */
162 /* 500: not able to detect MST <-> SST switch as HPD is low for
163 * only 100ms on DELL U2413
164 * 0: some passive dongle still show aux mode instead of i2c
165 * 20-50: not enough to hide bouncing HPD with passive dongle.
166 * also see intermittent i2c read issues.
167 */
168 delay_on_connect_in_ms = 80;
169 delay_on_disconnect_in_ms = 0;
170 break;
171 case SIGNAL_TYPE_LVDS:
172 case SIGNAL_TYPE_EDP:
173 default:
174 /* Don't program hpd filter */
175 return false0;
176 }
177
178 /* Obtain HPD handle */
179 hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id,
180 link->ctx->gpio_service);
181
182 if (!hpd)
183 return result;
184
185 /* Setup HPD filtering */
186 if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
187 struct gpio_hpd_config config;
188
189 config.delay_on_connect = delay_on_connect_in_ms;
190 config.delay_on_disconnect = delay_on_disconnect_in_ms;
191
192 dal_irq_setup_hpd_filter(hpd, &config);
193
194 dal_gpio_close(hpd);
195
196 result = true1;
197 } else {
198 ASSERT_CRITICAL(false)do { if (({ int __ret = !!(!(0)); if (__ret) printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c"
, 198); __builtin_expect(!!(__ret), 0); })) do {} while (0); }
while (0)
;
199 }
200
201 /* Release HPD handle */
202 dal_gpio_destroy_irq(&hpd);
203
204 return result;
205}
206
207bool_Bool dc_link_wait_for_t12(struct dc_link *link)
208{
209 if (link->connector_signal == SIGNAL_TYPE_EDP && link->dc->hwss.edp_wait_for_T12) {
210 link->dc->hwss.edp_wait_for_T12(link);
211
212 return true1;
213 }
214
215 return false0;
216}
217
218/**
219 * dc_link_detect_sink() - Determine if there is a sink connected
220 *
221 * @link: pointer to the dc link
222 * @type: Returned connection type
223 * Does not detect downstream devices, such as MST sinks
224 * or display connected through active dongles
225 */
226bool_Bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type)
227{
228 uint32_t is_hpd_high = 0;
229 struct gpio *hpd_pin;
230
231 if (link->connector_signal == SIGNAL_TYPE_LVDS) {
232 *type = dc_connection_single;
233 return true1;
234 }
235
236 if (link->connector_signal == SIGNAL_TYPE_EDP) {
237 /*in case it is not on*/
238 if (!link->dc->config.edp_no_power_sequencing)
239 link->dc->hwss.edp_power_control(link, true1);
240 link->dc->hwss.edp_wait_for_hpd_ready(link, true1);
241 }
242
243 /* Link may not have physical HPD pin. */
244 if (link->ep_type != DISPLAY_ENDPOINT_PHY) {
245 if (link->is_hpd_pending || !dc_link_dpia_query_hpd_status(link))
246 *type = dc_connection_none;
247 else
248 *type = dc_connection_single;
249
250 return true1;
251 }
252
253 /* todo: may need to lock gpio access */
254 hpd_pin = get_hpd_gpio(link->ctx->dc_bios, link->link_id,
255 link->ctx->gpio_service);
256 if (!hpd_pin)
257 goto hpd_gpio_failure;
258
259 dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);
260 dal_gpio_get_value(hpd_pin, &is_hpd_high);
261 dal_gpio_close(hpd_pin);
262 dal_gpio_destroy_irq(&hpd_pin);
263
264 if (is_hpd_high) {
265 *type = dc_connection_single;
266 /* TODO: need to do the actual detection */
267 } else {
268 *type = dc_connection_none;
269 }
270
271 return true1;
272
273hpd_gpio_failure:
274 return false0;
275}
276
277static enum ddc_transaction_type get_ddc_transaction_type(enum amd_signal_type sink_signal)
278{
279 enum ddc_transaction_type transaction_type = DDC_TRANSACTION_TYPE_NONE;
280
281 switch (sink_signal) {
282 case SIGNAL_TYPE_DVI_SINGLE_LINK:
283 case SIGNAL_TYPE_DVI_DUAL_LINK:
284 case SIGNAL_TYPE_HDMI_TYPE_A:
285 case SIGNAL_TYPE_LVDS:
286 case SIGNAL_TYPE_RGB:
287 transaction_type = DDC_TRANSACTION_TYPE_I2C;
288 break;
289
290 case SIGNAL_TYPE_DISPLAY_PORT:
291 case SIGNAL_TYPE_EDP:
292 transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
293 break;
294
295 case SIGNAL_TYPE_DISPLAY_PORT_MST:
296 /* MST does not use I2COverAux, but there is the
297 * SPECIAL use case for "immediate dwnstrm device
298 * access" (EPR#370830).
299 */
300 transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
301 break;
302
303 default:
304 break;
305 }
306
307 return transaction_type;
308}
309
310static enum amd_signal_type get_basic_signal_type(struct graphics_object_id encoder,
311 struct graphics_object_id downstream)
312{
313 if (downstream.type == OBJECT_TYPE_CONNECTOR) {
314 switch (downstream.id) {
315 case CONNECTOR_ID_SINGLE_LINK_DVII:
316 switch (encoder.id) {
317 case ENCODER_ID_INTERNAL_DAC1:
318 case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
319 case ENCODER_ID_INTERNAL_DAC2:
320 case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
321 return SIGNAL_TYPE_RGB;
322 default:
323 return SIGNAL_TYPE_DVI_SINGLE_LINK;
324 }
325 break;
326 case CONNECTOR_ID_DUAL_LINK_DVII:
327 {
328 switch (encoder.id) {
329 case ENCODER_ID_INTERNAL_DAC1:
330 case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
331 case ENCODER_ID_INTERNAL_DAC2:
332 case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
333 return SIGNAL_TYPE_RGB;
334 default:
335 return SIGNAL_TYPE_DVI_DUAL_LINK;
336 }
337 }
338 break;
339 case CONNECTOR_ID_SINGLE_LINK_DVID:
340 return SIGNAL_TYPE_DVI_SINGLE_LINK;
341 case CONNECTOR_ID_DUAL_LINK_DVID:
342 return SIGNAL_TYPE_DVI_DUAL_LINK;
343 case CONNECTOR_ID_VGA:
344 return SIGNAL_TYPE_RGB;
345 case CONNECTOR_ID_HDMI_TYPE_A:
346 return SIGNAL_TYPE_HDMI_TYPE_A;
347 case CONNECTOR_ID_LVDS:
348 return SIGNAL_TYPE_LVDS;
349 case CONNECTOR_ID_DISPLAY_PORT:
350 case CONNECTOR_ID_USBC:
351 return SIGNAL_TYPE_DISPLAY_PORT;
352 case CONNECTOR_ID_EDP:
353 return SIGNAL_TYPE_EDP;
354 default:
355 return SIGNAL_TYPE_NONE;
356 }
357 } else if (downstream.type == OBJECT_TYPE_ENCODER) {
358 switch (downstream.id) {
359 case ENCODER_ID_EXTERNAL_NUTMEG:
360 case ENCODER_ID_EXTERNAL_TRAVIS:
361 return SIGNAL_TYPE_DISPLAY_PORT;
362 default:
363 return SIGNAL_TYPE_NONE;
364 }
365 }
366
367 return SIGNAL_TYPE_NONE;
368}
369
370/*
371 * dc_link_is_dp_sink_present() - Check if there is a native DP
372 * or passive DP-HDMI dongle connected
373 */
374bool_Bool dc_link_is_dp_sink_present(struct dc_link *link)
375{
376 enum gpio_result gpio_result;
377 uint32_t clock_pin = 0;
378 uint8_t retry = 0;
379 struct ddc *ddc;
380
381 enum connector_id connector_id =
382 dal_graphics_object_id_get_connector_id(link->link_id);
383
384 bool_Bool present =
385 ((connector_id == CONNECTOR_ID_DISPLAY_PORT) ||
386 (connector_id == CONNECTOR_ID_EDP) ||
387 (connector_id == CONNECTOR_ID_USBC));
388
389 ddc = dal_ddc_service_get_ddc_pin(link->ddc);
390
391 if (!ddc) {
392 BREAK_TO_DEBUGGER()do { ___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s():%d\n", __func__
, 392); do {} while (0); } while (0)
;
393 return present;
394 }
395
396 /* Open GPIO and set it to I2C mode */
397 /* Note: this GpioMode_Input will be converted
398 * to GpioConfigType_I2cAuxDualMode in GPIO component,
399 * which indicates we need additional delay
400 */
401
402 if (dal_ddc_open(ddc, GPIO_MODE_INPUT,
403 GPIO_DDC_CONFIG_TYPE_MODE_I2C) != GPIO_RESULT_OK) {
404 dal_ddc_close(ddc);
405
406 return present;
407 }
408
409 /*
410 * Read GPIO: DP sink is present if both clock and data pins are zero
411 *
412 * [W/A] plug-unplug DP cable, sometimes customer board has
413 * one short pulse on clk_pin(1V, < 1ms). DP will be config to HDMI/DVI
414 * then monitor can't br light up. Add retry 3 times
415 * But in real passive dongle, it need additional 3ms to detect
416 */
417 do {
418 gpio_result = dal_gpio_get_value(ddc->pin_clock, &clock_pin);
419 ASSERT(gpio_result == GPIO_RESULT_OK)do { if (({ static int __warned; int __ret = !!(!(gpio_result
== GPIO_RESULT_OK)); if (__ret && !__warned) { printf
("WARNING %s failed at %s:%d\n", "!(gpio_result == GPIO_RESULT_OK)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c", 419
); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while
(0); } while (0)
;
420 if (clock_pin)
421 udelay(1000);
422 else
423 break;
424 } while (retry++ < 3);
425
426 present = (gpio_result == GPIO_RESULT_OK) && !clock_pin;
427
428 dal_ddc_close(ddc);
429
430 return present;
431}
432
433/*
434 * @brief
435 * Detect output sink type
436 */
437static enum amd_signal_type link_detect_sink(struct dc_link *link,
438 enum dc_detect_reason reason)
439{
440 enum amd_signal_type result;
441 struct graphics_object_id enc_id;
442
443 if (link->is_dig_mapping_flexible)
444 enc_id = (struct graphics_object_id){.id = ENCODER_ID_UNKNOWN};
445 else
446 enc_id = link->link_enc->id;
447 result = get_basic_signal_type(enc_id, link->link_id);
448
449 /* Use basic signal type for link without physical connector. */
450 if (link->ep_type != DISPLAY_ENDPOINT_PHY)
451 return result;
452
453 /* Internal digital encoder will detect only dongles
454 * that require digital signal
455 */
456
457 /* Detection mechanism is different
458 * for different native connectors.
459 * LVDS connector supports only LVDS signal;
460 * PCIE is a bus slot, the actual connector needs to be detected first;
461 * eDP connector supports only eDP signal;
462 * HDMI should check straps for audio
463 */
464
465 /* PCIE detects the actual connector on add-on board */
466 if (link->link_id.id == CONNECTOR_ID_PCIE) {
467 /* ZAZTODO implement PCIE add-on card detection */
468 }
469
470 switch (link->link_id.id) {
471 case CONNECTOR_ID_HDMI_TYPE_A: {
472 /* check audio support:
473 * if native HDMI is not supported, switch to DVI
474 */
475 struct audio_support *aud_support =
476 &link->dc->res_pool->audio_support;
477
478 if (!aud_support->hdmi_audio_native)
479 if (link->link_id.id == CONNECTOR_ID_HDMI_TYPE_A)
480 result = SIGNAL_TYPE_DVI_SINGLE_LINK;
481 }
482 break;
483 case CONNECTOR_ID_DISPLAY_PORT:
484 case CONNECTOR_ID_USBC: {
485 /* DP HPD short pulse. Passive DP dongle will not
486 * have short pulse
487 */
488 if (reason != DETECT_REASON_HPDRX) {
489 /* Check whether DP signal detected: if not -
490 * we assume signal is DVI; it could be corrected
491 * to HDMI after dongle detection
492 */
493 if (!dm_helpers_is_dp_sink_present(link))
494 result = SIGNAL_TYPE_DVI_SINGLE_LINK;
495 }
496 }
497 break;
498 default:
499 break;
500 }
501
502 return result;
503}
504
505static enum amd_signal_type decide_signal_from_strap_and_dongle_type(enum display_dongle_type dongle_type,
506 struct audio_support *audio_support)
507{
508 enum amd_signal_type signal = SIGNAL_TYPE_NONE;
509
510 switch (dongle_type) {
511 case DISPLAY_DONGLE_DP_HDMI_DONGLE:
512 if (audio_support->hdmi_audio_on_dongle)
513 signal = SIGNAL_TYPE_HDMI_TYPE_A;
514 else
515 signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
516 break;
517 case DISPLAY_DONGLE_DP_DVI_DONGLE:
518 signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
519 break;
520 case DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE:
521 if (audio_support->hdmi_audio_native)
522 signal = SIGNAL_TYPE_HDMI_TYPE_A;
523 else
524 signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
525 break;
526 default:
527 signal = SIGNAL_TYPE_NONE;
528 break;
529 }
530
531 return signal;
532}
533
534static enum amd_signal_type dp_passive_dongle_detection(struct ddc_service *ddc,
535 struct display_sink_capability *sink_cap,
536 struct audio_support *audio_support)
537{
538 dal_ddc_service_i2c_query_dp_dual_mode_adaptor(ddc, sink_cap);
539
540 return decide_signal_from_strap_and_dongle_type(sink_cap->dongle_type,
541 audio_support);
542}
543
544static void link_disconnect_sink(struct dc_link *link)
545{
546 if (link->local_sink) {
547 dc_sink_release(link->local_sink);
548 link->local_sink = NULL((void *)0);
549 }
550
551 link->dpcd_sink_count = 0;
552 //link->dpcd_caps.dpcd_rev.raw = 0;
553}
554
555static void link_disconnect_remap(struct dc_sink *prev_sink, struct dc_link *link)
556{
557 dc_sink_release(link->local_sink);
558 link->local_sink = prev_sink;
559}
560
561#if defined(CONFIG_DRM_AMD_DC_HDCP)
562bool_Bool dc_link_is_hdcp14(struct dc_link *link, enum amd_signal_type signal)
563{
564 bool_Bool ret = false0;
565
566 switch (signal) {
567 case SIGNAL_TYPE_DISPLAY_PORT:
568 case SIGNAL_TYPE_DISPLAY_PORT_MST:
569 ret = link->hdcp_caps.bcaps.bits.HDCP_CAPABLE;
570 break;
571 case SIGNAL_TYPE_DVI_SINGLE_LINK:
572 case SIGNAL_TYPE_DVI_DUAL_LINK:
573 case SIGNAL_TYPE_HDMI_TYPE_A:
574 /* HDMI doesn't tell us its HDCP(1.4) capability, so assume to always be capable,
575 * we can poll for bksv but some displays have an issue with this. Since its so rare
576 * for a display to not be 1.4 capable, this assumtion is ok
577 */
578 ret = true1;
579 break;
580 default:
581 break;
582 }
583 return ret;
584}
585
586bool_Bool dc_link_is_hdcp22(struct dc_link *link, enum amd_signal_type signal)
587{
588 bool_Bool ret = false0;
589
590 switch (signal) {
591 case SIGNAL_TYPE_DISPLAY_PORT:
592 case SIGNAL_TYPE_DISPLAY_PORT_MST:
593 ret = (link->hdcp_caps.bcaps.bits.HDCP_CAPABLE &&
594 link->hdcp_caps.rx_caps.fields.byte0.hdcp_capable &&
595 (link->hdcp_caps.rx_caps.fields.version == 0x2)) ? 1 : 0;
596 break;
597 case SIGNAL_TYPE_DVI_SINGLE_LINK:
598 case SIGNAL_TYPE_DVI_DUAL_LINK:
599 case SIGNAL_TYPE_HDMI_TYPE_A:
600 ret = (link->hdcp_caps.rx_caps.fields.version == 0x4) ? 1:0;
601 break;
602 default:
603 break;
604 }
605
606 return ret;
607}
608
609static void query_hdcp_capability(enum amd_signal_type signal, struct dc_link *link)
610{
611 struct hdcp_protection_message msg22;
612 struct hdcp_protection_message msg14;
613
614 memset(&msg22, 0, sizeof(struct hdcp_protection_message))__builtin_memset((&msg22), (0), (sizeof(struct hdcp_protection_message
)))
;
615 memset(&msg14, 0, sizeof(struct hdcp_protection_message))__builtin_memset((&msg14), (0), (sizeof(struct hdcp_protection_message
)))
;
616 memset(link->hdcp_caps.rx_caps.raw, 0,__builtin_memset((link->hdcp_caps.rx_caps.raw), (0), (sizeof
(link->hdcp_caps.rx_caps.raw)))
617 sizeof(link->hdcp_caps.rx_caps.raw))__builtin_memset((link->hdcp_caps.rx_caps.raw), (0), (sizeof
(link->hdcp_caps.rx_caps.raw)))
;
618
619 if ((link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
620 link->ddc->transaction_type ==
621 DDC_TRANSACTION_TYPE_I2C_OVER_AUX) ||
622 link->connector_signal == SIGNAL_TYPE_EDP) {
623 msg22.data = link->hdcp_caps.rx_caps.raw;
624 msg22.length = sizeof(link->hdcp_caps.rx_caps.raw);
625 msg22.msg_id = HDCP_MESSAGE_ID_RX_CAPS;
626 } else {
627 msg22.data = &link->hdcp_caps.rx_caps.fields.version;
628 msg22.length = sizeof(link->hdcp_caps.rx_caps.fields.version);
629 msg22.msg_id = HDCP_MESSAGE_ID_HDCP2VERSION;
630 }
631 msg22.version = HDCP_VERSION_22;
632 msg22.link = HDCP_LINK_PRIMARY;
633 msg22.max_retries = 5;
634 dc_process_hdcp_msg(signal, link, &msg22);
635
636 if (signal == SIGNAL_TYPE_DISPLAY_PORT || signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
637 msg14.data = &link->hdcp_caps.bcaps.raw;
638 msg14.length = sizeof(link->hdcp_caps.bcaps.raw);
639 msg14.msg_id = HDCP_MESSAGE_ID_READ_BCAPS;
640 msg14.version = HDCP_VERSION_14;
641 msg14.link = HDCP_LINK_PRIMARY;
642 msg14.max_retries = 5;
643
644 dc_process_hdcp_msg(signal, link, &msg14);
645 }
646
647}
648#endif
649
650static void read_current_link_settings_on_detect(struct dc_link *link)
651{
652 union lane_count_set lane_count_set = {0};
653 uint8_t link_bw_set;
654 uint8_t link_rate_set;
655 uint32_t read_dpcd_retry_cnt = 10;
656 enum dc_status status = DC_ERROR_UNEXPECTED;
657 int i;
658 union max_down_spread max_down_spread = {0};
659
660 // Read DPCD 00101h to find out the number of lanes currently set
661 for (i = 0; i < read_dpcd_retry_cnt; i++) {
662 status = core_link_read_dpcd(link,
663 DP_LANE_COUNT_SET0x101,
664 &lane_count_set.raw,
665 sizeof(lane_count_set));
666 /* First DPCD read after VDD ON can fail if the particular board
667 * does not have HPD pin wired correctly. So if DPCD read fails,
668 * which it should never happen, retry a few times. Target worst
669 * case scenario of 80 ms.
670 */
671 if (status == DC_OK) {
672 link->cur_link_settings.lane_count =
673 lane_count_set.bits.LANE_COUNT_SET;
674 break;
675 }
676
677 drm_msleep(8)mdelay(8);
678 }
679
680 // Read DPCD 00100h to find if standard link rates are set
681 core_link_read_dpcd(link, DP_LINK_BW_SET0x100,
682 &link_bw_set, sizeof(link_bw_set));
683
684 if (link_bw_set == 0) {
685 if (link->connector_signal == SIGNAL_TYPE_EDP) {
686 /* If standard link rates are not being used,
687 * Read DPCD 00115h to find the edp link rate set used
688 */
689 core_link_read_dpcd(link, DP_LINK_RATE_SET0x115,
690 &link_rate_set, sizeof(link_rate_set));
691
692 // edp_supported_link_rates_count = 0 for DP
693 if (link_rate_set < link->dpcd_caps.edp_supported_link_rates_count) {
694 link->cur_link_settings.link_rate =
695 link->dpcd_caps.edp_supported_link_rates[link_rate_set];
696 link->cur_link_settings.link_rate_set = link_rate_set;
697 link->cur_link_settings.use_link_rate_set = true1;
698 }
699 } else {
700 // Link Rate not found. Seamless boot may not work.
701 ASSERT(false)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.c"
, 701); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
702 }
703 } else {
704 link->cur_link_settings.link_rate = link_bw_set;
705 link->cur_link_settings.use_link_rate_set = false0;
706 }
707 // Read DPCD 00003h to find the max down spread.
708 core_link_read_dpcd(link, DP_MAX_DOWNSPREAD0x003,
709 &max_down_spread.raw, sizeof(max_down_spread));
710 link->cur_link_settings.link_spread =
711 max_down_spread.bits.MAX_DOWN_SPREAD ?
712 LINK_SPREAD_05_DOWNSPREAD_30KHZ : LINK_SPREAD_DISABLED;
713}
714
715static bool_Bool detect_dp(struct dc_link *link,
716 struct display_sink_capability *sink_caps,
717 enum dc_detect_reason reason)
718{
719 struct audio_support *audio_support = &link->dc->res_pool->audio_support;
720
721 sink_caps->signal = link_detect_sink(link, reason);
722 sink_caps->transaction_type =
723 get_ddc_transaction_type(sink_caps->signal);
724
725 if (sink_caps->transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
726 sink_caps->signal = SIGNAL_TYPE_DISPLAY_PORT;
727 if (!detect_dp_sink_caps(link))
728 return false0;
729
730 if (is_dp_branch_device(link))
731 /* DP SST branch */
732 link->type = dc_connection_sst_branch;
733 } else {
734 /* DP passive dongles */
735 sink_caps->signal = dp_passive_dongle_detection(link->ddc,
736 sink_caps,
737 audio_support);
738 link->dpcd_caps.dongle_type = sink_caps->dongle_type;
739 link->dpcd_caps.is_dongle_type_one = sink_caps->is_dongle_type_one;
740 link->dpcd_caps.dpcd_rev.raw = 0;
741 }
742
743 return true1;
744}
745
746static bool_Bool is_same_edid(struct dc_edid *old_edid, struct dc_edid *new_edid)
747{
748 if (old_edid->length != new_edid->length)
749 return false0;
750
751 if (new_edid->length == 0)
752 return false0;
753
754 return (memcmp(old_edid->raw_edid,__builtin_memcmp((old_edid->raw_edid), (new_edid->raw_edid
), (new_edid->length))
755 new_edid->raw_edid, new_edid->length)__builtin_memcmp((old_edid->raw_edid), (new_edid->raw_edid
), (new_edid->length))
== 0);
756}
757
758static bool_Bool wait_for_entering_dp_alt_mode(struct dc_link *link)
759{
760 /**
761 * something is terribly wrong if time out is > 200ms. (5Hz)
762 * 500 microseconds * 400 tries us 200 ms
763 **/
764 unsigned int sleep_time_in_microseconds = 500;
765 unsigned int tries_allowed = 400;
766 bool_Bool is_in_alt_mode;
767 unsigned long long enter_timestamp;
768 unsigned long long finish_timestamp;
769 unsigned long long time_taken_in_ns;
770 int tries_taken;
771
772 DC_LOGGER_INIT(link->ctx->logger);
773
774 if (!link->link_enc->funcs->is_in_alt_mode)
775 return true1;
776
777 is_in_alt_mode = link->link_enc->funcs->is_in_alt_mode(link->link_enc);
778 DC_LOG_WARNING("DP Alt mode state on HPD: %d\n", is_in_alt_mode)printk("\0014" "[" "drm" "] " "DP Alt mode state on HPD: %d\n"
, is_in_alt_mode)
;
779
780 if (is_in_alt_mode)
781 return true1;
782
783 enter_timestamp = dm_get_timestamp(link->ctx);
784
785 for (tries_taken = 0; tries_taken < tries_allowed; tries_taken++) {
786 udelay(sleep_time_in_microseconds);
787 /* ask the link if alt mode is enabled, if so return ok */
788 if (link->link_enc->funcs->is_in_alt_mode(link->link_enc)) {
789 finish_timestamp = dm_get_timestamp(link->ctx);
790 time_taken_in_ns =
791 dm_get_elapse_time_in_ns(link->ctx,
792 finish_timestamp,
793 enter_timestamp);
794 DC_LOG_WARNING("Alt mode entered finished after %llu ms\n",printk("\0014" "[" "drm" "] " "Alt mode entered finished after %llu ms\n"
, div_u64(time_taken_in_ns, 1000000))
795 div_u64(time_taken_in_ns, 1000000))printk("\0014" "[" "drm" "] " "Alt mode entered finished after %llu ms\n"
, div_u64(time_taken_in_ns, 1000000))
;
796 return true1;
797 }
798 }
799 finish_timestamp = dm_get_timestamp(link->ctx);
800 time_taken_in_ns = dm_get_elapse_time_in_ns(link->ctx, finish_timestamp,
801 enter_timestamp);
802 DC_LOG_WARNING("Alt mode has timed out after %llu ms\n",printk("\0014" "[" "drm" "] " "Alt mode has timed out after %llu ms\n"
, div_u64(time_taken_in_ns, 1000000))
803 div_u64(time_taken_in_ns, 1000000))printk("\0014" "[" "drm" "] " "Alt mode has timed out after %llu ms\n"
, div_u64(time_taken_in_ns, 1000000))
;
804 return false0;
805}
806
807static void apply_dpia_mst_dsc_always_on_wa(struct dc_link *link)
808{
809 /* Apply work around for tunneled MST on certain USB4 docks. Always use DSC if dock
810 * reports DSC support.
811 */
812 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
813 link->type == dc_connection_mst_branch &&
814 link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_90CC240x90CC24 &&
815 link->dpcd_caps.branch_hw_revision == DP_BRANCH_HW_REV_200x20 &&
816 link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT &&
817 !link->dc->debug.dpia_debug.bits.disable_mst_dsc_work_around)
818 link->wa_flags.dpia_mst_dsc_always_on = true1;
819}
820
821static void revert_dpia_mst_dsc_always_on_wa(struct dc_link *link)
822{
823 /* Disable work around which keeps DSC on for tunneled MST on certain USB4 docks. */
824 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
825 link->wa_flags.dpia_mst_dsc_always_on = false0;
826}
827
828static bool_Bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason reason)
829{
830 DC_LOGGER_INIT(link->ctx->logger);
831
832 LINK_INFO("link=%d, mst branch is now Connected\n",___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, mst branch is now Connected\n"
, link->link_index)
833 link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, mst branch is now Connected\n"
, link->link_index)
;
834
835 link->type = dc_connection_mst_branch;
836 apply_dpia_mst_dsc_always_on_wa(link);
837
838 dm_helpers_dp_update_branch_info(link->ctx, link);
839 if (dm_helpers_dp_mst_start_top_mgr(link->ctx,
840 link, (reason == DETECT_REASON_BOOT || reason == DETECT_REASON_RESUMEFROMS3S4))) {
841 link_disconnect_sink(link);
842 } else {
843 link->type = dc_connection_sst_branch;
844 }
845
846 return link->type == dc_connection_mst_branch;
847}
848
849bool_Bool reset_cur_dp_mst_topology(struct dc_link *link)
850{
851 DC_LOGGER_INIT(link->ctx->logger);
852
853 LINK_INFO("link=%d, mst branch is now Disconnected\n",___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, mst branch is now Disconnected\n"
, link->link_index)
854 link->link_index)___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, mst branch is now Disconnected\n"
, link->link_index)
;
855
856 revert_dpia_mst_dsc_always_on_wa(link);
857 return dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
858}
859
860static bool_Bool should_prepare_phy_clocks_for_link_verification(const struct dc *dc,
861 enum dc_detect_reason reason)
862{
863 int i;
864 bool_Bool can_apply_seamless_boot = false0;
865
866 for (i = 0; i < dc->current_state->stream_count; i++) {
867 if (dc->current_state->streams[i]->apply_seamless_boot_optimization) {
868 can_apply_seamless_boot = true1;
869 break;
870 }
871 }
872
873 return !can_apply_seamless_boot && reason != DETECT_REASON_BOOT;
874}
875
876static void prepare_phy_clocks_for_destructive_link_verification(const struct dc *dc)
877{
878 dc_z10_restore(dc);
879 clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr);
880}
881
882static void restore_phy_clocks_for_destructive_link_verification(const struct dc *dc)
883{
884 clk_mgr_optimize_pwr_state(dc, dc->clk_mgr);
885}
886
887static void set_all_streams_dpms_off_for_link(struct dc_link *link)
888{
889 int i;
890 struct pipe_ctx *pipe_ctx;
891 struct dc_stream_update stream_update;
892 bool_Bool dpms_off = true1;
893 struct link_resource link_res = {0};
894
895 memset(&stream_update, 0, sizeof(stream_update))__builtin_memset((&stream_update), (0), (sizeof(stream_update
)))
;
896 stream_update.dpms_off = &dpms_off;
897
898 for (i = 0; i < MAX_PIPES6; i++) {
899 pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
900 if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
901 pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
902 stream_update.stream = pipe_ctx->stream;
903 dc_commit_updates_for_stream(link->ctx->dc, NULL((void *)0), 0,
904 pipe_ctx->stream, &stream_update,
905 link->ctx->dc->current_state);
906 }
907 }
908
909 /* link can be also enabled by vbios. In this case it is not recorded
910 * in pipe_ctx. Disable link phy here to make sure it is completely off
911 */
912 dp_disable_link_phy(link, &link_res, link->connector_signal);
913}
914
915static void verify_link_capability_destructive(struct dc_link *link,
916 struct dc_sink *sink,
917 enum dc_detect_reason reason)
918{
919 bool_Bool should_prepare_phy_clocks =
920 should_prepare_phy_clocks_for_link_verification(link->dc, reason);
921
922 if (should_prepare_phy_clocks)
923 prepare_phy_clocks_for_destructive_link_verification(link->dc);
924
925 if (dc_is_dp_signal(link->local_sink->sink_signal)) {
926 struct dc_link_settings known_limit_link_setting =
927 dp_get_max_link_cap(link);
928 set_all_streams_dpms_off_for_link(link);
929 dp_verify_link_cap_with_retries(
930 link, &known_limit_link_setting,
931 LINK_TRAINING_MAX_VERIFY_RETRY);
932 } else {
933 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.c"
, 933); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
934 }
935
936 if (should_prepare_phy_clocks)
937 restore_phy_clocks_for_destructive_link_verification(link->dc);
938}
939
940static void verify_link_capability_non_destructive(struct dc_link *link)
941{
942 if (dc_is_dp_signal(link->local_sink->sink_signal)) {
943 if (dc_is_embedded_signal(link->local_sink->sink_signal) ||
944 link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
945 /* TODO - should we check link encoder's max link caps here?
946 * How do we know which link encoder to check from?
947 */
948 link->verified_link_cap = link->reported_link_cap;
949 else
950 link->verified_link_cap = dp_get_max_link_cap(link);
951 }
952}
953
954static bool_Bool should_verify_link_capability_destructively(struct dc_link *link,
955 enum dc_detect_reason reason)
956{
957 bool_Bool destrictive = false0;
958 struct dc_link_settings max_link_cap;
959 bool_Bool is_link_enc_unavailable = link->link_enc &&
960 link->dc->res_pool->funcs->link_encs_assign &&
961 !link_enc_cfg_is_link_enc_avail(
962 link->ctx->dc,
963 link->link_enc->preferred_engine,
964 link);
965
966 if (dc_is_dp_signal(link->local_sink->sink_signal)) {
967 max_link_cap = dp_get_max_link_cap(link);
968 destrictive = true1;
969
970 if (link->dc->debug.skip_detection_link_training ||
971 dc_is_embedded_signal(link->local_sink->sink_signal) ||
972 link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) {
973 destrictive = false0;
974 } else if (dp_get_link_encoding_format(&max_link_cap) ==
975 DP_8b_10b_ENCODING) {
976 if (link->dpcd_caps.is_mst_capable ||
977 is_link_enc_unavailable) {
978 destrictive = false0;
979 }
980 }
981 }
982
983 return destrictive;
984}
985
986static void verify_link_capability(struct dc_link *link, struct dc_sink *sink,
987 enum dc_detect_reason reason)
988{
989 if (should_verify_link_capability_destructively(link, reason))
990 verify_link_capability_destructive(link, sink, reason);
991 else
992 verify_link_capability_non_destructive(link);
993}
994
995
996/**
997 * detect_link_and_local_sink() - Detect if a sink is attached to a given link
998 *
999 * link->local_sink is created or destroyed as needed.
1000 *
1001 * This does not create remote sinks.
1002 */
1003static bool_Bool detect_link_and_local_sink(struct dc_link *link,
1004 enum dc_detect_reason reason)
1005{
1006 struct dc_sink_init_data sink_init_data = { 0 };
1007 struct display_sink_capability sink_caps = { 0 };
1008 uint32_t i;
1009 bool_Bool converter_disable_audio = false0;
1010 struct audio_support *aud_support = &link->dc->res_pool->audio_support;
1011 bool_Bool same_edid = false0;
1012 enum dc_edid_status edid_status;
1013 struct dc_context *dc_ctx = link->ctx;
1014 struct dc *dc = dc_ctx->dc;
1015 struct dc_sink *sink = NULL((void *)0);
1016 struct dc_sink *prev_sink = NULL((void *)0);
1017 struct dpcd_caps prev_dpcd_caps;
1018 enum dc_connection_type new_connection_type = dc_connection_none;
1019 enum dc_connection_type pre_connection_type = link->type;
1020 const uint32_t post_oui_delay = 30; // 30ms
1021
1022 DC_LOGGER_INIT(link->ctx->logger);
1023
1024 if (dc_is_virtual_signal(link->connector_signal))
1025 return false0;
1026
1027 if (((link->connector_signal == SIGNAL_TYPE_LVDS ||
1028 link->connector_signal == SIGNAL_TYPE_EDP) &&
1029 (!link->dc->config.allow_edp_hotplug_detection)) &&
1030 link->local_sink) {
1031 // need to re-write OUI and brightness in resume case
1032 if (link->connector_signal == SIGNAL_TYPE_EDP &&
1033 (link->dpcd_sink_ext_caps.bits.oled == 1)) {
1034 dpcd_set_source_specific_data(link);
1035 drm_msleep(post_oui_delay)mdelay(post_oui_delay);
1036 dc_link_set_default_brightness_aux(link);
1037 //TODO: use cached
1038 }
1039
1040 return true1;
1041 }
1042
1043 if (!dc_link_detect_sink(link, &new_connection_type)) {
1044 BREAK_TO_DEBUGGER()do { ___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s():%d\n", __func__
, 1044); do {} while (0); } while (0)
;
1045 return false0;
1046 }
1047
1048 prev_sink = link->local_sink;
1049 if (prev_sink) {
1050 dc_sink_retain(prev_sink);
1051 memcpy(&prev_dpcd_caps, &link->dpcd_caps, sizeof(struct dpcd_caps))__builtin_memcpy((&prev_dpcd_caps), (&link->dpcd_caps
), (sizeof(struct dpcd_caps)))
;
1052 }
1053
1054 link_disconnect_sink(link);
1055 if (new_connection_type != dc_connection_none) {
1056 link->type = new_connection_type;
1057 link->link_state_valid = false0;
1058
1059 /* From Disconnected-to-Connected. */
1060 switch (link->connector_signal) {
1061 case SIGNAL_TYPE_HDMI_TYPE_A: {
1062 sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
1063 if (aud_support->hdmi_audio_native)
1064 sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
1065 else
1066 sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
1067 break;
1068 }
1069
1070 case SIGNAL_TYPE_DVI_SINGLE_LINK: {
1071 sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
1072 sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
1073 break;
1074 }
1075
1076 case SIGNAL_TYPE_DVI_DUAL_LINK: {
1077 sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
1078 sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
1079 break;
1080 }
1081
1082 case SIGNAL_TYPE_LVDS: {
1083 sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
1084 sink_caps.signal = SIGNAL_TYPE_LVDS;
1085 break;
1086 }
1087
1088 case SIGNAL_TYPE_EDP: {
1089 read_current_link_settings_on_detect(link);
1090
1091 detect_edp_sink_caps(link);
1092 read_current_link_settings_on_detect(link);
1093
1094 /* Disable power sequence on MIPI panel + converter
1095 */
1096 if (dc->config.enable_mipi_converter_optimization &&
1097 dc_ctx->dce_version == DCN_VERSION_3_01 &&
1098 link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_0022B90x0022B9 &&
1099 memcmp(&link->dpcd_caps.branch_dev_name, DP_SINK_BRANCH_DEV_NAME_7580,__builtin_memcmp((&link->dpcd_caps.branch_dev_name), (
DP_SINK_BRANCH_DEV_NAME_7580), (sizeof(link->dpcd_caps.branch_dev_name
)))
1100 sizeof(link->dpcd_caps.branch_dev_name))__builtin_memcmp((&link->dpcd_caps.branch_dev_name), (
DP_SINK_BRANCH_DEV_NAME_7580), (sizeof(link->dpcd_caps.branch_dev_name
)))
== 0) {
1101 dc->config.edp_no_power_sequencing = true1;
1102
1103 if (!link->dpcd_caps.set_power_state_capable_edp)
1104 link->wa_flags.dp_keep_receiver_powered = true1;
1105 }
1106
1107 sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
1108 sink_caps.signal = SIGNAL_TYPE_EDP;
1109 break;
1110 }
1111
1112 case SIGNAL_TYPE_DISPLAY_PORT: {
1113 /* wa HPD high coming too early*/
1114 if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
1115 link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
1116 /* if alt mode times out, return false */
1117 if (!wait_for_entering_dp_alt_mode(link))
1118 return false0;
1119 }
1120
1121 if (!detect_dp(link, &sink_caps, reason)) {
1122 link->type = pre_connection_type;
1123
1124 if (prev_sink)
1125 dc_sink_release(prev_sink);
1126 return false0;
1127 }
1128
1129 /* Active SST downstream branch device unplug*/
1130 if (link->type == dc_connection_sst_branch &&
1131 link->dpcd_caps.sink_count.bits.SINK_COUNT == 0) {
1132 if (prev_sink)
1133 /* Downstream unplug */
1134 dc_sink_release(prev_sink);
1135 return true1;
1136 }
1137
1138 /* disable audio for non DP to HDMI active sst converter */
1139 if (link->type == dc_connection_sst_branch &&
1140 is_dp_active_dongle(link) &&
1141 (link->dpcd_caps.dongle_type !=
1142 DISPLAY_DONGLE_DP_HDMI_CONVERTER))
1143 converter_disable_audio = true1;
1144
1145 /* limited link rate to HBR3 for DPIA until we implement USB4 V2 */
1146 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA &&
1147 link->reported_link_cap.link_rate > LINK_RATE_HIGH3)
1148 link->reported_link_cap.link_rate = LINK_RATE_HIGH3;
1149 break;
1150 }
1151
1152 default:
1153 DC_ERROR("Invalid connector type! signal:%d\n",do { (void)(dc_ctx); __drm_err("Invalid connector type! signal:%d\n"
, link->connector_signal); } while (0)
1154 link->connector_signal)do { (void)(dc_ctx); __drm_err("Invalid connector type! signal:%d\n"
, link->connector_signal); } while (0)
;
1155 if (prev_sink)
1156 dc_sink_release(prev_sink);
1157 return false0;
1158 } /* switch() */
1159
1160 if (link->dpcd_caps.sink_count.bits.SINK_COUNT)
1161 link->dpcd_sink_count =
1162 link->dpcd_caps.sink_count.bits.SINK_COUNT;
1163 else
1164 link->dpcd_sink_count = 1;
1165
1166 dal_ddc_service_set_transaction_type(link->ddc,
1167 sink_caps.transaction_type);
1168
1169 link->aux_mode =
1170 dal_ddc_service_is_in_aux_transaction_mode(link->ddc);
1171
1172 sink_init_data.link = link;
1173 sink_init_data.sink_signal = sink_caps.signal;
1174
1175 sink = dc_sink_create(&sink_init_data);
1176 if (!sink) {
1177 DC_ERROR("Failed to create sink!\n")do { (void)(dc_ctx); __drm_err("Failed to create sink!\n"); }
while (0)
;
1178 if (prev_sink)
1179 dc_sink_release(prev_sink);
1180 return false0;
1181 }
1182
1183 sink->link->dongle_max_pix_clk = sink_caps.max_hdmi_pixel_clock;
1184 sink->converter_disable_audio = converter_disable_audio;
1185
1186 /* dc_sink_create returns a new reference */
1187 link->local_sink = sink;
1188
1189 edid_status = dm_helpers_read_local_edid(link->ctx,
1190 link, sink);
1191
1192 switch (edid_status) {
1193 case EDID_BAD_CHECKSUM:
1194 DC_LOG_ERROR("EDID checksum invalid.\n")__drm_err("EDID checksum invalid.\n");
1195 break;
1196 case EDID_PARTIAL_VALID:
1197 DC_LOG_ERROR("Partial EDID valid, abandon invalid blocks.\n")__drm_err("Partial EDID valid, abandon invalid blocks.\n");
1198 break;
1199 case EDID_NO_RESPONSE:
1200 DC_LOG_ERROR("No EDID read.\n")__drm_err("No EDID read.\n");
1201 /*
1202 * Abort detection for non-DP connectors if we have
1203 * no EDID
1204 *
1205 * DP needs to report as connected if HDP is high
1206 * even if we have no EDID in order to go to
1207 * fail-safe mode
1208 */
1209 if (dc_is_hdmi_signal(link->connector_signal) ||
1210 dc_is_dvi_signal(link->connector_signal)) {
1211 if (prev_sink)
1212 dc_sink_release(prev_sink);
1213
1214 return false0;
1215 }
1216
1217 if (link->type == dc_connection_sst_branch &&
1218 link->dpcd_caps.dongle_type ==
1219 DISPLAY_DONGLE_DP_VGA_CONVERTER &&
1220 reason == DETECT_REASON_HPDRX) {
1221 /* Abort detection for DP-VGA adapters when EDID
1222 * can't be read and detection reason is VGA-side
1223 * hotplug
1224 */
1225 if (prev_sink)
1226 dc_sink_release(prev_sink);
1227 link_disconnect_sink(link);
1228
1229 return true1;
1230 }
1231
1232 break;
1233 default:
1234 break;
1235 }
1236
1237 // Check if edid is the same
1238 if ((prev_sink) &&
1239 (edid_status == EDID_THE_SAME || edid_status == EDID_OK))
1240 same_edid = is_same_edid(&prev_sink->dc_edid,
1241 &sink->dc_edid);
1242
1243 if (sink->edid_caps.panel_patch.skip_scdc_overwrite)
1244 link->ctx->dc->debug.hdmi20_disable = true1;
1245
1246 if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
1247 sink_caps.transaction_type ==
1248 DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
1249 /*
1250 * TODO debug why Dell 2413 doesn't like
1251 * two link trainings
1252 */
1253#if defined(CONFIG_DRM_AMD_DC_HDCP)
1254 query_hdcp_capability(sink->sink_signal, link);
1255#endif
1256 } else {
1257 // If edid is the same, then discard new sink and revert back to original sink
1258 if (same_edid) {
1259 link_disconnect_remap(prev_sink, link);
1260 sink = prev_sink;
1261 prev_sink = NULL((void *)0);
1262 }
1263#if defined(CONFIG_DRM_AMD_DC_HDCP)
1264 query_hdcp_capability(sink->sink_signal, link);
1265#endif
1266 }
1267
1268 /* HDMI-DVI Dongle */
1269 if (sink->sink_signal == SIGNAL_TYPE_HDMI_TYPE_A &&
1270 !sink->edid_caps.edid_hdmi)
1271 sink->sink_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
1272
1273 if (link->local_sink && dc_is_dp_signal(sink_caps.signal))
1274 dp_trace_init(link);
1275
1276 /* Connectivity log: detection */
1277 for (i = 0; i < sink->dc_edid.length / DC_EDID_BLOCK_SIZE128; i++) {
1278 CONN_DATA_DETECT(link,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%s: [Block %d] "
, sink->edid_caps.display_name, i); } while (0)
1279 &sink->dc_edid.raw_edid[i * DC_EDID_BLOCK_SIZE],do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%s: [Block %d] "
, sink->edid_caps.display_name, i); } while (0)
1280 DC_EDID_BLOCK_SIZE,do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%s: [Block %d] "
, sink->edid_caps.display_name, i); } while (0)
1281 "%s: [Block %d] ", sink->edid_caps.display_name, i)do { (void)(link); ___drm_dbg(((void *)0), DRM_UT_KMS, "%s: [Block %d] "
, sink->edid_caps.display_name, i); } while (0)
;
1282 }
1283
1284 DC_LOG_DETECTION_EDID_PARSER("%s: "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1285 "manufacturer_id = %X, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1286 "product_id = %X, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1287 "serial_number = %X, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1288 "manufacture_week = %d, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1289 "manufacture_year = %d, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1290 "display_name = %s, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1291 "speaker_flag = %d, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1292 "audio_mode_count = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1293 __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1294 sink->edid_caps.manufacturer_id,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1295 sink->edid_caps.product_id,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1296 sink->edid_caps.serial_number,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1297 sink->edid_caps.manufacture_week,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1298 sink->edid_caps.manufacture_year,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1299 sink->edid_caps.display_name,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1300 sink->edid_caps.speaker_flags,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
1301 sink->edid_caps.audio_mode_count)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: " "manufacturer_id = %X, "
"product_id = %X, " "serial_number = %X, " "manufacture_week = %d, "
"manufacture_year = %d, " "display_name = %s, " "speaker_flag = %d, "
"audio_mode_count = %d\n", __func__, sink->edid_caps.manufacturer_id
, sink->edid_caps.product_id, sink->edid_caps.serial_number
, sink->edid_caps.manufacture_week, sink->edid_caps.manufacture_year
, sink->edid_caps.display_name, sink->edid_caps.speaker_flags
, sink->edid_caps.audio_mode_count)
;
1302
1303 for (i = 0; i < sink->edid_caps.audio_mode_count; i++) {
1304 DC_LOG_DETECTION_EDID_PARSER("%s: mode number = %d, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1305 "format_code = %d, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1306 "channel_count = %d, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1307 "sample_rate = %d, "___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1308 "sample_size = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1309 __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1310 i,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1311 sink->edid_caps.audio_modes[i].format_code,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1312 sink->edid_caps.audio_modes[i].channel_count,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1313 sink->edid_caps.audio_modes[i].sample_rate,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
1314 sink->edid_caps.audio_modes[i].sample_size)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: mode number = %d, " "format_code = %d, "
"channel_count = %d, " "sample_rate = %d, " "sample_size = %d\n"
, __func__, i, sink->edid_caps.audio_modes[i].format_code,
sink->edid_caps.audio_modes[i].channel_count, sink->edid_caps
.audio_modes[i].sample_rate, sink->edid_caps.audio_modes[i
].sample_size)
;
1315 }
1316
1317 if (link->connector_signal == SIGNAL_TYPE_EDP) {
1318 /* Init dc_panel_config by HW config */
1319 if (dc_ctx->dc->res_pool->funcs->get_panel_config_defaults)
1320 dc_ctx->dc->res_pool->funcs->get_panel_config_defaults(&link->panel_config);
1321 /* Pickup base DM settings */
1322 dm_helpers_init_panel_settings(dc_ctx, &link->panel_config, sink);
1323 // Override dc_panel_config if system has specific settings
1324 dm_helpers_override_panel_settings(dc_ctx, &link->panel_config);
1325 }
1326
1327 } else {
1328 /* From Connected-to-Disconnected. */
1329 link->type = dc_connection_none;
1330 sink_caps.signal = SIGNAL_TYPE_NONE;
1331 /* When we unplug a passive DP-HDMI dongle connection, dongle_max_pix_clk
1332 * is not cleared. If we emulate a DP signal on this connection, it thinks
1333 * the dongle is still there and limits the number of modes we can emulate.
1334 * Clear dongle_max_pix_clk on disconnect to fix this
1335 */
1336 link->dongle_max_pix_clk = 0;
1337
1338 dc_link_clear_dprx_states(link);
1339 dp_trace_reset(link);
1340 }
1341
1342 LINK_INFO("link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n"
, link->link_index, sink, (sink_caps.signal == SIGNAL_TYPE_NONE
? "Disconnected" : "Connected"), prev_sink, same_edid)
1343 link->link_index, sink,___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n"
, link->link_index, sink, (sink_caps.signal == SIGNAL_TYPE_NONE
? "Disconnected" : "Connected"), prev_sink, same_edid)
1344 (sink_caps.signal ==___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n"
, link->link_index, sink, (sink_caps.signal == SIGNAL_TYPE_NONE
? "Disconnected" : "Connected"), prev_sink, same_edid)
1345 SIGNAL_TYPE_NONE ? "Disconnected" : "Connected"),___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n"
, link->link_index, sink, (sink_caps.signal == SIGNAL_TYPE_NONE
? "Disconnected" : "Connected"), prev_sink, same_edid)
1346 prev_sink, same_edid)___drm_dbg(((void *)0), DRM_UT_KMS, "link=%d, dc_sink_in=%p is now %s prev_sink=%p edid same=%d\n"
, link->link_index, sink, (sink_caps.signal == SIGNAL_TYPE_NONE
? "Disconnected" : "Connected"), prev_sink, same_edid)
;
1347
1348 if (prev_sink)
1349 dc_sink_release(prev_sink);
1350
1351 return true1;
1352}
1353
1354bool_Bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
1355{
1356 bool_Bool is_local_sink_detect_success;
1357 bool_Bool is_delegated_to_mst_top_mgr = false0;
1358 enum dc_connection_type pre_link_type = link->type;
1359
1360 DC_LOGGER_INIT(link->ctx->logger);
1361
1362 is_local_sink_detect_success = detect_link_and_local_sink(link, reason);
1363
1364 if (is_local_sink_detect_success && link->local_sink)
1365 verify_link_capability(link, link->local_sink, reason);
1366
1367 if (is_local_sink_detect_success && link->local_sink &&
1368 dc_is_dp_signal(link->local_sink->sink_signal) &&
1369 link->dpcd_caps.is_mst_capable)
1370 is_delegated_to_mst_top_mgr = discover_dp_mst_topology(link, reason);
1371
1372 DC_LOG_DC("%s: link_index=%d is_local_sink_detect_success=%d pre_link_type=%d link_type=%d\n", __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: link_index=%d is_local_sink_detect_success=%d pre_link_type=%d link_type=%d\n"
, __func__, link->link_index, is_local_sink_detect_success
, pre_link_type, link->type)
1373 link->link_index, is_local_sink_detect_success, pre_link_type, link->type)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: link_index=%d is_local_sink_detect_success=%d pre_link_type=%d link_type=%d\n"
, __func__, link->link_index, is_local_sink_detect_success
, pre_link_type, link->type)
;
1374
1375
1376 if (is_local_sink_detect_success &&
1377 pre_link_type == dc_connection_mst_branch &&
1378 link->type != dc_connection_mst_branch)
1379 is_delegated_to_mst_top_mgr = reset_cur_dp_mst_topology(link);
1380
1381 return is_local_sink_detect_success && !is_delegated_to_mst_top_mgr;
1382}
1383
1384bool_Bool dc_link_get_hpd_state(struct dc_link *dc_link)
1385{
1386 uint32_t state;
1387
1388 dal_gpio_lock_pin(dc_link->hpd_gpio);
1389 dal_gpio_get_value(dc_link->hpd_gpio, &state);
1390 dal_gpio_unlock_pin(dc_link->hpd_gpio);
1391
1392 return state;
1393}
1394
1395static enum hpd_source_id get_hpd_line(struct dc_link *link)
1396{
1397 struct gpio *hpd;
1398 enum hpd_source_id hpd_id;
1399
1400 hpd_id = HPD_SOURCEID_UNKNOWN;
1401
1402 hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id,
1403 link->ctx->gpio_service);
1404
1405 if (hpd) {
1406 switch (dal_irq_get_source(hpd)) {
1407 case DC_IRQ_SOURCE_HPD1:
1408 hpd_id = HPD_SOURCEID1;
1409 break;
1410 case DC_IRQ_SOURCE_HPD2:
1411 hpd_id = HPD_SOURCEID2;
1412 break;
1413 case DC_IRQ_SOURCE_HPD3:
1414 hpd_id = HPD_SOURCEID3;
1415 break;
1416 case DC_IRQ_SOURCE_HPD4:
1417 hpd_id = HPD_SOURCEID4;
1418 break;
1419 case DC_IRQ_SOURCE_HPD5:
1420 hpd_id = HPD_SOURCEID5;
1421 break;
1422 case DC_IRQ_SOURCE_HPD6:
1423 hpd_id = HPD_SOURCEID6;
1424 break;
1425 default:
1426 BREAK_TO_DEBUGGER()do { ___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s():%d\n", __func__
, 1426); do {} while (0); } while (0)
;
1427 break;
1428 }
1429
1430 dal_gpio_destroy_irq(&hpd);
1431 }
1432
1433 return hpd_id;
1434}
1435
1436static enum channel_id get_ddc_line(struct dc_link *link)
1437{
1438 struct ddc *ddc;
1439 enum channel_id channel;
1440
1441 channel = CHANNEL_ID_UNKNOWN;
1442
1443 ddc = dal_ddc_service_get_ddc_pin(link->ddc);
1444
1445 if (ddc) {
1446 switch (dal_ddc_get_line(ddc)) {
1447 case GPIO_DDC_LINE_DDC1:
1448 channel = CHANNEL_ID_DDC1;
1449 break;
1450 case GPIO_DDC_LINE_DDC2:
1451 channel = CHANNEL_ID_DDC2;
1452 break;
1453 case GPIO_DDC_LINE_DDC3:
1454 channel = CHANNEL_ID_DDC3;
1455 break;
1456 case GPIO_DDC_LINE_DDC4:
1457 channel = CHANNEL_ID_DDC4;
1458 break;
1459 case GPIO_DDC_LINE_DDC5:
1460 channel = CHANNEL_ID_DDC5;
1461 break;
1462 case GPIO_DDC_LINE_DDC6:
1463 channel = CHANNEL_ID_DDC6;
1464 break;
1465 case GPIO_DDC_LINE_DDC_VGA:
1466 channel = CHANNEL_ID_DDC_VGA;
1467 break;
1468 case GPIO_DDC_LINE_I2C_PAD:
1469 channel = CHANNEL_ID_I2C_PAD;
1470 break;
1471 default:
1472 BREAK_TO_DEBUGGER()do { ___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s():%d\n", __func__
, 1472); do {} while (0); } while (0)
;
1473 break;
1474 }
1475 }
1476
1477 return channel;
1478}
1479
1480static enum transmitter translate_encoder_to_transmitter(struct graphics_object_id encoder)
1481{
1482 switch (encoder.id) {
1483 case ENCODER_ID_INTERNAL_UNIPHY:
1484 switch (encoder.enum_id) {
1485 case ENUM_ID_1:
1486 return TRANSMITTER_UNIPHY_A;
1487 case ENUM_ID_2:
1488 return TRANSMITTER_UNIPHY_B;
1489 default:
1490 return TRANSMITTER_UNKNOWN;
1491 }
1492 break;
1493 case ENCODER_ID_INTERNAL_UNIPHY1:
1494 switch (encoder.enum_id) {
1495 case ENUM_ID_1:
1496 return TRANSMITTER_UNIPHY_C;
1497 case ENUM_ID_2:
1498 return TRANSMITTER_UNIPHY_D;
1499 default:
1500 return TRANSMITTER_UNKNOWN;
1501 }
1502 break;
1503 case ENCODER_ID_INTERNAL_UNIPHY2:
1504 switch (encoder.enum_id) {
1505 case ENUM_ID_1:
1506 return TRANSMITTER_UNIPHY_E;
1507 case ENUM_ID_2:
1508 return TRANSMITTER_UNIPHY_F;
1509 default:
1510 return TRANSMITTER_UNKNOWN;
1511 }
1512 break;
1513 case ENCODER_ID_INTERNAL_UNIPHY3:
1514 switch (encoder.enum_id) {
1515 case ENUM_ID_1:
1516 return TRANSMITTER_UNIPHY_G;
1517 default:
1518 return TRANSMITTER_UNKNOWN;
1519 }
1520 break;
1521 case ENCODER_ID_EXTERNAL_NUTMEG:
1522 switch (encoder.enum_id) {
1523 case ENUM_ID_1:
1524 return TRANSMITTER_NUTMEG_CRT;
1525 default:
1526 return TRANSMITTER_UNKNOWN;
1527 }
1528 break;
1529 case ENCODER_ID_EXTERNAL_TRAVIS:
1530 switch (encoder.enum_id) {
1531 case ENUM_ID_1:
1532 return TRANSMITTER_TRAVIS_CRT;
1533 case ENUM_ID_2:
1534 return TRANSMITTER_TRAVIS_LCD;
1535 default:
1536 return TRANSMITTER_UNKNOWN;
1537 }
1538 break;
1539 default:
1540 return TRANSMITTER_UNKNOWN;
1541 }
1542}
1543
1544static bool_Bool dc_link_construct_legacy(struct dc_link *link,
1545 const struct link_init_data *init_params)
1546{
1547 uint8_t i;
1548 struct ddc_service_init_data ddc_service_init_data = { 0 };
1549 struct dc_context *dc_ctx = init_params->ctx;
1550 struct encoder_init_data enc_init_data = { 0 };
1551 struct panel_cntl_init_data panel_cntl_init_data = { 0 };
1552 struct integrated_info *info;
1553 struct dc_bios *bios = init_params->dc->ctx->dc_bios;
1554 const struct dc_vbios_funcs *bp_funcs = bios->funcs;
1555 struct bp_disp_connector_caps_info disp_connect_caps_info = { 0 };
1556
1557 DC_LOGGER_INIT(dc_ctx->logger);
1558
1559 info = kzalloc(sizeof(*info), GFP_KERNEL(0x0001 | 0x0004));
1560 if (!info)
1561 goto create_fail;
1562
1563 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
1564 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
1565
1566 link->link_status.dpcd_caps = &link->dpcd_caps;
1567
1568 link->dc = init_params->dc;
1569 link->ctx = dc_ctx;
1570 link->link_index = init_params->link_index;
1571
1572 memset(&link->preferred_training_settings, 0,__builtin_memset((&link->preferred_training_settings),
(0), (sizeof(struct dc_link_training_overrides)))
1573 sizeof(struct dc_link_training_overrides))__builtin_memset((&link->preferred_training_settings),
(0), (sizeof(struct dc_link_training_overrides)))
;
1574 memset(&link->preferred_link_setting, 0,__builtin_memset((&link->preferred_link_setting), (0),
(sizeof(struct dc_link_settings)))
1575 sizeof(struct dc_link_settings))__builtin_memset((&link->preferred_link_setting), (0),
(sizeof(struct dc_link_settings)))
;
1576
1577 link->link_id =
1578 bios->funcs->get_connector_id(bios, init_params->connector_index);
1579
1580 link->ep_type = DISPLAY_ENDPOINT_PHY;
1581
1582 DC_LOG_DC("BIOS object table - link_id: %d", link->link_id.id)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - link_id: %d"
, link->link_id.id)
;
1583
1584 if (bios->funcs->get_disp_connector_caps_info) {
1585 bios->funcs->get_disp_connector_caps_info(bios, link->link_id, &disp_connect_caps_info);
1586 link->is_internal_display = disp_connect_caps_info.INTERNAL_DISPLAY;
1587 DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - is_internal_display: %d"
, link->is_internal_display)
;
1588 }
1589
1590 if (link->link_id.type != OBJECT_TYPE_CONNECTOR) {
1591 dm_output_to_console("%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n"
, __func__, init_params->connector_index, link->link_id
.type, OBJECT_TYPE_CONNECTOR)
1592 __func__, init_params->connector_index,___drm_dbg(((void *)0), DRM_UT_KMS, "%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n"
, __func__, init_params->connector_index, link->link_id
.type, OBJECT_TYPE_CONNECTOR)
1593 link->link_id.type, OBJECT_TYPE_CONNECTOR)___drm_dbg(((void *)0), DRM_UT_KMS, "%s: Invalid Connector ObjectID from Adapter Service for connector index:%d! type %d expected %d\n"
, __func__, init_params->connector_index, link->link_id
.type, OBJECT_TYPE_CONNECTOR)
;
1594 goto create_fail;
1595 }
1596
1597 if (link->dc->res_pool->funcs->link_init)
1598 link->dc->res_pool->funcs->link_init(link);
1599
1600 link->hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id,
1601 link->ctx->gpio_service);
1602
1603 if (link->hpd_gpio) {
1604 dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT);
1605 dal_gpio_unlock_pin(link->hpd_gpio);
1606 link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio);
1607
1608 DC_LOG_DC("BIOS object table - hpd_gpio id: %d", link->hpd_gpio->id)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - hpd_gpio id: %d"
, link->hpd_gpio->id)
;
1609 DC_LOG_DC("BIOS object table - hpd_gpio en: %d", link->hpd_gpio->en)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - hpd_gpio en: %d"
, link->hpd_gpio->en)
;
1610 }
1611
1612 switch (link->link_id.id) {
1613 case CONNECTOR_ID_HDMI_TYPE_A:
1614 link->connector_signal = SIGNAL_TYPE_HDMI_TYPE_A;
1615
1616 break;
1617 case CONNECTOR_ID_SINGLE_LINK_DVID:
1618 case CONNECTOR_ID_SINGLE_LINK_DVII:
1619 link->connector_signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
1620 break;
1621 case CONNECTOR_ID_DUAL_LINK_DVID:
1622 case CONNECTOR_ID_DUAL_LINK_DVII:
1623 link->connector_signal = SIGNAL_TYPE_DVI_DUAL_LINK;
1624 break;
1625 case CONNECTOR_ID_DISPLAY_PORT:
1626 case CONNECTOR_ID_USBC:
1627 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
1628
1629 if (link->hpd_gpio)
1630 link->irq_source_hpd_rx =
1631 dal_irq_get_rx_source(link->hpd_gpio);
1632
1633 break;
1634 case CONNECTOR_ID_EDP:
1635 link->connector_signal = SIGNAL_TYPE_EDP;
1636
1637 if (link->hpd_gpio) {
1638 if (!link->dc->config.allow_edp_hotplug_detection)
1639 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
1640
1641 switch (link->dc->config.allow_edp_hotplug_detection) {
1642 case HPD_EN_FOR_ALL_EDP:
1643 link->irq_source_hpd_rx =
1644 dal_irq_get_rx_source(link->hpd_gpio);
1645 break;
1646 case HPD_EN_FOR_PRIMARY_EDP_ONLY:
1647 if (link->link_index == 0)
1648 link->irq_source_hpd_rx =
1649 dal_irq_get_rx_source(link->hpd_gpio);
1650 else
1651 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
1652 break;
1653 case HPD_EN_FOR_SECONDARY_EDP_ONLY:
1654 if (link->link_index == 1)
1655 link->irq_source_hpd_rx =
1656 dal_irq_get_rx_source(link->hpd_gpio);
1657 else
1658 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
1659 break;
1660 default:
1661 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
1662 break;
1663 }
1664 }
1665
1666 break;
1667 case CONNECTOR_ID_LVDS:
1668 link->connector_signal = SIGNAL_TYPE_LVDS;
1669 break;
1670 default:
1671 DC_LOG_WARNING("Unsupported Connector type:%d!\n",printk("\0014" "[" "drm" "] " "Unsupported Connector type:%d!\n"
, link->link_id.id)
1672 link->link_id.id)printk("\0014" "[" "drm" "] " "Unsupported Connector type:%d!\n"
, link->link_id.id)
;
1673 goto create_fail;
1674 }
1675
1676 /* TODO: #DAL3 Implement id to str function.*/
1677 LINK_INFO("Connector[%d] description:"___drm_dbg(((void *)0), DRM_UT_KMS, "Connector[%d] description:"
"signal %d\n", init_params->connector_index, link->connector_signal
)
1678 "signal %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "Connector[%d] description:"
"signal %d\n", init_params->connector_index, link->connector_signal
)
1679 init_params->connector_index,___drm_dbg(((void *)0), DRM_UT_KMS, "Connector[%d] description:"
"signal %d\n", init_params->connector_index, link->connector_signal
)
1680 link->connector_signal)___drm_dbg(((void *)0), DRM_UT_KMS, "Connector[%d] description:"
"signal %d\n", init_params->connector_index, link->connector_signal
)
;
1681
1682 ddc_service_init_data.ctx = link->ctx;
1683 ddc_service_init_data.id = link->link_id;
1684 ddc_service_init_data.link = link;
1685 link->ddc = dal_ddc_service_create(&ddc_service_init_data);
1686
1687 if (!link->ddc) {
1688 DC_ERROR("Failed to create ddc_service!\n")do { (void)(dc_ctx); __drm_err("Failed to create ddc_service!\n"
); } while (0)
;
1689 goto ddc_create_fail;
1690 }
1691
1692 if (!link->ddc->ddc_pin) {
1693 DC_ERROR("Failed to get I2C info for connector!\n")do { (void)(dc_ctx); __drm_err("Failed to get I2C info for connector!\n"
); } while (0)
;
1694 goto ddc_create_fail;
1695 }
1696
1697 link->ddc_hw_inst =
1698 dal_ddc_get_line(dal_ddc_service_get_ddc_pin(link->ddc));
1699
1700
1701 if (link->dc->res_pool->funcs->panel_cntl_create &&
1702 (link->link_id.id == CONNECTOR_ID_EDP ||
1703 link->link_id.id == CONNECTOR_ID_LVDS)) {
1704 panel_cntl_init_data.ctx = dc_ctx;
1705 panel_cntl_init_data.inst =
1706 panel_cntl_init_data.ctx->dc_edp_id_count;
1707 link->panel_cntl =
1708 link->dc->res_pool->funcs->panel_cntl_create(
1709 &panel_cntl_init_data);
1710 panel_cntl_init_data.ctx->dc_edp_id_count++;
1711
1712 if (link->panel_cntl == NULL((void *)0)) {
1713 DC_ERROR("Failed to create link panel_cntl!\n")do { (void)(dc_ctx); __drm_err("Failed to create link panel_cntl!\n"
); } while (0)
;
1714 goto panel_cntl_create_fail;
1715 }
1716 }
1717
1718 enc_init_data.ctx = dc_ctx;
1719 bp_funcs->get_src_obj(dc_ctx->dc_bios, link->link_id, 0,
1720 &enc_init_data.encoder);
1721 enc_init_data.connector = link->link_id;
1722 enc_init_data.channel = get_ddc_line(link);
1723 enc_init_data.hpd_source = get_hpd_line(link);
1724
1725 link->hpd_src = enc_init_data.hpd_source;
1726
1727 enc_init_data.transmitter =
1728 translate_encoder_to_transmitter(enc_init_data.encoder);
1729 link->link_enc =
1730 link->dc->res_pool->funcs->link_enc_create(dc_ctx, &enc_init_data);
1731
1732 if (!link->link_enc) {
1733 DC_ERROR("Failed to create link encoder!\n")do { (void)(dc_ctx); __drm_err("Failed to create link encoder!\n"
); } while (0)
;
1734 goto link_enc_create_fail;
1735 }
1736
1737 DC_LOG_DC("BIOS object table - DP_IS_USB_C: %d", link->link_enc->features.flags.bits.DP_IS_USB_C)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - DP_IS_USB_C: %d"
, link->link_enc->features.flags.bits.DP_IS_USB_C)
;
1738 DC_LOG_DC("BIOS object table - IS_DP2_CAPABLE: %d", link->link_enc->features.flags.bits.IS_DP2_CAPABLE)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - IS_DP2_CAPABLE: %d"
, link->link_enc->features.flags.bits.IS_DP2_CAPABLE)
;
1739
1740 /* Update link encoder tracking variables. These are used for the dynamic
1741 * assignment of link encoders to streams.
1742 */
1743 link->eng_id = link->link_enc->preferred_engine;
1744 link->dc->res_pool->link_encoders[link->eng_id - ENGINE_ID_DIGA] = link->link_enc;
1745 link->dc->res_pool->dig_link_enc_count++;
1746
1747 link->link_enc_hw_inst = link->link_enc->transmitter;
1748
1749 for (i = 0; i < 4; i++) {
1750 if (bp_funcs->get_device_tag(dc_ctx->dc_bios,
1751 link->link_id, i,
1752 &link->device_tag) != BP_RESULT_OK) {
1753 DC_ERROR("Failed to find device tag!\n")do { (void)(dc_ctx); __drm_err("Failed to find device tag!\n"
); } while (0)
;
1754 goto device_tag_fail;
1755 }
1756
1757 /* Look for device tag that matches connector signal,
1758 * CRT for rgb, LCD for other supported signal tyes
1759 */
1760 if (!bp_funcs->is_device_id_supported(dc_ctx->dc_bios,
1761 link->device_tag.dev_id))
1762 continue;
1763 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT &&
1764 link->connector_signal != SIGNAL_TYPE_RGB)
1765 continue;
1766 if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD &&
1767 link->connector_signal == SIGNAL_TYPE_RGB)
1768 continue;
1769
1770 DC_LOG_DC("BIOS object table - device_tag.acpi_device: %d", link->device_tag.acpi_device)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - device_tag.acpi_device: %d"
, link->device_tag.acpi_device)
;
1771 DC_LOG_DC("BIOS object table - device_tag.dev_id.device_type: %d", link->device_tag.dev_id.device_type)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - device_tag.dev_id.device_type: %d"
, link->device_tag.dev_id.device_type)
;
1772 DC_LOG_DC("BIOS object table - device_tag.dev_id.enum_id: %d", link->device_tag.dev_id.enum_id)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - device_tag.dev_id.enum_id: %d"
, link->device_tag.dev_id.enum_id)
;
1773 break;
1774 }
1775
1776 if (bios->integrated_info)
1777 memcpy(info, bios->integrated_info, sizeof(*info))__builtin_memcpy((info), (bios->integrated_info), (sizeof(
*info)))
;
1778
1779 /* Look for channel mapping corresponding to connector and device tag */
1780 for (i = 0; i < MAX_NUMBER_OF_EXT_DISPLAY_PATH7; i++) {
1781 struct external_display_path *path =
1782 &info->ext_disp_conn_info.path[i];
1783
1784 if (path->device_connector_id.enum_id == link->link_id.enum_id &&
1785 path->device_connector_id.id == link->link_id.id &&
1786 path->device_connector_id.type == link->link_id.type) {
1787 if (link->device_tag.acpi_device != 0 &&
1788 path->device_acpi_enum == link->device_tag.acpi_device) {
1789 link->ddi_channel_mapping = path->channel_mapping;
1790 link->chip_caps = path->caps;
1791 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - ddi_channel_mapping: 0x%04X"
, link->ddi_channel_mapping.raw)
;
1792 DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - chip_caps: %d"
, link->chip_caps)
;
1793 } else if (path->device_tag ==
1794 link->device_tag.dev_id.raw_device_tag) {
1795 link->ddi_channel_mapping = path->channel_mapping;
1796 link->chip_caps = path->caps;
1797 DC_LOG_DC("BIOS object table - ddi_channel_mapping: 0x%04X", link->ddi_channel_mapping.raw)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - ddi_channel_mapping: 0x%04X"
, link->ddi_channel_mapping.raw)
;
1798 DC_LOG_DC("BIOS object table - chip_caps: %d", link->chip_caps)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - chip_caps: %d"
, link->chip_caps)
;
1799 }
1800
1801 if (link->chip_caps & EXT_DISPLAY_PATH_CAPS__DP_FIXED_VS_EN) {
1802 link->bios_forced_drive_settings.VOLTAGE_SWING =
1803 (info->ext_disp_conn_info.fixdpvoltageswing & 0x3);
1804 link->bios_forced_drive_settings.PRE_EMPHASIS =
1805 ((info->ext_disp_conn_info.fixdpvoltageswing >> 2) & 0x3);
1806 }
1807
1808 break;
1809 }
1810 }
1811
1812 if (bios->funcs->get_atom_dc_golden_table)
1813 bios->funcs->get_atom_dc_golden_table(bios);
1814
1815 /*
1816 * TODO check if GPIO programmed correctly
1817 *
1818 * If GPIO isn't programmed correctly HPD might not rise or drain
1819 * fast enough, leading to bounces.
1820 */
1821 program_hpd_filter(link);
1822
1823 link->psr_settings.psr_vtotal_control_support = false0;
1824 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
1825
1826 DC_LOG_DC("BIOS object table - %s finished successfully.\n", __func__)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - %s finished successfully.\n"
, __func__)
;
1827 kfree(info);
1828 return true1;
1829device_tag_fail:
1830 link->link_enc->funcs->destroy(&link->link_enc);
1831link_enc_create_fail:
1832 if (link->panel_cntl != NULL((void *)0))
1833 link->panel_cntl->funcs->destroy(&link->panel_cntl);
1834panel_cntl_create_fail:
1835 dal_ddc_service_destroy(&link->ddc);
1836ddc_create_fail:
1837create_fail:
1838
1839 if (link->hpd_gpio) {
1840 dal_gpio_destroy_irq(&link->hpd_gpio);
1841 link->hpd_gpio = NULL((void *)0);
1842 }
1843
1844 DC_LOG_DC("BIOS object table - %s failed.\n", __func__)___drm_dbg(((void *)0), DRM_UT_KMS, "BIOS object table - %s failed.\n"
, __func__)
;
1845 kfree(info);
1846
1847 return false0;
1848}
1849
1850static bool_Bool dc_link_construct_dpia(struct dc_link *link,
1851 const struct link_init_data *init_params)
1852{
1853 struct ddc_service_init_data ddc_service_init_data = { 0 };
1854 struct dc_context *dc_ctx = init_params->ctx;
1855
1856 DC_LOGGER_INIT(dc_ctx->logger);
1857
1858 /* Initialized irq source for hpd and hpd rx */
1859 link->irq_source_hpd = DC_IRQ_SOURCE_INVALID;
1860 link->irq_source_hpd_rx = DC_IRQ_SOURCE_INVALID;
1861 link->link_status.dpcd_caps = &link->dpcd_caps;
1862
1863 link->dc = init_params->dc;
1864 link->ctx = dc_ctx;
1865 link->link_index = init_params->link_index;
1866
1867 memset(&link->preferred_training_settings, 0,__builtin_memset((&link->preferred_training_settings),
(0), (sizeof(struct dc_link_training_overrides)))
1868 sizeof(struct dc_link_training_overrides))__builtin_memset((&link->preferred_training_settings),
(0), (sizeof(struct dc_link_training_overrides)))
;
1869 memset(&link->preferred_link_setting, 0,__builtin_memset((&link->preferred_link_setting), (0),
(sizeof(struct dc_link_settings)))
1870 sizeof(struct dc_link_settings))__builtin_memset((&link->preferred_link_setting), (0),
(sizeof(struct dc_link_settings)))
;
1871
1872 /* Dummy Init for linkid */
1873 link->link_id.type = OBJECT_TYPE_CONNECTOR;
1874 link->link_id.id = CONNECTOR_ID_DISPLAY_PORT;
1875 link->link_id.enum_id = ENUM_ID_1 + init_params->connector_index;
1876 link->is_internal_display = false0;
1877 link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
1878 LINK_INFO("Connector[%d] description:signal %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "Connector[%d] description:signal %d\n"
, init_params->connector_index, link->connector_signal)
1879 init_params->connector_index,___drm_dbg(((void *)0), DRM_UT_KMS, "Connector[%d] description:signal %d\n"
, init_params->connector_index, link->connector_signal)
1880 link->connector_signal)___drm_dbg(((void *)0), DRM_UT_KMS, "Connector[%d] description:signal %d\n"
, init_params->connector_index, link->connector_signal)
;
1881
1882 link->ep_type = DISPLAY_ENDPOINT_USB4_DPIA;
1883 link->is_dig_mapping_flexible = true1;
1884
1885 /* TODO: Initialize link : funcs->link_init */
1886
1887 ddc_service_init_data.ctx = link->ctx;
1888 ddc_service_init_data.id = link->link_id;
1889 ddc_service_init_data.link = link;
1890 /* Set indicator for dpia link so that ddc won't be created */
1891 ddc_service_init_data.is_dpia_link = true1;
1892
1893 link->ddc = dal_ddc_service_create(&ddc_service_init_data);
1894 if (!link->ddc) {
1895 DC_ERROR("Failed to create ddc_service!\n")do { (void)(dc_ctx); __drm_err("Failed to create ddc_service!\n"
); } while (0)
;
1896 goto ddc_create_fail;
1897 }
1898
1899 /* Set dpia port index : 0 to number of dpia ports */
1900 link->ddc_hw_inst = init_params->connector_index;
1901
1902 /* TODO: Create link encoder */
1903
1904 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
1905
1906 /* Some docks seem to NAK I2C writes to segment pointer with mot=0. */
1907 link->wa_flags.dp_mot_reset_segment = true1;
1908
1909 return true1;
1910
1911ddc_create_fail:
1912 return false0;
1913}
1914
1915static bool_Bool dc_link_construct(struct dc_link *link,
1916 const struct link_init_data *init_params)
1917{
1918 /* Handle dpia case */
1919 if (init_params->is_dpia_link)
1920 return dc_link_construct_dpia(link, init_params);
1921 else
1922 return dc_link_construct_legacy(link, init_params);
1923}
1924/*******************************************************************************
1925 * Public functions
1926 ******************************************************************************/
1927struct dc_link *link_create(const struct link_init_data *init_params)
1928{
1929 struct dc_link *link =
1930 kzalloc(sizeof(*link), GFP_KERNEL(0x0001 | 0x0004));
1931
1932 if (NULL((void *)0) == link)
1933 goto alloc_fail;
1934
1935 if (false0 == dc_link_construct(link, init_params))
1936 goto construct_fail;
1937
1938 return link;
1939
1940construct_fail:
1941 kfree(link);
1942
1943alloc_fail:
1944 return NULL((void *)0);
1945}
1946
1947void link_destroy(struct dc_link **link)
1948{
1949 dc_link_destruct(*link);
1950 kfree(*link);
1951 *link = NULL((void *)0);
1952}
1953
1954static void enable_stream_features(struct pipe_ctx *pipe_ctx)
1955{
1956 struct dc_stream_state *stream = pipe_ctx->stream;
1957
1958 if (pipe_ctx->stream->signal != SIGNAL_TYPE_DISPLAY_PORT_MST) {
1959 struct dc_link *link = stream->link;
1960 union down_spread_ctrl old_downspread;
1961 union down_spread_ctrl new_downspread;
1962
1963 memset(&old_downspread, 0, sizeof(old_downspread))__builtin_memset((&old_downspread), (0), (sizeof(old_downspread
)))
;
1964
1965 core_link_read_dpcd(link, DP_DOWNSPREAD_CTRL0x107,
1966 &old_downspread.raw, sizeof(old_downspread));
1967
1968 new_downspread.raw = old_downspread.raw;
1969
1970 new_downspread.bits.IGNORE_MSA_TIMING_PARAM =
1971 (stream->ignore_msa_timing_param) ? 1 : 0;
1972
1973 if (new_downspread.raw != old_downspread.raw) {
1974 core_link_write_dpcd(link, DP_DOWNSPREAD_CTRL0x107,
1975 &new_downspread.raw, sizeof(new_downspread));
1976 }
1977
1978 } else {
1979 dm_helpers_mst_enable_stream_features(stream);
1980 }
1981}
1982
1983static enum dc_status enable_link_dp(struct dc_state *state,
1984 struct pipe_ctx *pipe_ctx)
1985{
1986 struct dc_stream_state *stream = pipe_ctx->stream;
1987 enum dc_status status;
1988 bool_Bool skip_video_pattern;
1989 struct dc_link *link = stream->link;
1990 const struct dc_link_settings *link_settings =
1991 &pipe_ctx->link_config.dp_link_settings;
1992 bool_Bool fec_enable;
1993 int i;
1994 bool_Bool apply_seamless_boot_optimization = false0;
1995 uint32_t bl_oled_enable_delay = 50; // in ms
1996 uint32_t post_oui_delay = 30; // 30ms
1997 /* Reduce link bandwidth between failed link training attempts. */
1998 bool_Bool do_fallback = false0;
1999
2000 // check for seamless boot
2001 for (i = 0; i < state->stream_count; i++) {
2002 if (state->streams[i]->apply_seamless_boot_optimization) {
2003 apply_seamless_boot_optimization = true1;
2004 break;
2005 }
2006 }
2007
2008 /* Train with fallback when enabling DPIA link. Conventional links are
2009 * trained with fallback during sink detection.
2010 */
2011 if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
2012 do_fallback = true1;
2013
2014 /*
2015 * Temporary w/a to get DP2.0 link rates to work with SST.
2016 * TODO DP2.0 - Workaround: Remove w/a if and when the issue is resolved.
2017 */
2018 if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING &&
2019 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
2020 link->dc->debug.set_mst_en_for_sst) {
2021 dp_enable_mst_on_sink(link, true1);
2022 }
2023
2024 if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP) {
2025 /*in case it is not on*/
2026 if (!link->dc->config.edp_no_power_sequencing)
2027 link->dc->hwss.edp_power_control(link, true1);
2028 link->dc->hwss.edp_wait_for_hpd_ready(link, true1);
2029 }
2030
2031 if (dp_get_link_encoding_format(link_settings) == DP_128b_132b_ENCODING) {
2032 /* TODO - DP2.0 HW: calculate 32 symbol clock for HPO encoder */
2033 } else {
2034 pipe_ctx->stream_res.pix_clk_params.requested_sym_clk =
2035 link_settings->link_rate * LINK_RATE_REF_FREQ_IN_KHZ;
2036 if (state->clk_mgr && !apply_seamless_boot_optimization)
2037 state->clk_mgr->funcs->update_clocks(state->clk_mgr,
2038 state, false0);
2039 }
2040
2041 // during mode switch we do DP_SET_POWER off then on, and OUI is lost
2042 dpcd_set_source_specific_data(link);
2043 if (link->dpcd_sink_ext_caps.raw != 0) {
2044 post_oui_delay += link->panel_config.pps.extra_post_OUI_ms;
2045 drm_msleep(post_oui_delay)mdelay(post_oui_delay);
2046 }
2047
2048 // similarly, mode switch can cause loss of cable ID
2049 dpcd_write_cable_id_to_dprx(link);
2050
2051 skip_video_pattern = true1;
2052
2053 if (link_settings->link_rate == LINK_RATE_LOW)
2054 skip_video_pattern = false0;
2055
2056 if (perform_link_training_with_retries(link_settings,
2057 skip_video_pattern,
2058 LINK_TRAINING_ATTEMPTS4,
2059 pipe_ctx,
2060 pipe_ctx->stream->signal,
2061 do_fallback)) {
2062 status = DC_OK;
2063 } else {
2064 status = DC_FAIL_DP_LINK_TRAINING;
2065 }
2066
2067 if (link->preferred_training_settings.fec_enable)
2068 fec_enable = *link->preferred_training_settings.fec_enable;
2069 else
2070 fec_enable = true1;
2071
2072 if (dp_get_link_encoding_format(link_settings) == DP_8b_10b_ENCODING)
2073 dp_set_fec_enable(link, fec_enable);
2074
2075 // during mode set we do DP_SET_POWER off then on, aux writes are lost
2076 if (link->dpcd_sink_ext_caps.bits.oled == 1 ||
2077 link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1 ||
2078 link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1) {
2079 dc_link_set_default_brightness_aux(link); // TODO: use cached if known
2080 if (link->dpcd_sink_ext_caps.bits.oled == 1)
2081 drm_msleep(bl_oled_enable_delay)mdelay(bl_oled_enable_delay);
2082 dc_link_backlight_enable_aux(link, true1);
2083 }
2084
2085 return status;
2086}
2087
2088static enum dc_status enable_link_edp(
2089 struct dc_state *state,
2090 struct pipe_ctx *pipe_ctx)
2091{
2092 return enable_link_dp(state, pipe_ctx);
2093}
2094
2095static enum dc_status enable_link_dp_mst(
2096 struct dc_state *state,
2097 struct pipe_ctx *pipe_ctx)
2098{
2099 struct dc_link *link = pipe_ctx->stream->link;
2100 unsigned char mstm_cntl;
2101
2102 /* sink signal type after MST branch is MST. Multiple MST sinks
2103 * share one link. Link DP PHY is enable or training only once.
2104 */
2105 if (link->link_status.link_active)
2106 return DC_OK;
2107
2108 /* clear payload table */
2109 core_link_read_dpcd(link, DP_MSTM_CTRL0x111, &mstm_cntl, 1);
2110 if (mstm_cntl & DP_MST_EN(1 << 0))
2111 dm_helpers_dp_mst_clear_payload_allocation_table(link->ctx, link);
2112
2113 /* to make sure the pending down rep can be processed
2114 * before enabling the link
2115 */
2116 dm_helpers_dp_mst_poll_pending_down_reply(link->ctx, link);
2117
2118 /* set the sink to MST mode before enabling the link */
2119 dp_enable_mst_on_sink(link, true1);
2120
2121 return enable_link_dp(state, pipe_ctx);
2122}
2123
2124void dc_link_blank_all_dp_displays(struct dc *dc)
2125{
2126 unsigned int i;
2127 uint8_t dpcd_power_state = '\0';
2128 enum dc_status status = DC_ERROR_UNEXPECTED;
2129
2130 for (i = 0; i < dc->link_count; i++) {
2131 if ((dc->links[i]->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) ||
2132 (dc->links[i]->priv == NULL((void *)0)) || (dc->links[i]->local_sink == NULL((void *)0)))
2133 continue;
2134
2135 /* DP 2.0 spec requires that we read LTTPR caps first */
2136 dp_retrieve_lttpr_cap(dc->links[i]);
2137 /* if any of the displays are lit up turn them off */
2138 status = core_link_read_dpcd(dc->links[i], DP_SET_POWER0x600,
2139 &dpcd_power_state, sizeof(dpcd_power_state));
2140
2141 if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0)
2142 dc_link_blank_dp_stream(dc->links[i], true1);
2143 }
2144
2145}
2146
2147void dc_link_blank_all_edp_displays(struct dc *dc)
2148{
2149 unsigned int i;
2150 uint8_t dpcd_power_state = '\0';
2151 enum dc_status status = DC_ERROR_UNEXPECTED;
2152
2153 for (i = 0; i < dc->link_count; i++) {
2154 if ((dc->links[i]->connector_signal != SIGNAL_TYPE_EDP) ||
2155 (!dc->links[i]->edp_sink_present))
2156 continue;
2157
2158 /* if any of the displays are lit up turn them off */
2159 status = core_link_read_dpcd(dc->links[i], DP_SET_POWER0x600,
2160 &dpcd_power_state, sizeof(dpcd_power_state));
2161
2162 if (status == DC_OK && dpcd_power_state == DP_POWER_STATE_D0)
2163 dc_link_blank_dp_stream(dc->links[i], true1);
2164 }
2165}
2166
2167void dc_link_blank_dp_stream(struct dc_link *link, bool_Bool hw_init)
2168{
2169 unsigned int j;
2170 struct dc *dc = link->ctx->dc;
2171 enum amd_signal_type signal = link->connector_signal;
2172
2173 if ((signal == SIGNAL_TYPE_EDP) ||
2174 (signal == SIGNAL_TYPE_DISPLAY_PORT)) {
2175 if (link->ep_type == DISPLAY_ENDPOINT_PHY &&
2176 link->link_enc->funcs->get_dig_frontend &&
2177 link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
2178 unsigned int fe = link->link_enc->funcs->get_dig_frontend(link->link_enc);
2179
2180 if (fe != ENGINE_ID_UNKNOWN)
2181 for (j = 0; j < dc->res_pool->stream_enc_count; j++) {
2182 if (fe == dc->res_pool->stream_enc[j]->id) {
2183 dc->res_pool->stream_enc[j]->funcs->dp_blank(link,
2184 dc->res_pool->stream_enc[j]);
2185 break;
2186 }
2187 }
2188 }
2189
2190 if ((!link->wa_flags.dp_keep_receiver_powered) || hw_init)
2191 dp_receiver_power_ctrl(link, false0);
2192 }
2193}
2194
2195static bool_Bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
2196 enum engine_id eng_id,
2197 struct ext_hdmi_settings *settings)
2198{
2199 bool_Bool result = false0;
2200 int i = 0;
2201 struct integrated_info *integrated_info =
2202 pipe_ctx->stream->ctx->dc_bios->integrated_info;
2203
2204 if (integrated_info == NULL((void *)0))
2205 return false0;
2206
2207 /*
2208 * Get retimer settings from sbios for passing SI eye test for DCE11
2209 * The setting values are varied based on board revision and port id
2210 * Therefore the setting values of each ports is passed by sbios.
2211 */
2212
2213 // Check if current bios contains ext Hdmi settings
2214 if (integrated_info->gpu_cap_info & 0x20) {
2215 switch (eng_id) {
2216 case ENGINE_ID_DIGA:
2217 settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr;
2218 settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num;
2219 settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num;
2220 memmove(settings->reg_settings,__builtin_memmove((settings->reg_settings), (integrated_info
->dp0_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp0_ext_hdmi_reg_settings)))
2221 integrated_info->dp0_ext_hdmi_reg_settings,__builtin_memmove((settings->reg_settings), (integrated_info
->dp0_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp0_ext_hdmi_reg_settings)))
2222 sizeof(integrated_info->dp0_ext_hdmi_reg_settings))__builtin_memmove((settings->reg_settings), (integrated_info
->dp0_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp0_ext_hdmi_reg_settings)))
;
2223 memmove(settings->reg_settings_6g,__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp0_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp0_ext_hdmi_6g_reg_settings)))
2224 integrated_info->dp0_ext_hdmi_6g_reg_settings,__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp0_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp0_ext_hdmi_6g_reg_settings)))
2225 sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings))__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp0_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp0_ext_hdmi_6g_reg_settings)))
;
2226 result = true1;
2227 break;
2228 case ENGINE_ID_DIGB:
2229 settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr;
2230 settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num;
2231 settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num;
2232 memmove(settings->reg_settings,__builtin_memmove((settings->reg_settings), (integrated_info
->dp1_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp1_ext_hdmi_reg_settings)))
2233 integrated_info->dp1_ext_hdmi_reg_settings,__builtin_memmove((settings->reg_settings), (integrated_info
->dp1_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp1_ext_hdmi_reg_settings)))
2234 sizeof(integrated_info->dp1_ext_hdmi_reg_settings))__builtin_memmove((settings->reg_settings), (integrated_info
->dp1_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp1_ext_hdmi_reg_settings)))
;
2235 memmove(settings->reg_settings_6g,__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp1_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp1_ext_hdmi_6g_reg_settings)))
2236 integrated_info->dp1_ext_hdmi_6g_reg_settings,__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp1_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp1_ext_hdmi_6g_reg_settings)))
2237 sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings))__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp1_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp1_ext_hdmi_6g_reg_settings)))
;
2238 result = true1;
2239 break;
2240 case ENGINE_ID_DIGC:
2241 settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr;
2242 settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num;
2243 settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num;
2244 memmove(settings->reg_settings,__builtin_memmove((settings->reg_settings), (integrated_info
->dp2_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp2_ext_hdmi_reg_settings)))
2245 integrated_info->dp2_ext_hdmi_reg_settings,__builtin_memmove((settings->reg_settings), (integrated_info
->dp2_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp2_ext_hdmi_reg_settings)))
2246 sizeof(integrated_info->dp2_ext_hdmi_reg_settings))__builtin_memmove((settings->reg_settings), (integrated_info
->dp2_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp2_ext_hdmi_reg_settings)))
;
2247 memmove(settings->reg_settings_6g,__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp2_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp2_ext_hdmi_6g_reg_settings)))
2248 integrated_info->dp2_ext_hdmi_6g_reg_settings,__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp2_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp2_ext_hdmi_6g_reg_settings)))
2249 sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings))__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp2_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp2_ext_hdmi_6g_reg_settings)))
;
2250 result = true1;
2251 break;
2252 case ENGINE_ID_DIGD:
2253 settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr;
2254 settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num;
2255 settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num;
2256 memmove(settings->reg_settings,__builtin_memmove((settings->reg_settings), (integrated_info
->dp3_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp3_ext_hdmi_reg_settings)))
2257 integrated_info->dp3_ext_hdmi_reg_settings,__builtin_memmove((settings->reg_settings), (integrated_info
->dp3_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp3_ext_hdmi_reg_settings)))
2258 sizeof(integrated_info->dp3_ext_hdmi_reg_settings))__builtin_memmove((settings->reg_settings), (integrated_info
->dp3_ext_hdmi_reg_settings), (sizeof(integrated_info->
dp3_ext_hdmi_reg_settings)))
;
2259 memmove(settings->reg_settings_6g,__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp3_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp3_ext_hdmi_6g_reg_settings)))
2260 integrated_info->dp3_ext_hdmi_6g_reg_settings,__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp3_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp3_ext_hdmi_6g_reg_settings)))
2261 sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings))__builtin_memmove((settings->reg_settings_6g), (integrated_info
->dp3_ext_hdmi_6g_reg_settings), (sizeof(integrated_info->
dp3_ext_hdmi_6g_reg_settings)))
;
2262 result = true1;
2263 break;
2264 default:
2265 break;
2266 }
2267
2268 if (result == true1) {
2269 // Validate settings from bios integrated info table
2270 if (settings->slv_addr == 0)
2271 return false0;
2272 if (settings->reg_num > 9)
2273 return false0;
2274 if (settings->reg_num_6g > 3)
2275 return false0;
2276
2277 for (i = 0; i < settings->reg_num; i++) {
2278 if (settings->reg_settings[i].i2c_reg_index > 0x20)
2279 return false0;
2280 }
2281
2282 for (i = 0; i < settings->reg_num_6g; i++) {
2283 if (settings->reg_settings_6g[i].i2c_reg_index > 0x20)
2284 return false0;
2285 }
2286 }
2287 }
2288
2289 return result;
2290}
2291
2292static bool_Bool i2c_write(struct pipe_ctx *pipe_ctx,
2293 uint8_t address, uint8_t *buffer, uint32_t length)
2294{
2295 struct i2c_command cmd = {0};
2296 struct i2c_payload payload = {0};
2297
2298 memset(&payload, 0, sizeof(payload))__builtin_memset((&payload), (0), (sizeof(payload)));
2299 memset(&cmd, 0, sizeof(cmd))__builtin_memset((&cmd), (0), (sizeof(cmd)));
2300
2301 cmd.number_of_payloads = 1;
2302 cmd.engine = I2C_COMMAND_ENGINE_DEFAULT;
2303 cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz;
2304
2305 payload.address = address;
2306 payload.data = buffer;
2307 payload.length = length;
2308 payload.write = true1;
2309 cmd.payloads = &payload;
2310
2311 if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx,
2312 pipe_ctx->stream->link, &cmd))
2313 return true1;
2314
2315 return false0;
2316}
2317
2318static void write_i2c_retimer_setting(
2319 struct pipe_ctx *pipe_ctx,
2320 bool_Bool is_vga_mode,
2321 bool_Bool is_over_340mhz,
2322 struct ext_hdmi_settings *settings)
2323{
2324 uint8_t slave_address = (settings->slv_addr >> 1);
2325 uint8_t buffer[2];
2326 const uint8_t apply_rx_tx_change = 0x4;
2327 uint8_t offset = 0xA;
2328 uint8_t value = 0;
2329 int i = 0;
2330 bool_Bool i2c_success = false0;
2331 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
2332
2333 memset(&buffer, 0, sizeof(buffer))__builtin_memset((&buffer), (0), (sizeof(buffer)));
2334
2335 /* Start Ext-Hdmi programming*/
2336
2337 for (i = 0; i < settings->reg_num; i++) {
2338 /* Apply 3G settings */
2339 if (settings->reg_settings[i].i2c_reg_index <= 0x20) {
2340
2341 buffer[0] = settings->reg_settings[i].i2c_reg_index;
2342 buffer[1] = settings->reg_settings[i].i2c_reg_val;
2343 i2c_success = i2c_write(pipe_ctx, slave_address,
2344 buffer, sizeof(buffer));
2345 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2346 offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2347 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2348
2349 if (!i2c_success)
2350 goto i2c_write_fail;
2351
2352 /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
2353 * needs to be set to 1 on every 0xA-0xC write.
2354 */
2355 if (settings->reg_settings[i].i2c_reg_index == 0xA ||
2356 settings->reg_settings[i].i2c_reg_index == 0xB ||
2357 settings->reg_settings[i].i2c_reg_index == 0xC) {
2358
2359 /* Query current value from offset 0xA */
2360 if (settings->reg_settings[i].i2c_reg_index == 0xA)
2361 value = settings->reg_settings[i].i2c_reg_val;
2362 else {
2363 i2c_success =
2364 dal_ddc_service_query_ddc_data(
2365 pipe_ctx->stream->link->ddc,
2366 slave_address, &offset, 1, &value, 1);
2367 if (!i2c_success)
2368 goto i2c_write_fail;
2369 }
2370
2371 buffer[0] = offset;
2372 /* Set APPLY_RX_TX_CHANGE bit to 1 */
2373 buffer[1] = value | apply_rx_tx_change;
2374 i2c_success = i2c_write(pipe_ctx, slave_address,
2375 buffer, sizeof(buffer));
2376 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2377 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2378 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2379 if (!i2c_success)
2380 goto i2c_write_fail;
2381 }
2382 }
2383 }
2384
2385 /* Apply 3G settings */
2386 if (is_over_340mhz) {
2387 for (i = 0; i < settings->reg_num_6g; i++) {
2388 /* Apply 3G settings */
2389 if (settings->reg_settings[i].i2c_reg_index <= 0x20) {
2390
2391 buffer[0] = settings->reg_settings_6g[i].i2c_reg_index;
2392 buffer[1] = settings->reg_settings_6g[i].i2c_reg_val;
2393 i2c_success = i2c_write(pipe_ctx, slave_address,
2394 buffer, sizeof(buffer));
2395 RETIMER_REDRIVER_INFO("above 340Mhz: retimer write to slave_address = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "above 340Mhz: retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2396 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "above 340Mhz: retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2397 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "above 340Mhz: retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2398
2399 if (!i2c_success)
2400 goto i2c_write_fail;
2401
2402 /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
2403 * needs to be set to 1 on every 0xA-0xC write.
2404 */
2405 if (settings->reg_settings_6g[i].i2c_reg_index == 0xA ||
2406 settings->reg_settings_6g[i].i2c_reg_index == 0xB ||
2407 settings->reg_settings_6g[i].i2c_reg_index == 0xC) {
2408
2409 /* Query current value from offset 0xA */
2410 if (settings->reg_settings_6g[i].i2c_reg_index == 0xA)
2411 value = settings->reg_settings_6g[i].i2c_reg_val;
2412 else {
2413 i2c_success =
2414 dal_ddc_service_query_ddc_data(
2415 pipe_ctx->stream->link->ddc,
2416 slave_address, &offset, 1, &value, 1);
2417 if (!i2c_success)
2418 goto i2c_write_fail;
2419 }
2420
2421 buffer[0] = offset;
2422 /* Set APPLY_RX_TX_CHANGE bit to 1 */
2423 buffer[1] = value | apply_rx_tx_change;
2424 i2c_success = i2c_write(pipe_ctx, slave_address,
2425 buffer, sizeof(buffer));
2426 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2427 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2428 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2429 if (!i2c_success)
2430 goto i2c_write_fail;
2431 }
2432 }
2433 }
2434 }
2435
2436 if (is_vga_mode) {
2437 /* Program additional settings if using 640x480 resolution */
2438
2439 /* Write offset 0xFF to 0x01 */
2440 buffer[0] = 0xff;
2441 buffer[1] = 0x01;
2442 i2c_success = i2c_write(pipe_ctx, slave_address,
2443 buffer, sizeof(buffer));
2444 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2445 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2446 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2447 if (!i2c_success)
2448 goto i2c_write_fail;
2449
2450 /* Write offset 0x00 to 0x23 */
2451 buffer[0] = 0x00;
2452 buffer[1] = 0x23;
2453 i2c_success = i2c_write(pipe_ctx, slave_address,
2454 buffer, sizeof(buffer));
2455 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2456 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2457 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2458 if (!i2c_success)
2459 goto i2c_write_fail;
2460
2461 /* Write offset 0xff to 0x00 */
2462 buffer[0] = 0xff;
2463 buffer[1] = 0x00;
2464 i2c_success = i2c_write(pipe_ctx, slave_address,
2465 buffer, sizeof(buffer));
2466 RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2467 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2468 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2469 if (!i2c_success)
2470 goto i2c_write_fail;
2471
2472 }
2473
2474 return;
2475
2476i2c_write_fail:
2477 DC_LOG_DEBUG("Set retimer failed")___drm_dbg(((void *)0), DRM_UT_KMS, "Set retimer failed");
2478}
2479
2480static void write_i2c_default_retimer_setting(
2481 struct pipe_ctx *pipe_ctx,
2482 bool_Bool is_vga_mode,
2483 bool_Bool is_over_340mhz)
2484{
2485 uint8_t slave_address = (0xBA >> 1);
2486 uint8_t buffer[2];
2487 bool_Bool i2c_success = false0;
2488 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
2489
2490 memset(&buffer, 0, sizeof(buffer))__builtin_memset((&buffer), (0), (sizeof(buffer)));
2491
2492 /* Program Slave Address for tuning single integrity */
2493 /* Write offset 0x0A to 0x13 */
2494 buffer[0] = 0x0A;
2495 buffer[1] = 0x13;
2496 i2c_success = i2c_write(pipe_ctx, slave_address,
2497 buffer, sizeof(buffer));
2498 RETIMER_REDRIVER_INFO("retimer writes default setting to slave_address = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer writes default setting to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2499 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer writes default setting to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2500 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer writes default setting to slave_address = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2501 if (!i2c_success)
2502 goto i2c_write_fail;
2503
2504 /* Write offset 0x0A to 0x17 */
2505 buffer[0] = 0x0A;
2506 buffer[1] = 0x17;
2507 i2c_success = i2c_write(pipe_ctx, slave_address,
2508 buffer, sizeof(buffer));
2509 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2510 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2511 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2512 if (!i2c_success)
2513 goto i2c_write_fail;
2514
2515 /* Write offset 0x0B to 0xDA or 0xD8 */
2516 buffer[0] = 0x0B;
2517 buffer[1] = is_over_340mhz ? 0xDA : 0xD8;
2518 i2c_success = i2c_write(pipe_ctx, slave_address,
2519 buffer, sizeof(buffer));
2520 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2521 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2522 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2523 if (!i2c_success)
2524 goto i2c_write_fail;
2525
2526 /* Write offset 0x0A to 0x17 */
2527 buffer[0] = 0x0A;
2528 buffer[1] = 0x17;
2529 i2c_success = i2c_write(pipe_ctx, slave_address,
2530 buffer, sizeof(buffer));
2531 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2532 offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2533 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2534 if (!i2c_success)
2535 goto i2c_write_fail;
2536
2537 /* Write offset 0x0C to 0x1D or 0x91 */
2538 buffer[0] = 0x0C;
2539 buffer[1] = is_over_340mhz ? 0x1D : 0x91;
2540 i2c_success = i2c_write(pipe_ctx, slave_address,
2541 buffer, sizeof(buffer));
2542 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2543 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2544 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2545 if (!i2c_success)
2546 goto i2c_write_fail;
2547
2548 /* Write offset 0x0A to 0x17 */
2549 buffer[0] = 0x0A;
2550 buffer[1] = 0x17;
2551 i2c_success = i2c_write(pipe_ctx, slave_address,
2552 buffer, sizeof(buffer));
2553 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2554 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2555 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2556 if (!i2c_success)
2557 goto i2c_write_fail;
2558
2559
2560 if (is_vga_mode) {
2561 /* Program additional settings if using 640x480 resolution */
2562
2563 /* Write offset 0xFF to 0x01 */
2564 buffer[0] = 0xff;
2565 buffer[1] = 0x01;
2566 i2c_success = i2c_write(pipe_ctx, slave_address,
2567 buffer, sizeof(buffer));
2568 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2569 offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2570 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2571 if (!i2c_success)
2572 goto i2c_write_fail;
2573
2574 /* Write offset 0x00 to 0x23 */
2575 buffer[0] = 0x00;
2576 buffer[1] = 0x23;
2577 i2c_success = i2c_write(pipe_ctx, slave_address,
2578 buffer, sizeof(buffer));
2579 RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2580 offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2581 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2582 if (!i2c_success)
2583 goto i2c_write_fail;
2584
2585 /* Write offset 0xff to 0x00 */
2586 buffer[0] = 0xff;
2587 buffer[1] = 0x00;
2588 i2c_success = i2c_write(pipe_ctx, slave_address,
2589 buffer, sizeof(buffer));
2590 RETIMER_REDRIVER_INFO("retimer write default setting to slave_addr = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write default setting to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2591 offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n",___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write default setting to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
2592 slave_address, buffer[0], buffer[1], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "retimer write default setting to slave_addr = 0x%x, offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n"
, slave_address, buffer[0], buffer[1], i2c_success?1:0)
;
2593 if (!i2c_success)
2594 goto i2c_write_fail;
2595 }
2596
2597 return;
2598
2599i2c_write_fail:
2600 DC_LOG_DEBUG("Set default retimer failed")___drm_dbg(((void *)0), DRM_UT_KMS, "Set default retimer failed"
)
;
2601}
2602
2603static void write_i2c_redriver_setting(
2604 struct pipe_ctx *pipe_ctx,
2605 bool_Bool is_over_340mhz)
2606{
2607 uint8_t slave_address = (0xF0 >> 1);
2608 uint8_t buffer[16];
2609 bool_Bool i2c_success = false0;
2610 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
2611
2612 memset(&buffer, 0, sizeof(buffer))__builtin_memset((&buffer), (0), (sizeof(buffer)));
2613
2614 // Program Slave Address for tuning single integrity
2615 buffer[3] = 0x4E;
2616 buffer[4] = 0x4E;
2617 buffer[5] = 0x4E;
2618 buffer[6] = is_over_340mhz ? 0x4E : 0x4A;
2619
2620 i2c_success = i2c_write(pipe_ctx, slave_address,
2621 buffer, sizeof(buffer));
2622 RETIMER_REDRIVER_INFO("redriver write 0 to all 16 reg offset expect following:\n\___drm_dbg(((void *)0), DRM_UT_KMS, "redriver write 0 to all 16 reg offset expect following:\n \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x, offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x, i2c_success = %d\n"
, slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success
?1:0)
2623 \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "redriver write 0 to all 16 reg offset expect following:\n \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x, offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x, i2c_success = %d\n"
, slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success
?1:0)
2624 offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x,\___drm_dbg(((void *)0), DRM_UT_KMS, "redriver write 0 to all 16 reg offset expect following:\n \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x, offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x, i2c_success = %d\n"
, slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success
?1:0)
2625 i2c_success = %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "redriver write 0 to all 16 reg offset expect following:\n \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x, offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x, i2c_success = %d\n"
, slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success
?1:0)
2626 slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0)___drm_dbg(((void *)0), DRM_UT_KMS, "redriver write 0 to all 16 reg offset expect following:\n \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x, offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x, i2c_success = %d\n"
, slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success
?1:0)
;
2627
2628 if (!i2c_success)
2629 DC_LOG_DEBUG("Set redriver failed")___drm_dbg(((void *)0), DRM_UT_KMS, "Set redriver failed");
2630}
2631
2632static void disable_link(struct dc_link *link, const struct link_resource *link_res,
2633 enum amd_signal_type signal)
2634{
2635 /*
2636 * TODO: implement call for dp_set_hw_test_pattern
2637 * it is needed for compliance testing
2638 */
2639
2640 /* Here we need to specify that encoder output settings
2641 * need to be calculated as for the set mode,
2642 * it will lead to querying dynamic link capabilities
2643 * which should be done before enable output
2644 */
2645
2646 if (dc_is_dp_signal(signal)) {
2647 /* SST DP, eDP */
2648 struct dc_link_settings link_settings = link->cur_link_settings;
2649 if (dc_is_dp_sst_signal(signal))
2650 dp_disable_link_phy(link, link_res, signal);
2651 else
2652 dp_disable_link_phy_mst(link, link_res, signal);
2653
2654 if (dc_is_dp_sst_signal(signal) ||
2655 link->mst_stream_alloc_table.stream_count == 0) {
2656 if (dp_get_link_encoding_format(&link_settings) == DP_8b_10b_ENCODING) {
2657 dp_set_fec_enable(link, false0);
2658 dp_set_fec_ready(link, link_res, false0);
2659 }
2660 }
2661 } else if (signal != SIGNAL_TYPE_VIRTUAL) {
2662 link->dc->hwss.disable_link_output(link, link_res, signal);
2663 }
2664
2665 if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
2666 /* MST disable link only when no stream use the link */
2667 if (link->mst_stream_alloc_table.stream_count <= 0)
2668 link->link_status.link_active = false0;
2669 } else {
2670 link->link_status.link_active = false0;
2671 }
2672}
2673
2674static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
2675{
2676 struct dc_stream_state *stream = pipe_ctx->stream;
2677 struct dc_link *link = stream->link;
2678 enum dc_color_depth display_color_depth;
2679 enum engine_id eng_id;
2680 struct ext_hdmi_settings settings = {0};
2681 bool_Bool is_over_340mhz = false0;
2682 bool_Bool is_vga_mode = (stream->timing.h_addressable == 640)
2683 && (stream->timing.v_addressable == 480);
2684 struct dc *dc = pipe_ctx->stream->ctx->dc;
2685
2686 if (stream->phy_pix_clk == 0)
2687 stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
2688 if (stream->phy_pix_clk > 340000)
2689 is_over_340mhz = true1;
2690
2691 if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
2692 unsigned short masked_chip_caps = pipe_ctx->stream->link->chip_caps &
2693 EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
2694 if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
2695 /* DP159, Retimer settings */
2696 eng_id = pipe_ctx->stream_res.stream_enc->id;
2697
2698 if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) {
2699 write_i2c_retimer_setting(pipe_ctx,
2700 is_vga_mode, is_over_340mhz, &settings);
2701 } else {
2702 write_i2c_default_retimer_setting(pipe_ctx,
2703 is_vga_mode, is_over_340mhz);
2704 }
2705 } else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {
2706 /* PI3EQX1204, Redriver settings */
2707 write_i2c_redriver_setting(pipe_ctx, is_over_340mhz);
2708 }
2709 }
2710
2711 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
2712 dal_ddc_service_write_scdc_data(
2713 stream->link->ddc,
2714 stream->phy_pix_clk,
2715 stream->timing.flags.LTE_340MCSC_SCRAMBLE);
2716
2717 memset(&stream->link->cur_link_settings, 0,__builtin_memset((&stream->link->cur_link_settings)
, (0), (sizeof(struct dc_link_settings)))
2718 sizeof(struct dc_link_settings))__builtin_memset((&stream->link->cur_link_settings)
, (0), (sizeof(struct dc_link_settings)))
;
2719
2720 display_color_depth = stream->timing.display_color_depth;
2721 if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
2722 display_color_depth = COLOR_DEPTH_888;
2723
2724 dc->hwss.enable_tmds_link_output(
2725 link,
2726 &pipe_ctx->link_res,
2727 pipe_ctx->stream->signal,
2728 pipe_ctx->clock_source->id,
2729 display_color_depth,
2730 stream->phy_pix_clk);
2731
2732 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
2733 dal_ddc_service_read_scdc_data(link->ddc);
2734}
2735
2736static void enable_link_lvds(struct pipe_ctx *pipe_ctx)
2737{
2738 struct dc_stream_state *stream = pipe_ctx->stream;
2739 struct dc_link *link = stream->link;
2740 struct dc *dc = stream->ctx->dc;
2741
2742 if (stream->phy_pix_clk == 0)
2743 stream->phy_pix_clk = stream->timing.pix_clk_100hz / 10;
2744
2745 memset(&stream->link->cur_link_settings, 0,__builtin_memset((&stream->link->cur_link_settings)
, (0), (sizeof(struct dc_link_settings)))
2746 sizeof(struct dc_link_settings))__builtin_memset((&stream->link->cur_link_settings)
, (0), (sizeof(struct dc_link_settings)))
;
2747 dc->hwss.enable_lvds_link_output(
2748 link,
2749 &pipe_ctx->link_res,
2750 pipe_ctx->clock_source->id,
2751 stream->phy_pix_clk);
2752
2753}
2754
2755bool_Bool dc_power_alpm_dpcd_enable(struct dc_link *link, bool_Bool enable)
2756{
2757 bool_Bool ret = false0;
2758 union dpcd_alpm_configuration alpm_config;
2759
2760 if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
2761 memset(&alpm_config, 0, sizeof(alpm_config))__builtin_memset((&alpm_config), (0), (sizeof(alpm_config
)))
;
2762
2763 alpm_config.bits.ENABLE = (enable ? true1 : false0);
2764 ret = dm_helpers_dp_write_dpcd(link->ctx, link,
2765 DP_RECEIVER_ALPM_CONFIG0x116, &alpm_config.raw,
2766 sizeof(alpm_config.raw));
2767 }
2768 return ret;
2769}
2770
2771/****************************enable_link***********************************/
2772static enum dc_status enable_link(
2773 struct dc_state *state,
2774 struct pipe_ctx *pipe_ctx)
2775{
2776 enum dc_status status = DC_ERROR_UNEXPECTED;
2777 struct dc_stream_state *stream = pipe_ctx->stream;
2778 struct dc_link *link = stream->link;
2779
2780 /* There's some scenarios where driver is unloaded with display
2781 * still enabled. When driver is reloaded, it may cause a display
2782 * to not light up if there is a mismatch between old and new
2783 * link settings. Need to call disable first before enabling at
2784 * new link settings.
2785 */
2786 if (link->link_status.link_active) {
2787 disable_link(link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
2788 }
2789
2790 switch (pipe_ctx->stream->signal) {
2791 case SIGNAL_TYPE_DISPLAY_PORT:
2792 status = enable_link_dp(state, pipe_ctx);
2793 break;
2794 case SIGNAL_TYPE_EDP:
2795 status = enable_link_edp(state, pipe_ctx);
2796 break;
2797 case SIGNAL_TYPE_DISPLAY_PORT_MST:
2798 status = enable_link_dp_mst(state, pipe_ctx);
2799 drm_msleep(200)mdelay(200);
2800 break;
2801 case SIGNAL_TYPE_DVI_SINGLE_LINK:
2802 case SIGNAL_TYPE_DVI_DUAL_LINK:
2803 case SIGNAL_TYPE_HDMI_TYPE_A:
2804 enable_link_hdmi(pipe_ctx);
2805 status = DC_OK;
2806 break;
2807 case SIGNAL_TYPE_LVDS:
2808 enable_link_lvds(pipe_ctx);
2809 status = DC_OK;
2810 break;
2811 case SIGNAL_TYPE_VIRTUAL:
2812 status = DC_OK;
2813 break;
2814 default:
2815 break;
2816 }
2817
2818 if (status == DC_OK)
2819 pipe_ctx->stream->link->link_status.link_active = true1;
2820
2821 return status;
2822}
2823
2824static uint32_t get_timing_pixel_clock_100hz(const struct dc_crtc_timing *timing)
2825{
2826
2827 uint32_t pxl_clk = timing->pix_clk_100hz;
2828
2829 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
2830 pxl_clk /= 2;
2831 else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
2832 pxl_clk = pxl_clk * 2 / 3;
2833
2834 if (timing->display_color_depth == COLOR_DEPTH_101010)
2835 pxl_clk = pxl_clk * 10 / 8;
2836 else if (timing->display_color_depth == COLOR_DEPTH_121212)
2837 pxl_clk = pxl_clk * 12 / 8;
2838
2839 return pxl_clk;
2840}
2841
2842static bool_Bool dp_active_dongle_validate_timing(
2843 const struct dc_crtc_timing *timing,
2844 const struct dpcd_caps *dpcd_caps)
2845{
2846 const struct dc_dongle_caps *dongle_caps = &dpcd_caps->dongle_caps;
2847
2848 switch (dpcd_caps->dongle_type) {
2849 case DISPLAY_DONGLE_DP_VGA_CONVERTER:
2850 case DISPLAY_DONGLE_DP_DVI_CONVERTER:
2851 case DISPLAY_DONGLE_DP_DVI_DONGLE:
2852 if (timing->pixel_encoding == PIXEL_ENCODING_RGB)
2853 return true1;
2854 else
2855 return false0;
2856 default:
2857 break;
2858 }
2859
2860 if (dpcd_caps->dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER &&
2861 dongle_caps->extendedCapValid == true1) {
2862 /* Check Pixel Encoding */
2863 switch (timing->pixel_encoding) {
2864 case PIXEL_ENCODING_RGB:
2865 case PIXEL_ENCODING_YCBCR444:
2866 break;
2867 case PIXEL_ENCODING_YCBCR422:
2868 if (!dongle_caps->is_dp_hdmi_ycbcr422_pass_through)
2869 return false0;
2870 break;
2871 case PIXEL_ENCODING_YCBCR420:
2872 if (!dongle_caps->is_dp_hdmi_ycbcr420_pass_through)
2873 return false0;
2874 break;
2875 default:
2876 /* Invalid Pixel Encoding*/
2877 return false0;
2878 }
2879
2880 switch (timing->display_color_depth) {
2881 case COLOR_DEPTH_666:
2882 case COLOR_DEPTH_888:
2883 /*888 and 666 should always be supported*/
2884 break;
2885 case COLOR_DEPTH_101010:
2886 if (dongle_caps->dp_hdmi_max_bpc < 10)
2887 return false0;
2888 break;
2889 case COLOR_DEPTH_121212:
2890 if (dongle_caps->dp_hdmi_max_bpc < 12)
2891 return false0;
2892 break;
2893 case COLOR_DEPTH_141414:
2894 case COLOR_DEPTH_161616:
2895 default:
2896 /* These color depths are currently not supported */
2897 return false0;
2898 }
2899
2900 /* Check 3D format */
2901 switch (timing->timing_3d_format) {
2902 case TIMING_3D_FORMAT_NONE:
2903 case TIMING_3D_FORMAT_FRAME_ALTERNATE:
2904 /*Only frame alternate 3D is supported on active dongle*/
2905 break;
2906 default:
2907 /*other 3D formats are not supported due to bad infoframe translation */
2908 return false0;
2909 }
2910
2911#if defined(CONFIG_DRM_AMD_DC_DCN1)
2912 if (dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps > 0) { // DP to HDMI FRL converter
2913 struct dc_crtc_timing outputTiming = *timing;
2914
2915 if (timing->flags.DSC && !timing->dsc_cfg.is_frl)
2916 /* DP input has DSC, HDMI FRL output doesn't have DSC, remove DSC from output timing */
2917 outputTiming.flags.DSC = 0;
2918 if (dc_bandwidth_in_kbps_from_timing(&outputTiming) > dongle_caps->dp_hdmi_frl_max_link_bw_in_kbps)
2919 return false0;
2920 } else { // DP to HDMI TMDS converter
2921 if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
2922 return false0;
2923 }
2924#else
2925 if (get_timing_pixel_clock_100hz(timing) > (dongle_caps->dp_hdmi_max_pixel_clk_in_khz * 10))
2926 return false0;
2927#endif
2928 }
2929
2930 if (dpcd_caps->channel_coding_cap.bits.DP_128b_132b_SUPPORTED == 0 &&
2931 dpcd_caps->dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_PASSTHROUGH_SUPPORT == 0 &&
2932 dongle_caps->dfp_cap_ext.supported) {
2933
2934 if (dongle_caps->dfp_cap_ext.max_pixel_rate_in_mps < (timing->pix_clk_100hz / 10000))
2935 return false0;
2936
2937 if (dongle_caps->dfp_cap_ext.max_video_h_active_width < timing->h_addressable)
2938 return false0;
2939
2940 if (dongle_caps->dfp_cap_ext.max_video_v_active_height < timing->v_addressable)
2941 return false0;
2942
2943 if (timing->pixel_encoding == PIXEL_ENCODING_RGB) {
2944 if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
2945 return false0;
2946 if (timing->display_color_depth == COLOR_DEPTH_666 &&
2947 !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_6bpc)
2948 return false0;
2949 else if (timing->display_color_depth == COLOR_DEPTH_888 &&
2950 !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_8bpc)
2951 return false0;
2952 else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
2953 !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_10bpc)
2954 return false0;
2955 else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
2956 !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_12bpc)
2957 return false0;
2958 else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
2959 !dongle_caps->dfp_cap_ext.rgb_color_depth_caps.support_16bpc)
2960 return false0;
2961 } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR444) {
2962 if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
2963 return false0;
2964 if (timing->display_color_depth == COLOR_DEPTH_888 &&
2965 !dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_8bpc)
2966 return false0;
2967 else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
2968 !dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_10bpc)
2969 return false0;
2970 else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
2971 !dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_12bpc)
2972 return false0;
2973 else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
2974 !dongle_caps->dfp_cap_ext.ycbcr444_color_depth_caps.support_16bpc)
2975 return false0;
2976 } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
2977 if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
2978 return false0;
2979 if (timing->display_color_depth == COLOR_DEPTH_888 &&
2980 !dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_8bpc)
2981 return false0;
2982 else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
2983 !dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_10bpc)
2984 return false0;
2985 else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
2986 !dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_12bpc)
2987 return false0;
2988 else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
2989 !dongle_caps->dfp_cap_ext.ycbcr422_color_depth_caps.support_16bpc)
2990 return false0;
2991 } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) {
2992 if (!dongle_caps->dfp_cap_ext.encoding_format_caps.support_rgb)
2993 return false0;
2994 if (timing->display_color_depth == COLOR_DEPTH_888 &&
2995 !dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_8bpc)
2996 return false0;
2997 else if (timing->display_color_depth == COLOR_DEPTH_101010 &&
2998 !dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_10bpc)
2999 return false0;
3000 else if (timing->display_color_depth == COLOR_DEPTH_121212 &&
3001 !dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_12bpc)
3002 return false0;
3003 else if (timing->display_color_depth == COLOR_DEPTH_161616 &&
3004 !dongle_caps->dfp_cap_ext.ycbcr420_color_depth_caps.support_16bpc)
3005 return false0;
3006 }
3007 }
3008
3009 return true1;
3010}
3011
3012enum dc_status dc_link_validate_mode_timing(
3013 const struct dc_stream_state *stream,
3014 struct dc_link *link,
3015 const struct dc_crtc_timing *timing)
3016{
3017 uint32_t max_pix_clk = stream->link->dongle_max_pix_clk * 10;
3018 struct dpcd_caps *dpcd_caps = &link->dpcd_caps;
3019
3020 /* A hack to avoid failing any modes for EDID override feature on
3021 * topology change such as lower quality cable for DP or different dongle
3022 */
3023 if (link->remote_sinks[0] && link->remote_sinks[0]->sink_signal == SIGNAL_TYPE_VIRTUAL)
3024 return DC_OK;
3025
3026 /* Passive Dongle */
3027 if (max_pix_clk != 0 && get_timing_pixel_clock_100hz(timing) > max_pix_clk)
3028 return DC_EXCEED_DONGLE_CAP;
3029
3030 /* Active Dongle*/
3031 if (!dp_active_dongle_validate_timing(timing, dpcd_caps))
3032 return DC_EXCEED_DONGLE_CAP;
3033
3034 switch (stream->signal) {
3035 case SIGNAL_TYPE_EDP:
3036 case SIGNAL_TYPE_DISPLAY_PORT:
3037 if (!dp_validate_mode_timing(
3038 link,
3039 timing))
3040 return DC_NO_DP_LINK_BANDWIDTH;
3041 break;
3042
3043 default:
3044 break;
3045 }
3046
3047 return DC_OK;
3048}
3049
3050static struct abm *get_abm_from_stream_res(const struct dc_link *link)
3051{
3052 int i;
3053 struct dc *dc = NULL((void *)0);
3054 struct abm *abm = NULL((void *)0);
3055
3056 if (!link || !link->ctx)
3057 return NULL((void *)0);
3058
3059 dc = link->ctx->dc;
3060
3061 for (i = 0; i < MAX_PIPES6; i++) {
3062 struct pipe_ctx pipe_ctx = dc->current_state->res_ctx.pipe_ctx[i];
3063 struct dc_stream_state *stream = pipe_ctx.stream;
3064
3065 if (stream && stream->link == link) {
3066 abm = pipe_ctx.stream_res.abm;
3067 break;
3068 }
3069 }
3070 return abm;
3071}
3072
3073int dc_link_get_backlight_level(const struct dc_link *link)
3074{
3075 struct abm *abm = get_abm_from_stream_res(link);
3076 struct panel_cntl *panel_cntl = link->panel_cntl;
3077 struct dc *dc = link->ctx->dc;
3078 struct dmcu *dmcu = dc->res_pool->dmcu;
3079 bool_Bool fw_set_brightness = true1;
3080
3081 if (dmcu)
3082 fw_set_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
3083
3084 if (!fw_set_brightness && panel_cntl->funcs->get_current_backlight)
3085 return panel_cntl->funcs->get_current_backlight(panel_cntl);
3086 else if (abm != NULL((void *)0) && abm->funcs->get_current_backlight != NULL((void *)0))
3087 return (int) abm->funcs->get_current_backlight(abm);
3088 else
3089 return DC_ERROR_UNEXPECTED;
3090}
3091
3092int dc_link_get_target_backlight_pwm(const struct dc_link *link)
3093{
3094 struct abm *abm = get_abm_from_stream_res(link);
3095
3096 if (abm == NULL((void *)0) || abm->funcs->get_target_backlight == NULL((void *)0))
3097 return DC_ERROR_UNEXPECTED;
3098
3099 return (int) abm->funcs->get_target_backlight(abm);
3100}
3101
3102static struct pipe_ctx *get_pipe_from_link(const struct dc_link *link)
3103{
3104 int i;
3105 struct dc *dc = link->ctx->dc;
3106 struct pipe_ctx *pipe_ctx = NULL((void *)0);
3107
3108 for (i = 0; i < MAX_PIPES6; i++) {
3109 if (dc->current_state->res_ctx.pipe_ctx[i].stream) {
3110 if (dc->current_state->res_ctx.pipe_ctx[i].stream->link == link) {
3111 pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
3112 break;
3113 }
3114 }
3115 }
3116
3117 return pipe_ctx;
3118}
3119
3120bool_Bool dc_link_set_backlight_level(const struct dc_link *link,
3121 uint32_t backlight_pwm_u16_16,
3122 uint32_t frame_ramp)
3123{
3124 struct dc *dc = link->ctx->dc;
3125
3126 DC_LOGGER_INIT(link->ctx->logger);
3127 DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",___drm_dbg(((void *)0), DRM_UT_KMS, "New Backlight level: %d (0x%X)\n"
, backlight_pwm_u16_16, backlight_pwm_u16_16)
3128 backlight_pwm_u16_16, backlight_pwm_u16_16)___drm_dbg(((void *)0), DRM_UT_KMS, "New Backlight level: %d (0x%X)\n"
, backlight_pwm_u16_16, backlight_pwm_u16_16)
;
3129
3130 if (dc_is_embedded_signal(link->connector_signal)) {
3131 struct pipe_ctx *pipe_ctx = get_pipe_from_link(link);
3132
3133 if (pipe_ctx) {
3134 /* Disable brightness ramping when the display is blanked
3135 * as it can hang the DMCU
3136 */
3137 if (pipe_ctx->plane_state == NULL((void *)0))
3138 frame_ramp = 0;
3139 } else {
3140 return false0;
3141 }
3142
3143 dc->hwss.set_backlight_level(
3144 pipe_ctx,
3145 backlight_pwm_u16_16,
3146 frame_ramp);
3147 }
3148 return true1;
3149}
3150
3151bool_Bool dc_link_set_psr_allow_active(struct dc_link *link, const bool_Bool *allow_active,
3152 bool_Bool wait, bool_Bool force_static, const unsigned int *power_opts)
3153{
3154 struct dc *dc = link->ctx->dc;
3155 struct dmcu *dmcu = dc->res_pool->dmcu;
3156 struct dmub_psr *psr = dc->res_pool->psr;
3157 unsigned int panel_inst;
3158
3159 if (psr == NULL((void *)0) && force_static)
3160 return false0;
3161
3162 if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
3163 return false0;
3164
3165 if ((allow_active != NULL((void *)0)) && (*allow_active == true1) && (link->type == dc_connection_none)) {
3166 // Don't enter PSR if panel is not connected
3167 return false0;
3168 }
3169
3170 /* Set power optimization flag */
3171 if (power_opts && link->psr_settings.psr_power_opt != *power_opts) {
3172 link->psr_settings.psr_power_opt = *power_opts;
3173
3174 if (psr != NULL((void *)0) && link->psr_settings.psr_feature_enabled && psr->funcs->psr_set_power_opt)
3175 psr->funcs->psr_set_power_opt(psr, link->psr_settings.psr_power_opt, panel_inst);
3176 }
3177
3178 if (psr != NULL((void *)0) && link->psr_settings.psr_feature_enabled &&
3179 force_static && psr->funcs->psr_force_static)
3180 psr->funcs->psr_force_static(psr, panel_inst);
3181
3182 /* Enable or Disable PSR */
3183 if (allow_active && link->psr_settings.psr_allow_active != *allow_active) {
3184 link->psr_settings.psr_allow_active = *allow_active;
3185
3186 if (!link->psr_settings.psr_allow_active)
3187 dc_z10_restore(dc);
3188
3189 if (psr != NULL((void *)0) && link->psr_settings.psr_feature_enabled) {
3190 psr->funcs->psr_enable(psr, link->psr_settings.psr_allow_active, wait, panel_inst);
3191 } else if ((dmcu != NULL((void *)0) && dmcu->funcs->is_dmcu_initialized(dmcu)) &&
3192 link->psr_settings.psr_feature_enabled)
3193 dmcu->funcs->set_psr_enable(dmcu, link->psr_settings.psr_allow_active, wait);
3194 else
3195 return false0;
3196 }
3197
3198 return true1;
3199}
3200
3201bool_Bool dc_link_get_psr_state(const struct dc_link *link, enum dc_psr_state *state)
3202{
3203 struct dc *dc = link->ctx->dc;
3204 struct dmcu *dmcu = dc->res_pool->dmcu;
3205 struct dmub_psr *psr = dc->res_pool->psr;
3206 unsigned int panel_inst;
3207
3208 if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
3209 return false0;
3210
3211 if (psr != NULL((void *)0) && link->psr_settings.psr_feature_enabled)
3212 psr->funcs->psr_get_state(psr, state, panel_inst);
3213 else if (dmcu != NULL((void *)0) && link->psr_settings.psr_feature_enabled)
3214 dmcu->funcs->get_psr_state(dmcu, state);
3215
3216 return true1;
3217}
3218
3219static inline enum physical_phy_id
3220transmitter_to_phy_id(enum transmitter transmitter_value)
3221{
3222 switch (transmitter_value) {
3223 case TRANSMITTER_UNIPHY_A:
3224 return PHYLD_0;
3225 case TRANSMITTER_UNIPHY_B:
3226 return PHYLD_1;
3227 case TRANSMITTER_UNIPHY_C:
3228 return PHYLD_2;
3229 case TRANSMITTER_UNIPHY_D:
3230 return PHYLD_3;
3231 case TRANSMITTER_UNIPHY_E:
3232 return PHYLD_4;
3233 case TRANSMITTER_UNIPHY_F:
3234 return PHYLD_5;
3235 case TRANSMITTER_NUTMEG_CRT:
3236 return PHYLD_6;
3237 case TRANSMITTER_TRAVIS_CRT:
3238 return PHYLD_7;
3239 case TRANSMITTER_TRAVIS_LCD:
3240 return PHYLD_8;
3241 case TRANSMITTER_UNIPHY_G:
3242 return PHYLD_9;
3243 case TRANSMITTER_COUNT:
3244 return PHYLD_COUNT;
3245 case TRANSMITTER_UNKNOWN:
3246 return PHYLD_UNKNOWN;
3247 default:
3248 WARN_ONCE(1, "Unknown transmitter value %d\n",({ static int __warned; int __ret = !!(1); if (__ret &&
!__warned) { printf("Unknown transmitter value %d\n", transmitter_value
); __warned = 1; } __builtin_expect(!!(__ret), 0); })
3249 transmitter_value)({ static int __warned; int __ret = !!(1); if (__ret &&
!__warned) { printf("Unknown transmitter value %d\n", transmitter_value
); __warned = 1; } __builtin_expect(!!(__ret), 0); })
;
3250 return PHYLD_UNKNOWN;
3251 }
3252}
3253
3254bool_Bool dc_link_setup_psr(struct dc_link *link,
3255 const struct dc_stream_state *stream, struct psr_config *psr_config,
3256 struct psr_context *psr_context)
3257{
3258 struct dc *dc;
3259 struct dmcu *dmcu;
3260 struct dmub_psr *psr;
3261 int i;
3262 unsigned int panel_inst;
3263 /* updateSinkPsrDpcdConfig*/
3264 union dpcd_psr_configuration psr_configuration;
3265 union dpcd_sink_active_vtotal_control_mode vtotal_control = {0};
3266
3267 psr_context->controllerId = CONTROLLER_ID_UNDEFINED;
3268
3269 if (!link)
3270 return false0;
3271
3272 dc = link->ctx->dc;
3273 dmcu = dc->res_pool->dmcu;
3274 psr = dc->res_pool->psr;
3275
3276 if (!dmcu && !psr)
3277 return false0;
3278
3279 if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
3280 return false0;
3281
3282
3283 memset(&psr_configuration, 0, sizeof(psr_configuration))__builtin_memset((&psr_configuration), (0), (sizeof(psr_configuration
)))
;
3284
3285 psr_configuration.bits.ENABLE = 1;
3286 psr_configuration.bits.CRC_VERIFICATION = 1;
3287 psr_configuration.bits.FRAME_CAPTURE_INDICATION =
3288 psr_config->psr_frame_capture_indication_req;
3289
3290 /* Check for PSR v2*/
3291 if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
3292 /* For PSR v2 selective update.
3293 * Indicates whether sink should start capturing
3294 * immediately following active scan line,
3295 * or starting with the 2nd active scan line.
3296 */
3297 psr_configuration.bits.LINE_CAPTURE_INDICATION = 0;
3298 /*For PSR v2, determines whether Sink should generate
3299 * IRQ_HPD when CRC mismatch is detected.
3300 */
3301 psr_configuration.bits.IRQ_HPD_WITH_CRC_ERROR = 1;
3302 /* For PSR v2, set the bit when the Source device will
3303 * be enabling PSR2 operation.
3304 */
3305 psr_configuration.bits.ENABLE_PSR2 = 1;
3306 /* For PSR v2, the Sink device must be able to receive
3307 * SU region updates early in the frame time.
3308 */
3309 psr_configuration.bits.EARLY_TRANSPORT_ENABLE = 1;
3310 }
3311
3312 dm_helpers_dp_write_dpcd(
3313 link->ctx,
3314 link,
3315 368,
3316 &psr_configuration.raw,
3317 sizeof(psr_configuration.raw));
3318
3319 if (link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) {
3320 dc_power_alpm_dpcd_enable(link, true1);
3321 psr_context->su_granularity_required =
3322 psr_config->su_granularity_required;
3323 psr_context->su_y_granularity =
3324 psr_config->su_y_granularity;
3325 psr_context->line_time_in_us =
3326 psr_config->line_time_in_us;
3327
3328 if (link->psr_settings.psr_vtotal_control_support) {
3329 psr_context->rate_control_caps = psr_config->rate_control_caps;
3330 vtotal_control.bits.ENABLE = true1;
3331 core_link_write_dpcd(link, DP_SINK_PSR_ACTIVE_VTOTAL_CONTROL_MODE0x375,
3332 &vtotal_control.raw, sizeof(vtotal_control.raw));
3333 }
3334 }
3335
3336 psr_context->channel = link->ddc->ddc_pin->hw_info.ddc_channel;
3337 psr_context->transmitterId = link->link_enc->transmitter;
3338 psr_context->engineId = link->link_enc->preferred_engine;
3339
3340 for (i = 0; i < MAX_PIPES6; i++) {
3341 if (dc->current_state->res_ctx.pipe_ctx[i].stream
3342 == stream) {
3343 /* dmcu -1 for all controller id values,
3344 * therefore +1 here
3345 */
3346 psr_context->controllerId =
3347 dc->current_state->res_ctx.
3348 pipe_ctx[i].stream_res.tg->inst + 1;
3349 break;
3350 }
3351 }
3352
3353 /* Hardcoded for now. Can be Pcie or Uniphy (or Unknown)*/
3354 psr_context->phyType = PHY_TYPE_UNIPHY;
3355 /*PhyId is associated with the transmitter id*/
3356 psr_context->smuPhyId =
3357 transmitter_to_phy_id(link->link_enc->transmitter);
3358
3359 psr_context->crtcTimingVerticalTotal = stream->timing.v_total;
3360 psr_context->vsync_rate_hz = div64_u64(div64_u64((stream->
3361 timing.pix_clk_100hz * 100),
3362 stream->timing.v_total),
3363 stream->timing.h_total);
3364
3365 psr_context->psrSupportedDisplayConfig = true1;
3366 psr_context->psrExitLinkTrainingRequired =
3367 psr_config->psr_exit_link_training_required;
3368 psr_context->sdpTransmitLineNumDeadline =
3369 psr_config->psr_sdp_transmit_line_num_deadline;
3370 psr_context->psrFrameCaptureIndicationReq =
3371 psr_config->psr_frame_capture_indication_req;
3372
3373 psr_context->skipPsrWaitForPllLock = 0; /* only = 1 in KV */
3374
3375 psr_context->numberOfControllers =
3376 link->dc->res_pool->timing_generator_count;
3377
3378 psr_context->rfb_update_auto_en = true1;
3379
3380 /* 2 frames before enter PSR. */
3381 psr_context->timehyst_frames = 2;
3382 /* half a frame
3383 * (units in 100 lines, i.e. a value of 1 represents 100 lines)
3384 */
3385 psr_context->hyst_lines = stream->timing.v_total / 2 / 100;
3386 psr_context->aux_repeats = 10;
3387
3388 psr_context->psr_level.u32all = 0;
3389
3390 /*skip power down the single pipe since it blocks the cstate*/
3391#if defined(CONFIG_DRM_AMD_DC_DCN1)
3392 if (link->ctx->asic_id.chip_family >= FAMILY_RV142) {
3393 switch(link->ctx->asic_id.chip_family) {
3394 case FAMILY_YELLOW_CARP146:
3395 case AMDGPU_FAMILY_GC_10_3_6149:
3396 case AMDGPU_FAMILY_GC_11_0_1148:
3397 if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable)
3398 psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true1;
3399 break;
3400 default:
3401 psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true1;
3402 break;
3403 }
3404 }
3405#else
3406 if (link->ctx->asic_id.chip_family >= FAMILY_RV142)
3407 psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true1;
3408#endif
3409
3410 /* SMU will perform additional powerdown sequence.
3411 * For unsupported ASICs, set psr_level flag to skip PSR
3412 * static screen notification to SMU.
3413 * (Always set for DAL2, did not check ASIC)
3414 */
3415 psr_context->allow_smu_optimizations = psr_config->allow_smu_optimizations;
3416 psr_context->allow_multi_disp_optimizations = psr_config->allow_multi_disp_optimizations;
3417
3418 /* Complete PSR entry before aborting to prevent intermittent
3419 * freezes on certain eDPs
3420 */
3421 psr_context->psr_level.bits.DISABLE_PSR_ENTRY_ABORT = 1;
3422
3423 /* enable ALPM */
3424 psr_context->psr_level.bits.DISABLE_ALPM = 0;
3425 psr_context->psr_level.bits.ALPM_DEFAULT_PD_MODE = 1;
3426
3427 /* Controls additional delay after remote frame capture before
3428 * continuing power down, default = 0
3429 */
3430 psr_context->frame_delay = 0;
3431
3432 if (psr) {
3433 link->psr_settings.psr_feature_enabled = psr->funcs->psr_copy_settings(psr,
3434 link, psr_context, panel_inst);
3435 link->psr_settings.psr_power_opt = 0;
3436 link->psr_settings.psr_allow_active = 0;
3437 }
3438 else
3439 link->psr_settings.psr_feature_enabled = dmcu->funcs->setup_psr(dmcu, link, psr_context);
3440
3441 /* psr_enabled == 0 indicates setup_psr did not succeed, but this
3442 * should not happen since firmware should be running at this point
3443 */
3444 if (link->psr_settings.psr_feature_enabled == 0)
3445 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.c"
, 3445); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
3446
3447 return true1;
3448
3449}
3450
3451void dc_link_get_psr_residency(const struct dc_link *link, uint32_t *residency)
3452{
3453 struct dc *dc = link->ctx->dc;
3454 struct dmub_psr *psr = dc->res_pool->psr;
3455 unsigned int panel_inst;
3456
3457 if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
3458 return;
3459
3460 /* PSR residency measurements only supported on DMCUB */
3461 if (psr != NULL((void *)0) && link->psr_settings.psr_feature_enabled)
3462 psr->funcs->psr_get_residency(psr, residency, panel_inst);
3463 else
3464 *residency = 0;
3465}
3466
3467bool_Bool dc_link_set_sink_vtotal_in_psr_active(const struct dc_link *link, uint16_t psr_vtotal_idle, uint16_t psr_vtotal_su)
3468{
3469 struct dc *dc = link->ctx->dc;
3470 struct dmub_psr *psr = dc->res_pool->psr;
3471
3472 if (psr == NULL((void *)0) || !link->psr_settings.psr_feature_enabled || !link->psr_settings.psr_vtotal_control_support)
3473 return false0;
3474
3475 psr->funcs->psr_set_sink_vtotal_in_psr_active(psr, psr_vtotal_idle, psr_vtotal_su);
3476
3477 return true1;
3478}
3479
3480const struct dc_link_status *dc_link_get_status(const struct dc_link *link)
3481{
3482 return &link->link_status;
3483}
3484
3485void core_link_resume(struct dc_link *link)
3486{
3487 if (link->connector_signal != SIGNAL_TYPE_VIRTUAL)
3488 program_hpd_filter(link);
3489}
3490
3491static struct fixed31_32 get_pbn_per_slot(struct dc_stream_state *stream)
3492{
3493 struct fixed31_32 mbytes_per_sec;
3494 uint32_t link_rate_in_mbytes_per_sec = dc_link_bandwidth_kbps(stream->link,
3495 &stream->link->cur_link_settings);
3496 link_rate_in_mbytes_per_sec /= 8000; /* Kbits to MBytes */
3497
3498 mbytes_per_sec = dc_fixpt_from_int(link_rate_in_mbytes_per_sec);
3499
3500 return dc_fixpt_div_int(mbytes_per_sec, 54);
3501}
3502
3503static struct fixed31_32 get_pbn_from_bw_in_kbps(uint64_t kbps)
3504{
3505 struct fixed31_32 peak_kbps;
3506 uint32_t numerator = 0;
3507 uint32_t denominator = 1;
3508
3509 /*
3510 * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006
3511 * The unit of 54/64Mbytes/sec is an arbitrary unit chosen based on
3512 * common multiplier to render an integer PBN for all link rate/lane
3513 * counts combinations
3514 * calculate
3515 * peak_kbps *= (1006/1000)
3516 * peak_kbps *= (64/54)
3517 * peak_kbps *= 8 convert to bytes
3518 */
3519
3520 numerator = 64 * PEAK_FACTOR_X1000;
3521 denominator = 54 * 8 * 1000 * 1000;
3522 kbps *= numerator;
3523 peak_kbps = dc_fixpt_from_fraction(kbps, denominator);
3524
3525 return peak_kbps;
3526}
3527
3528static struct fixed31_32 get_pbn_from_timing(struct pipe_ctx *pipe_ctx)
3529{
3530 uint64_t kbps;
3531
3532 kbps = dc_bandwidth_in_kbps_from_timing(&pipe_ctx->stream->timing);
3533 return get_pbn_from_bw_in_kbps(kbps);
3534}
3535
3536static void update_mst_stream_alloc_table(
3537 struct dc_link *link,
3538 struct stream_encoder *stream_enc,
3539 struct hpo_dp_stream_encoder *hpo_dp_stream_enc, // TODO: Rename stream_enc to dio_stream_enc?
3540 const struct dc_dp_mst_stream_allocation_table *proposed_table)
3541{
3542 struct link_mst_stream_allocation work_table[MAX_CONTROLLER_NUM] = { 0 };
3543 struct link_mst_stream_allocation *dc_alloc;
3544
3545 int i;
3546 int j;
3547
3548 /* if DRM proposed_table has more than one new payload */
3549 ASSERT(proposed_table->stream_count -do { if (({ static int __warned; int __ret = !!(!(proposed_table
->stream_count - link->mst_stream_alloc_table.stream_count
< 2)); if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(proposed_table->stream_count - link->mst_stream_alloc_table.stream_count < 2)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c", 3550
); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while
(0); } while (0)
3550 link->mst_stream_alloc_table.stream_count < 2)do { if (({ static int __warned; int __ret = !!(!(proposed_table
->stream_count - link->mst_stream_alloc_table.stream_count
< 2)); if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(proposed_table->stream_count - link->mst_stream_alloc_table.stream_count < 2)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c", 3550
); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while
(0); } while (0)
;
3551
3552 /* copy proposed_table to link, add stream encoder */
3553 for (i = 0; i < proposed_table->stream_count; i++) {
3554
3555 for (j = 0; j < link->mst_stream_alloc_table.stream_count; j++) {
3556 dc_alloc =
3557 &link->mst_stream_alloc_table.stream_allocations[j];
3558
3559 if (dc_alloc->vcp_id ==
3560 proposed_table->stream_allocations[i].vcp_id) {
3561
3562 work_table[i] = *dc_alloc;
3563 work_table[i].slot_count = proposed_table->stream_allocations[i].slot_count;
3564 break; /* exit j loop */
3565 }
3566 }
3567
3568 /* new vcp_id */
3569 if (j == link->mst_stream_alloc_table.stream_count) {
3570 work_table[i].vcp_id =
3571 proposed_table->stream_allocations[i].vcp_id;
3572 work_table[i].slot_count =
3573 proposed_table->stream_allocations[i].slot_count;
3574 work_table[i].stream_enc = stream_enc;
3575 work_table[i].hpo_dp_stream_enc = hpo_dp_stream_enc;
3576 }
3577 }
3578
3579 /* update link->mst_stream_alloc_table with work_table */
3580 link->mst_stream_alloc_table.stream_count =
3581 proposed_table->stream_count;
3582 for (i = 0; i < MAX_CONTROLLER_NUM; i++)
3583 link->mst_stream_alloc_table.stream_allocations[i] =
3584 work_table[i];
3585}
3586
3587static void remove_stream_from_alloc_table(
3588 struct dc_link *link,
3589 struct stream_encoder *dio_stream_enc,
3590 struct hpo_dp_stream_encoder *hpo_dp_stream_enc)
3591{
3592 int i = 0;
3593 struct link_mst_stream_allocation_table *table =
3594 &link->mst_stream_alloc_table;
3595
3596 if (hpo_dp_stream_enc) {
3597 for (; i < table->stream_count; i++)
3598 if (hpo_dp_stream_enc == table->stream_allocations[i].hpo_dp_stream_enc)
3599 break;
3600 } else {
3601 for (; i < table->stream_count; i++)
3602 if (dio_stream_enc == table->stream_allocations[i].stream_enc)
3603 break;
3604 }
3605
3606 if (i < table->stream_count) {
3607 i++;
3608 for (; i < table->stream_count; i++)
3609 table->stream_allocations[i-1] = table->stream_allocations[i];
3610 memset(&table->stream_allocations[table->stream_count-1], 0,__builtin_memset((&table->stream_allocations[table->
stream_count-1]), (0), (sizeof(struct link_mst_stream_allocation
)))
3611 sizeof(struct link_mst_stream_allocation))__builtin_memset((&table->stream_allocations[table->
stream_count-1]), (0), (sizeof(struct link_mst_stream_allocation
)))
;
3612 table->stream_count--;
3613 }
3614}
3615
3616static void dc_log_vcp_x_y(const struct dc_link *link, struct fixed31_32 avg_time_slots_per_mtp)
3617{
3618 const uint32_t VCP_Y_PRECISION = 1000;
3619 uint64_t vcp_x, vcp_y;
3620
3621 // Add 0.5*(1/VCP_Y_PRECISION) to round up to decimal precision
3622 avg_time_slots_per_mtp = dc_fixpt_add(
3623 avg_time_slots_per_mtp, dc_fixpt_from_fraction(1, 2 * VCP_Y_PRECISION));
3624
3625 vcp_x = dc_fixpt_floor(avg_time_slots_per_mtp);
3626 vcp_y = dc_fixpt_floor(
3627 dc_fixpt_mul_int(
3628 dc_fixpt_sub_int(avg_time_slots_per_mtp, dc_fixpt_floor(avg_time_slots_per_mtp)),
3629 VCP_Y_PRECISION));
3630
3631 if (link->type == dc_connection_mst_branch)
3632 DC_LOG_DP2("MST Update Payload: set_throttled_vcp_size slot X.Y for MST stream "___drm_dbg(((void *)0), DRM_UT_KMS, "MST Update Payload: set_throttled_vcp_size slot X.Y for MST stream "
"X: %lld Y: %lld/%d", vcp_x, vcp_y, VCP_Y_PRECISION)
3633 "X: %lld Y: %lld/%d", vcp_x, vcp_y, VCP_Y_PRECISION)___drm_dbg(((void *)0), DRM_UT_KMS, "MST Update Payload: set_throttled_vcp_size slot X.Y for MST stream "
"X: %lld Y: %lld/%d", vcp_x, vcp_y, VCP_Y_PRECISION)
;
3634 else
3635 DC_LOG_DP2("SST Update Payload: set_throttled_vcp_size slot X.Y for SST stream "___drm_dbg(((void *)0), DRM_UT_KMS, "SST Update Payload: set_throttled_vcp_size slot X.Y for SST stream "
"X: %lld Y: %lld/%d", vcp_x, vcp_y, VCP_Y_PRECISION)
3636 "X: %lld Y: %lld/%d", vcp_x, vcp_y, VCP_Y_PRECISION)___drm_dbg(((void *)0), DRM_UT_KMS, "SST Update Payload: set_throttled_vcp_size slot X.Y for SST stream "
"X: %lld Y: %lld/%d", vcp_x, vcp_y, VCP_Y_PRECISION)
;
3637}
3638
3639/*
3640 * Payload allocation/deallocation for SST introduced in DP2.0
3641 */
3642static enum dc_status dc_link_update_sst_payload(struct pipe_ctx *pipe_ctx,
3643 bool_Bool allocate)
3644{
3645 struct dc_stream_state *stream = pipe_ctx->stream;
3646 struct dc_link *link = stream->link;
3647 struct link_mst_stream_allocation_table proposed_table = {0};
3648 struct fixed31_32 avg_time_slots_per_mtp;
3649 const struct dc_link_settings empty_link_settings = {0};
3650 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
3651 DC_LOGGER_INIT(link->ctx->logger);
3652
3653 /* slot X.Y for SST payload deallocate */
3654 if (!allocate) {
3655 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
3656
3657 dc_log_vcp_x_y(link, avg_time_slots_per_mtp);
3658
3659 if (link_hwss->ext.set_throttled_vcp_size)
3660 link_hwss->ext.set_throttled_vcp_size(pipe_ctx,
3661 avg_time_slots_per_mtp);
3662 if (link_hwss->ext.set_hblank_min_symbol_width)
3663 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,
3664 &empty_link_settings,
3665 avg_time_slots_per_mtp);
3666 }
3667
3668 /* calculate VC payload and update branch with new payload allocation table*/
3669 if (!dpcd_write_128b_132b_sst_payload_allocation_table(
3670 stream,
3671 link,
3672 &proposed_table,
3673 allocate)) {
3674 DC_LOG_ERROR("SST Update Payload: Failed to update "__drm_err("SST Update Payload: Failed to update " "allocation table for "
"pipe idx: %d\n", pipe_ctx->pipe_idx)
3675 "allocation table for "__drm_err("SST Update Payload: Failed to update " "allocation table for "
"pipe idx: %d\n", pipe_ctx->pipe_idx)
3676 "pipe idx: %d\n",__drm_err("SST Update Payload: Failed to update " "allocation table for "
"pipe idx: %d\n", pipe_ctx->pipe_idx)
3677 pipe_ctx->pipe_idx)__drm_err("SST Update Payload: Failed to update " "allocation table for "
"pipe idx: %d\n", pipe_ctx->pipe_idx)
;
3678 return DC_FAIL_DP_PAYLOAD_ALLOCATION;
3679 }
3680
3681 proposed_table.stream_allocations[0].hpo_dp_stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
3682
3683 ASSERT(proposed_table.stream_count == 1)do { if (({ static int __warned; int __ret = !!(!(proposed_table
.stream_count == 1)); if (__ret && !__warned) { printf
("WARNING %s failed at %s:%d\n", "!(proposed_table.stream_count == 1)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c", 3683
); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while
(0); } while (0)
;
3684
3685 //TODO - DP2.0 Logging: Instead of hpo_dp_stream_enc pointer, log instance id
3686 DC_LOG_DP2("SST Update Payload: hpo_dp_stream_enc: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "SST Update Payload: hpo_dp_stream_enc: %p "
"vcp_id: %d " "slot_count: %d\n", (void *) proposed_table
.stream_allocations[0].hpo_dp_stream_enc, proposed_table.stream_allocations
[0].vcp_id, proposed_table.stream_allocations[0].slot_count)
3687 "vcp_id: %d "___drm_dbg(((void *)0), DRM_UT_KMS, "SST Update Payload: hpo_dp_stream_enc: %p "
"vcp_id: %d " "slot_count: %d\n", (void *) proposed_table
.stream_allocations[0].hpo_dp_stream_enc, proposed_table.stream_allocations
[0].vcp_id, proposed_table.stream_allocations[0].slot_count)
3688 "slot_count: %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "SST Update Payload: hpo_dp_stream_enc: %p "
"vcp_id: %d " "slot_count: %d\n", (void *) proposed_table
.stream_allocations[0].hpo_dp_stream_enc, proposed_table.stream_allocations
[0].vcp_id, proposed_table.stream_allocations[0].slot_count)
3689 (void *) proposed_table.stream_allocations[0].hpo_dp_stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "SST Update Payload: hpo_dp_stream_enc: %p "
"vcp_id: %d " "slot_count: %d\n", (void *) proposed_table
.stream_allocations[0].hpo_dp_stream_enc, proposed_table.stream_allocations
[0].vcp_id, proposed_table.stream_allocations[0].slot_count)
3690 proposed_table.stream_allocations[0].vcp_id,___drm_dbg(((void *)0), DRM_UT_KMS, "SST Update Payload: hpo_dp_stream_enc: %p "
"vcp_id: %d " "slot_count: %d\n", (void *) proposed_table
.stream_allocations[0].hpo_dp_stream_enc, proposed_table.stream_allocations
[0].vcp_id, proposed_table.stream_allocations[0].slot_count)
3691 proposed_table.stream_allocations[0].slot_count)___drm_dbg(((void *)0), DRM_UT_KMS, "SST Update Payload: hpo_dp_stream_enc: %p "
"vcp_id: %d " "slot_count: %d\n", (void *) proposed_table
.stream_allocations[0].hpo_dp_stream_enc, proposed_table.stream_allocations
[0].vcp_id, proposed_table.stream_allocations[0].slot_count)
;
3692
3693 /* program DP source TX for payload */
3694 link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,
3695 &proposed_table);
3696
3697 /* poll for ACT handled */
3698 if (!dpcd_poll_for_allocation_change_trigger(link)) {
3699 // Failures will result in blackscreen and errors logged
3700 BREAK_TO_DEBUGGER()do { ___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s():%d\n", __func__
, 3700); do {} while (0); } while (0)
;
3701 }
3702
3703 /* slot X.Y for SST payload allocate */
3704 if (allocate && dp_get_link_encoding_format(&link->cur_link_settings) ==
3705 DP_128b_132b_ENCODING) {
3706 avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, link);
3707
3708 dc_log_vcp_x_y(link, avg_time_slots_per_mtp);
3709
3710 if (link_hwss->ext.set_throttled_vcp_size)
3711 link_hwss->ext.set_throttled_vcp_size(pipe_ctx,
3712 avg_time_slots_per_mtp);
3713 if (link_hwss->ext.set_hblank_min_symbol_width)
3714 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,
3715 &link->cur_link_settings,
3716 avg_time_slots_per_mtp);
3717 }
3718
3719 /* Always return DC_OK.
3720 * If part of sequence fails, log failure(s) and show blackscreen
3721 */
3722 return DC_OK;
3723}
3724
3725/* convert link_mst_stream_alloc_table to dm dp_mst_stream_alloc_table
3726 * because stream_encoder is not exposed to dm
3727 */
3728enum dc_status dc_link_allocate_mst_payload(struct pipe_ctx *pipe_ctx)
3729{
3730 struct dc_stream_state *stream = pipe_ctx->stream;
3731 struct dc_link *link = stream->link;
3732 struct dc_dp_mst_stream_allocation_table proposed_table = {0};
3733 struct fixed31_32 avg_time_slots_per_mtp;
3734 struct fixed31_32 pbn;
3735 struct fixed31_32 pbn_per_slot;
3736 int i;
3737 enum act_return_status ret;
3738 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
3739 DC_LOGGER_INIT(link->ctx->logger);
3740
3741 /* enable_link_dp_mst already check link->enabled_stream_count
3742 * and stream is in link->stream[]. This is called during set mode,
3743 * stream_enc is available.
3744 */
3745
3746 /* get calculate VC payload for stream: stream_alloc */
3747 if (dm_helpers_dp_mst_write_payload_allocation_table(
3748 stream->ctx,
3749 stream,
3750 &proposed_table,
3751 true1))
3752 update_mst_stream_alloc_table(
3753 link,
3754 pipe_ctx->stream_res.stream_enc,
3755 pipe_ctx->stream_res.hpo_dp_stream_enc,
3756 &proposed_table);
3757 else
3758 DC_LOG_WARNING("Failed to update"printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
3759 "MST allocation table for"printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
3760 "pipe idx:%d\n",printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
3761 pipe_ctx->pipe_idx)printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
;
3762
3763 DC_LOG_MST("%s "___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3764 "stream_count: %d: \n ",___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3765 __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3766 link->mst_stream_alloc_table.stream_count)___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
;
3767
3768 for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
3769 DC_LOG_MST("stream_enc[%d]: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3770 "stream[%d].hpo_dp_stream_enc: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3771 "stream[%d].vcp_id: %d "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3772 "stream[%d].slot_count: %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3773 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3774 (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3775 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3776 (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3777 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3778 link->mst_stream_alloc_table.stream_allocations[i].vcp_id,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3779 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3780 link->mst_stream_alloc_table.stream_allocations[i].slot_count)___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
;
3781 }
3782
3783 ASSERT(proposed_table.stream_count > 0)do { if (({ static int __warned; int __ret = !!(!(proposed_table
.stream_count > 0)); if (__ret && !__warned) { printf
("WARNING %s failed at %s:%d\n", "!(proposed_table.stream_count > 0)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c", 3783
); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while
(0); } while (0)
;
3784
3785 /* program DP source TX for payload */
3786 if (link_hwss->ext.update_stream_allocation_table == NULL((void *)0) ||
3787 dp_get_link_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {
3788 DC_LOG_ERROR("Failure: unknown encoding format\n")__drm_err("Failure: unknown encoding format\n");
3789 return DC_ERROR_UNEXPECTED;
3790 }
3791
3792 link_hwss->ext.update_stream_allocation_table(link,
3793 &pipe_ctx->link_res,
3794 &link->mst_stream_alloc_table);
3795
3796 /* send down message */
3797 ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
3798 stream->ctx,
3799 stream);
3800
3801 if (ret != ACT_LINK_LOST) {
3802 dm_helpers_dp_mst_send_payload_allocation(
3803 stream->ctx,
3804 stream,
3805 true1);
3806 }
3807
3808 /* slot X.Y for only current stream */
3809 pbn_per_slot = get_pbn_per_slot(stream);
3810 if (pbn_per_slot.value == 0) {
3811 DC_LOG_ERROR("Failure: pbn_per_slot==0 not allowed. Cannot continue, returning DC_UNSUPPORTED_VALUE.\n")__drm_err("Failure: pbn_per_slot==0 not allowed. Cannot continue, returning DC_UNSUPPORTED_VALUE.\n"
)
;
3812 return DC_UNSUPPORTED_VALUE;
3813 }
3814 pbn = get_pbn_from_timing(pipe_ctx);
3815 avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
3816
3817 dc_log_vcp_x_y(link, avg_time_slots_per_mtp);
3818
3819 if (link_hwss->ext.set_throttled_vcp_size)
3820 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);
3821 if (link_hwss->ext.set_hblank_min_symbol_width)
3822 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,
3823 &link->cur_link_settings,
3824 avg_time_slots_per_mtp);
3825
3826 return DC_OK;
3827
3828}
3829
3830enum dc_status dc_link_reduce_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)
3831{
3832 struct dc_stream_state *stream = pipe_ctx->stream;
3833 struct dc_link *link = stream->link;
3834 struct fixed31_32 avg_time_slots_per_mtp;
3835 struct fixed31_32 pbn;
3836 struct fixed31_32 pbn_per_slot;
3837 struct dc_dp_mst_stream_allocation_table proposed_table = {0};
3838 uint8_t i;
3839 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
3840 DC_LOGGER_INIT(link->ctx->logger);
3841
3842 /* decrease throttled vcp size */
3843 pbn_per_slot = get_pbn_per_slot(stream);
3844 pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);
3845 avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
3846
3847 if (link_hwss->ext.set_throttled_vcp_size)
3848 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);
3849 if (link_hwss->ext.set_hblank_min_symbol_width)
3850 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,
3851 &link->cur_link_settings,
3852 avg_time_slots_per_mtp);
3853
3854 /* send ALLOCATE_PAYLOAD sideband message with updated pbn */
3855 dm_helpers_dp_mst_send_payload_allocation(
3856 stream->ctx,
3857 stream,
3858 true1);
3859
3860 /* notify immediate branch device table update */
3861 if (dm_helpers_dp_mst_write_payload_allocation_table(
3862 stream->ctx,
3863 stream,
3864 &proposed_table,
3865 true1)) {
3866 /* update mst stream allocation table software state */
3867 update_mst_stream_alloc_table(
3868 link,
3869 pipe_ctx->stream_res.stream_enc,
3870 pipe_ctx->stream_res.hpo_dp_stream_enc,
3871 &proposed_table);
3872 } else {
3873 DC_LOG_WARNING("Failed to update"printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
3874 "MST allocation table for"printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
3875 "pipe idx:%d\n",printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
3876 pipe_ctx->pipe_idx)printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
;
3877 }
3878
3879 DC_LOG_MST("%s "___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3880 "stream_count: %d: \n ",___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3881 __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3882 link->mst_stream_alloc_table.stream_count)___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
;
3883
3884 for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
3885 DC_LOG_MST("stream_enc[%d]: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3886 "stream[%d].hpo_dp_stream_enc: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3887 "stream[%d].vcp_id: %d "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3888 "stream[%d].slot_count: %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3889 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3890 (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3891 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3892 (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3893 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3894 link->mst_stream_alloc_table.stream_allocations[i].vcp_id,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3895 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3896 link->mst_stream_alloc_table.stream_allocations[i].slot_count)___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
;
3897 }
3898
3899 ASSERT(proposed_table.stream_count > 0)do { if (({ static int __warned; int __ret = !!(!(proposed_table
.stream_count > 0)); if (__ret && !__warned) { printf
("WARNING %s failed at %s:%d\n", "!(proposed_table.stream_count > 0)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c", 3899
); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while
(0); } while (0)
;
3900
3901 /* update mst stream allocation table hardware state */
3902 if (link_hwss->ext.update_stream_allocation_table == NULL((void *)0) ||
3903 dp_get_link_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {
3904 DC_LOG_ERROR("Failure: unknown encoding format\n")__drm_err("Failure: unknown encoding format\n");
3905 return DC_ERROR_UNEXPECTED;
3906 }
3907
3908 link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,
3909 &link->mst_stream_alloc_table);
3910
3911 /* poll for immediate branch device ACT handled */
3912 dm_helpers_dp_mst_poll_for_allocation_change_trigger(
3913 stream->ctx,
3914 stream);
3915
3916 return DC_OK;
3917}
3918
3919enum dc_status dc_link_increase_mst_payload(struct pipe_ctx *pipe_ctx, uint32_t bw_in_kbps)
3920{
3921 struct dc_stream_state *stream = pipe_ctx->stream;
3922 struct dc_link *link = stream->link;
3923 struct fixed31_32 avg_time_slots_per_mtp;
3924 struct fixed31_32 pbn;
3925 struct fixed31_32 pbn_per_slot;
3926 struct dc_dp_mst_stream_allocation_table proposed_table = {0};
3927 uint8_t i;
3928 enum act_return_status ret;
3929 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
3930 DC_LOGGER_INIT(link->ctx->logger);
3931
3932 /* notify immediate branch device table update */
3933 if (dm_helpers_dp_mst_write_payload_allocation_table(
3934 stream->ctx,
3935 stream,
3936 &proposed_table,
3937 true1)) {
3938 /* update mst stream allocation table software state */
3939 update_mst_stream_alloc_table(
3940 link,
3941 pipe_ctx->stream_res.stream_enc,
3942 pipe_ctx->stream_res.hpo_dp_stream_enc,
3943 &proposed_table);
3944 }
3945
3946 DC_LOG_MST("%s "___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3947 "stream_count: %d: \n ",___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3948 __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
3949 link->mst_stream_alloc_table.stream_count)___drm_dbg(((void *)0), DRM_UT_KMS, "%s " "stream_count: %d: \n "
, __func__, link->mst_stream_alloc_table.stream_count)
;
3950
3951 for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
3952 DC_LOG_MST("stream_enc[%d]: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3953 "stream[%d].hpo_dp_stream_enc: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3954 "stream[%d].vcp_id: %d "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3955 "stream[%d].slot_count: %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3956 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3957 (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3958 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3959 (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3960 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3961 link->mst_stream_alloc_table.stream_allocations[i].vcp_id,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3962 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
3963 link->mst_stream_alloc_table.stream_allocations[i].slot_count)___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
;
3964 }
3965
3966 ASSERT(proposed_table.stream_count > 0)do { if (({ static int __warned; int __ret = !!(!(proposed_table
.stream_count > 0)); if (__ret && !__warned) { printf
("WARNING %s failed at %s:%d\n", "!(proposed_table.stream_count > 0)"
, "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c", 3966
); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do {} while
(0); } while (0)
;
3967
3968 /* update mst stream allocation table hardware state */
3969 if (link_hwss->ext.update_stream_allocation_table == NULL((void *)0) ||
3970 dp_get_link_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {
3971 DC_LOG_ERROR("Failure: unknown encoding format\n")__drm_err("Failure: unknown encoding format\n");
3972 return DC_ERROR_UNEXPECTED;
3973 }
3974
3975 link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,
3976 &link->mst_stream_alloc_table);
3977
3978 /* poll for immediate branch device ACT handled */
3979 ret = dm_helpers_dp_mst_poll_for_allocation_change_trigger(
3980 stream->ctx,
3981 stream);
3982
3983 if (ret != ACT_LINK_LOST) {
3984 /* send ALLOCATE_PAYLOAD sideband message with updated pbn */
3985 dm_helpers_dp_mst_send_payload_allocation(
3986 stream->ctx,
3987 stream,
3988 true1);
3989 }
3990
3991 /* increase throttled vcp size */
3992 pbn = get_pbn_from_bw_in_kbps(bw_in_kbps);
3993 pbn_per_slot = get_pbn_per_slot(stream);
3994 avg_time_slots_per_mtp = dc_fixpt_div(pbn, pbn_per_slot);
3995
3996 if (link_hwss->ext.set_throttled_vcp_size)
3997 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);
3998 if (link_hwss->ext.set_hblank_min_symbol_width)
3999 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,
4000 &link->cur_link_settings,
4001 avg_time_slots_per_mtp);
4002
4003 return DC_OK;
4004}
4005
4006static enum dc_status deallocate_mst_payload(struct pipe_ctx *pipe_ctx)
4007{
4008 struct dc_stream_state *stream = pipe_ctx->stream;
4009 struct dc_link *link = stream->link;
4010 struct dc_dp_mst_stream_allocation_table proposed_table = {0};
4011 struct fixed31_32 avg_time_slots_per_mtp = dc_fixpt_from_int(0);
4012 int i;
4013 bool_Bool mst_mode = (link->type == dc_connection_mst_branch);
4014 /* adjust for drm changes*/
4015 bool_Bool update_drm_mst_state = true1;
4016 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
4017 const struct dc_link_settings empty_link_settings = {0};
4018 DC_LOGGER_INIT(link->ctx->logger);
4019
4020
4021 /* deallocate_mst_payload is called before disable link. When mode or
4022 * disable/enable monitor, new stream is created which is not in link
4023 * stream[] yet. For this, payload is not allocated yet, so de-alloc
4024 * should not done. For new mode set, map_resources will get engine
4025 * for new stream, so stream_enc->id should be validated until here.
4026 */
4027
4028 /* slot X.Y */
4029 if (link_hwss->ext.set_throttled_vcp_size)
4030 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);
4031 if (link_hwss->ext.set_hblank_min_symbol_width)
4032 link_hwss->ext.set_hblank_min_symbol_width(pipe_ctx,
4033 &empty_link_settings,
4034 avg_time_slots_per_mtp);
4035
4036 if (mst_mode || update_drm_mst_state) {
4037 /* when link is in mst mode, reply on mst manager to remove
4038 * payload
4039 */
4040 if (dm_helpers_dp_mst_write_payload_allocation_table(
4041 stream->ctx,
4042 stream,
4043 &proposed_table,
4044 false0))
4045
4046 update_mst_stream_alloc_table(
4047 link,
4048 pipe_ctx->stream_res.stream_enc,
4049 pipe_ctx->stream_res.hpo_dp_stream_enc,
4050 &proposed_table);
4051 else
4052 DC_LOG_WARNING("Failed to update"printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
4053 "MST allocation table for"printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
4054 "pipe idx:%d\n",printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
4055 pipe_ctx->pipe_idx)printk("\0014" "[" "drm" "] " "Failed to update" "MST allocation table for"
"pipe idx:%d\n", pipe_ctx->pipe_idx)
;
4056 } else {
4057 /* when link is no longer in mst mode (mst hub unplugged),
4058 * remove payload with default dc logic
4059 */
4060 remove_stream_from_alloc_table(link, pipe_ctx->stream_res.stream_enc,
4061 pipe_ctx->stream_res.hpo_dp_stream_enc);
4062 }
4063
4064 DC_LOG_MST("%s"___drm_dbg(((void *)0), DRM_UT_KMS, "%s" "stream_count: %d: "
, __func__, link->mst_stream_alloc_table.stream_count)
4065 "stream_count: %d: ",___drm_dbg(((void *)0), DRM_UT_KMS, "%s" "stream_count: %d: "
, __func__, link->mst_stream_alloc_table.stream_count)
4066 __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s" "stream_count: %d: "
, __func__, link->mst_stream_alloc_table.stream_count)
4067 link->mst_stream_alloc_table.stream_count)___drm_dbg(((void *)0), DRM_UT_KMS, "%s" "stream_count: %d: "
, __func__, link->mst_stream_alloc_table.stream_count)
;
4068
4069 for (i = 0; i < MAX_CONTROLLER_NUM; i++) {
4070 DC_LOG_MST("stream_enc[%d]: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4071 "stream[%d].hpo_dp_stream_enc: %p "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4072 "stream[%d].vcp_id: %d "___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4073 "stream[%d].slot_count: %d\n",___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4074 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4075 (void *) link->mst_stream_alloc_table.stream_allocations[i].stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4076 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4077 (void *) link->mst_stream_alloc_table.stream_allocations[i].hpo_dp_stream_enc,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4078 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4079 link->mst_stream_alloc_table.stream_allocations[i].vcp_id,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4080 i,___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
4081 link->mst_stream_alloc_table.stream_allocations[i].slot_count)___drm_dbg(((void *)0), DRM_UT_KMS, "stream_enc[%d]: %p "
"stream[%d].hpo_dp_stream_enc: %p " "stream[%d].vcp_id: %d "
"stream[%d].slot_count: %d\n", i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].stream_enc, i, (void *) link->mst_stream_alloc_table
.stream_allocations[i].hpo_dp_stream_enc, i, link->mst_stream_alloc_table
.stream_allocations[i].vcp_id, i, link->mst_stream_alloc_table
.stream_allocations[i].slot_count)
;
4082 }
4083
4084 /* update mst stream allocation table hardware state */
4085 if (link_hwss->ext.update_stream_allocation_table == NULL((void *)0) ||
4086 dp_get_link_encoding_format(&link->cur_link_settings) == DP_UNKNOWN_ENCODING) {
4087 DC_LOG_DEBUG("Unknown encoding format\n")___drm_dbg(((void *)0), DRM_UT_KMS, "Unknown encoding format\n"
)
;
4088 return DC_ERROR_UNEXPECTED;
4089 }
4090
4091 link_hwss->ext.update_stream_allocation_table(link, &pipe_ctx->link_res,
4092 &link->mst_stream_alloc_table);
4093
4094 if (mst_mode) {
4095 dm_helpers_dp_mst_poll_for_allocation_change_trigger(
4096 stream->ctx,
4097 stream);
4098
4099 if (!update_drm_mst_state)
4100 dm_helpers_dp_mst_send_payload_allocation(
4101 stream->ctx,
4102 stream,
4103 false0);
4104 }
4105
4106 if (update_drm_mst_state)
4107 dm_helpers_dp_mst_send_payload_allocation(
4108 stream->ctx,
4109 stream,
4110 false0);
4111
4112 return DC_OK;
4113}
4114
4115
4116#if defined(CONFIG_DRM_AMD_DC_HDCP)
4117static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool_Bool dpms_off)
4118{
4119 struct cp_psp *cp_psp = &pipe_ctx->stream->ctx->cp_psp;
4120 struct link_encoder *link_enc = NULL((void *)0);
4121 struct cp_psp_stream_config config = {0};
4122 enum dp_panel_mode panel_mode =
4123 dp_get_panel_mode(pipe_ctx->stream->link);
4124
4125 if (cp_psp == NULL((void *)0) || cp_psp->funcs.update_stream_config == NULL((void *)0))
4126 return;
4127
4128 link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);
4129 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.c"
, 4129); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
4130 if (link_enc == NULL((void *)0))
4131 return;
4132
4133 /* otg instance */
4134 config.otg_inst = (uint8_t) pipe_ctx->stream_res.tg->inst;
4135
4136 /* dig front end */
4137 config.dig_fe = (uint8_t) pipe_ctx->stream_res.stream_enc->stream_enc_inst;
4138
4139 /* stream encoder index */
4140 config.stream_enc_idx = pipe_ctx->stream_res.stream_enc->id - ENGINE_ID_DIGA;
4141 if (is_dp_128b_132b_signal(pipe_ctx))
4142 config.stream_enc_idx =
4143 pipe_ctx->stream_res.hpo_dp_stream_enc->id - ENGINE_ID_HPO_DP_0;
4144
4145 /* dig back end */
4146 config.dig_be = pipe_ctx->stream->link->link_enc_hw_inst;
4147
4148 /* link encoder index */
4149 config.link_enc_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
4150 if (is_dp_128b_132b_signal(pipe_ctx))
4151 config.link_enc_idx = pipe_ctx->link_res.hpo_dp_link_enc->inst;
4152
4153 /* dio output index is dpia index for DPIA endpoint & dcio index by default */
4154 if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
4155 config.dio_output_idx = pipe_ctx->stream->link->link_id.enum_id - ENUM_ID_1;
4156 else
4157 config.dio_output_idx = link_enc->transmitter - TRANSMITTER_UNIPHY_A;
4158
4159
4160 /* phy index */
4161 config.phy_idx = resource_transmitter_to_phy_idx(
4162 pipe_ctx->stream->link->dc, link_enc->transmitter);
4163 if (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
4164 /* USB4 DPIA doesn't use PHY in our soc, initialize it to 0 */
4165 config.phy_idx = 0;
4166
4167 /* stream properties */
4168 config.assr_enabled = (panel_mode == DP_PANEL_MODE_EDP) ? 1 : 0;
4169 config.mst_enabled = (pipe_ctx->stream->signal ==
4170 SIGNAL_TYPE_DISPLAY_PORT_MST) ? 1 : 0;
4171 config.dp2_enabled = is_dp_128b_132b_signal(pipe_ctx) ? 1 : 0;
4172 config.usb4_enabled = (pipe_ctx->stream->link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ?
4173 1 : 0;
4174 config.dpms_off = dpms_off;
4175
4176 /* dm stream context */
4177 config.dm_stream_ctx = pipe_ctx->stream->dm_stream_context;
4178
4179 cp_psp->funcs.update_stream_config(cp_psp->handle, &config);
4180}
4181#endif
4182
4183static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pipe_ctx *pipe_ctx)
4184{
4185 struct dc *dc = pipe_ctx->stream->ctx->dc;
4186 struct dc_stream_state *stream = pipe_ctx->stream;
4187 struct link_mst_stream_allocation_table proposed_table = {0};
4188 struct fixed31_32 avg_time_slots_per_mtp;
4189 uint8_t req_slot_count = 0;
4190 uint8_t vc_id = 1; /// VC ID always 1 for SST
4191 struct dc_link_settings link_settings = pipe_ctx->link_config.dp_link_settings;
4192 const struct link_hwss *link_hwss = get_link_hwss(stream->link, &pipe_ctx->link_res);
4193 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
4194
4195 stream->link->cur_link_settings = link_settings;
4196
4197 if (link_hwss->ext.enable_dp_link_output)
4198 link_hwss->ext.enable_dp_link_output(stream->link, &pipe_ctx->link_res,
4199 stream->signal, pipe_ctx->clock_source->id,
4200 &link_settings);
4201
4202#ifdef DIAGS_BUILD
4203 /* Workaround for FPGA HPO capture DP link data:
4204 * HPO capture will set link to active mode
4205 * This workaround is required to get a capture from start of frame
4206 */
4207 if (!dc->debug.fpga_hpo_capture_en) {
4208 struct encoder_set_dp_phy_pattern_param params = {0};
4209 params.dp_phy_pattern = DP_TEST_PATTERN_VIDEO_MODE;
4210
4211 /* Set link active */
4212 stream->link->hpo_dp_link_enc->funcs->set_link_test_pattern(
4213 stream->link->hpo_dp_link_enc,
4214 &params);
4215 }
4216#endif
4217
4218 /* Enable DP_STREAM_ENC */
4219 dc->hwss.enable_stream(pipe_ctx);
4220
4221 /* Set DPS PPS SDP (AKA "info frames") */
4222 if (pipe_ctx->stream->timing.flags.DSC) {
4223 dp_set_dsc_pps_sdp(pipe_ctx, true1, true1);
4224 }
4225
4226 /* Allocate Payload */
4227 if ((stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) && (state->stream_count > 1)) {
4228 // MST case
4229 uint8_t i;
4230
4231 proposed_table.stream_count = state->stream_count;
4232 for (i = 0; i < state->stream_count; i++) {
4233 avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(state->streams[i], state->streams[i]->link);
4234 req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
4235 proposed_table.stream_allocations[i].slot_count = req_slot_count;
4236 proposed_table.stream_allocations[i].vcp_id = i+1;
4237 /* NOTE: This makes assumption that pipe_ctx index is same as stream index */
4238 proposed_table.stream_allocations[i].hpo_dp_stream_enc = state->res_ctx.pipe_ctx[i].stream_res.hpo_dp_stream_enc;
4239 }
4240 } else {
4241 // SST case
4242 avg_time_slots_per_mtp = calculate_sst_avg_time_slots_per_mtp(stream, stream->link);
4243 req_slot_count = dc_fixpt_ceil(avg_time_slots_per_mtp);
4244 proposed_table.stream_count = 1; /// Always 1 stream for SST
4245 proposed_table.stream_allocations[0].slot_count = req_slot_count;
4246 proposed_table.stream_allocations[0].vcp_id = vc_id;
4247 proposed_table.stream_allocations[0].hpo_dp_stream_enc = pipe_ctx->stream_res.hpo_dp_stream_enc;
4248 }
4249
4250 link_hwss->ext.update_stream_allocation_table(stream->link,
4251 &pipe_ctx->link_res,
4252 &proposed_table);
4253
4254 if (link_hwss->ext.set_throttled_vcp_size)
4255 link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);
4256
4257 dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings);
4258}
4259
4260void core_link_enable_stream(
4261 struct dc_state *state,
4262 struct pipe_ctx *pipe_ctx)
4263{
4264 struct dc *dc = pipe_ctx->stream->ctx->dc;
4265 struct dc_stream_state *stream = pipe_ctx->stream;
4266 struct dc_link *link = stream->sink->link;
4267 enum dc_status status;
4268 struct link_encoder *link_enc;
4269 enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO;
4270 struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg;
4271 const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
4272
4273 if (is_dp_128b_132b_signal(pipe_ctx))
4274 vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg;
4275
4276 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
4277
4278 if (pipe_ctx->stream->sink) {
4279 if (pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&
4280 pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_NONE) {
4281 DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x\n", __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s pipe_ctx dispname=%s signal=%x\n"
, __func__, pipe_ctx->stream->sink->edid_caps.display_name
, pipe_ctx->stream->signal)
4282 pipe_ctx->stream->sink->edid_caps.display_name,___drm_dbg(((void *)0), DRM_UT_KMS, "%s pipe_ctx dispname=%s signal=%x\n"
, __func__, pipe_ctx->stream->sink->edid_caps.display_name
, pipe_ctx->stream->signal)
4283 pipe_ctx->stream->signal)___drm_dbg(((void *)0), DRM_UT_KMS, "%s pipe_ctx dispname=%s signal=%x\n"
, __func__, pipe_ctx->stream->sink->edid_caps.display_name
, pipe_ctx->stream->signal)
;
4284 }
4285 }
4286
4287 if (!IS_DIAG_DC(dc->ctx->dce_environment)((dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) || (
dc->ctx->dce_environment == DCE_ENV_DIAG))
&&
4288 dc_is_virtual_signal(pipe_ctx->stream->signal))
4289 return;
4290
4291 link_enc = link_enc_cfg_get_link_enc(link);
4292 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.c"
, 4292); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
4293
4294 if (!dc_is_virtual_signal(pipe_ctx->stream->signal)
4295 && !is_dp_128b_132b_signal(pipe_ctx)) {
4296 if (link_enc)
4297 link_enc->funcs->setup(
4298 link_enc,
4299 pipe_ctx->stream->signal);
4300 }
4301
4302 pipe_ctx->stream->link->link_state_valid = true1;
4303
4304 if (pipe_ctx->stream_res.tg->funcs->set_out_mux) {
4305 if (is_dp_128b_132b_signal(pipe_ctx))
4306 otg_out_dest = OUT_MUX_HPO_DP;
4307 else
4308 otg_out_dest = OUT_MUX_DIO;
4309 pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest);
4310 }
4311
4312 link_hwss->setup_stream_attribute(pipe_ctx);
4313
4314 if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)(dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS)) {
4315 bool_Bool apply_edp_fast_boot_optimization =
4316 pipe_ctx->stream->apply_edp_fast_boot_optimization;
4317
4318 pipe_ctx->stream->apply_edp_fast_boot_optimization = false0;
4319
4320 // Enable VPG before building infoframe
4321 if (vpg && vpg->funcs->vpg_poweron)
4322 vpg->funcs->vpg_poweron(vpg);
4323
4324 resource_build_info_frame(pipe_ctx);
4325 dc->hwss.update_info_frame(pipe_ctx);
4326
4327 if (dc_is_dp_signal(pipe_ctx->stream->signal))
4328 dp_source_sequence_trace(link, DPCD_SOURCE_SEQ_AFTER_UPDATE_INFO_FRAME);
4329
4330 /* Do not touch link on seamless boot optimization. */
4331 if (pipe_ctx->stream->apply_seamless_boot_optimization) {
4332 pipe_ctx->stream->dpms_off = false0;
4333
4334 /* Still enable stream features & audio on seamless boot for DP external displays */
4335 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT) {
4336 enable_stream_features(pipe_ctx);
4337 if (pipe_ctx->stream_res.audio != NULL((void *)0)) {
4338 pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
4339 dc->hwss.enable_audio_stream(pipe_ctx);
4340 }
4341 }
4342
4343#if defined(CONFIG_DRM_AMD_DC_HDCP)
4344 update_psp_stream_config(pipe_ctx, false0);
4345#endif
4346 return;
4347 }
4348
4349 /* eDP lit up by bios already, no need to enable again. */
4350 if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP &&
4351 apply_edp_fast_boot_optimization &&
4352 !pipe_ctx->stream->timing.flags.DSC &&
4353 !pipe_ctx->next_odm_pipe) {
4354 pipe_ctx->stream->dpms_off = false0;
4355#if defined(CONFIG_DRM_AMD_DC_HDCP)
4356 update_psp_stream_config(pipe_ctx, false0);
4357#endif
4358 return;
4359 }
4360
4361 if (pipe_ctx->stream->dpms_off)
4362 return;
4363
4364 /* Have to setup DSC before DIG FE and BE are connected (which happens before the
4365 * link training). This is to make sure the bandwidth sent to DIG BE won't be
4366 * bigger than what the link and/or DIG BE can handle. VBID[6]/CompressedStream_flag
4367 * will be automatically set at a later time when the video is enabled
4368 * (DP_VID_STREAM_EN = 1).
4369 */
4370 if (pipe_ctx->stream->timing.flags.DSC) {
4371 if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
4372 dc_is_virtual_signal(pipe_ctx->stream->signal))
4373 dp_set_dsc_enable(pipe_ctx, true1);
4374
4375 }
4376
4377 status = enable_link(state, pipe_ctx);
4378
4379 if (status != DC_OK) {
4380 DC_LOG_WARNING("enabling link %u failed: %d\n",printk("\0014" "[" "drm" "] " "enabling link %u failed: %d\n"
, pipe_ctx->stream->link->link_index, status)
4381 pipe_ctx->stream->link->link_index,printk("\0014" "[" "drm" "] " "enabling link %u failed: %d\n"
, pipe_ctx->stream->link->link_index, status)
4382 status)printk("\0014" "[" "drm" "] " "enabling link %u failed: %d\n"
, pipe_ctx->stream->link->link_index, status)
;
4383
4384 /* Abort stream enable *unless* the failure was due to
4385 * DP link training - some DP monitors will recover and
4386 * show the stream anyway. But MST displays can't proceed
4387 * without link training.
4388 */
4389 if (status != DC_FAIL_DP_LINK_TRAINING ||
4390 pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
4391 if (false0 == stream->link->link_status.link_active)
4392 disable_link(stream->link, &pipe_ctx->link_res,
4393 pipe_ctx->stream->signal);
4394 BREAK_TO_DEBUGGER()do { ___drm_dbg(((void *)0), DRM_UT_DRIVER, "%s():%d\n", __func__
, 4394); do {} while (0); } while (0)
;
4395 return;
4396 }
4397 }
4398
4399 /* turn off otg test pattern if enable */
4400 if (pipe_ctx->stream_res.tg->funcs->set_test_pattern)
4401 pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg,
4402 CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
4403 COLOR_DEPTH_UNDEFINED);
4404
4405 /* This second call is needed to reconfigure the DIG
4406 * as a workaround for the incorrect value being applied
4407 * from transmitter control.
4408 */
4409 if (!(dc_is_virtual_signal(pipe_ctx->stream->signal) ||
4410 is_dp_128b_132b_signal(pipe_ctx)))
4411 if (link_enc)
4412 link_enc->funcs->setup(
4413 link_enc,
4414 pipe_ctx->stream->signal);
4415
4416 dc->hwss.enable_stream(pipe_ctx);
4417
4418 /* Set DPS PPS SDP (AKA "info frames") */
4419 if (pipe_ctx->stream->timing.flags.DSC) {
4420 if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
4421 dc_is_virtual_signal(pipe_ctx->stream->signal)) {
4422 dp_set_dsc_on_rx(pipe_ctx, true1);
4423 dp_set_dsc_pps_sdp(pipe_ctx, true1, true1);
4424 }
4425 }
4426
4427 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
4428 dc_link_allocate_mst_payload(pipe_ctx);
4429 else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
4430 is_dp_128b_132b_signal(pipe_ctx))
4431 dc_link_update_sst_payload(pipe_ctx, true1);
4432
4433 dc->hwss.unblank_stream(pipe_ctx,
4434 &pipe_ctx->stream->link->cur_link_settings);
4435
4436 if (stream->sink_patches.delay_ignore_msa > 0)
4437 drm_msleep(stream->sink_patches.delay_ignore_msa)mdelay(stream->sink_patches.delay_ignore_msa);
4438
4439 if (dc_is_dp_signal(pipe_ctx->stream->signal))
4440 enable_stream_features(pipe_ctx);
4441#if defined(CONFIG_DRM_AMD_DC_HDCP)
4442 update_psp_stream_config(pipe_ctx, false0);
4443#endif
4444
4445 dc->hwss.enable_audio_stream(pipe_ctx);
4446
4447 } else { // if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment))
4448 if (is_dp_128b_132b_signal(pipe_ctx))
4449 fpga_dp_hpo_enable_link_and_stream(state, pipe_ctx);
4450 if (dc_is_dp_signal(pipe_ctx->stream->signal) ||
4451 dc_is_virtual_signal(pipe_ctx->stream->signal))
4452 dp_set_dsc_enable(pipe_ctx, true1);
4453 }
4454
4455 if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
4456 core_link_set_avmute(pipe_ctx, false0);
4457 }
4458}
4459
4460void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
4461{
4462 struct dc *dc = pipe_ctx->stream->ctx->dc;
4463 struct dc_stream_state *stream = pipe_ctx->stream;
4464 struct dc_link *link = stream->sink->link;
4465 struct vpg *vpg = pipe_ctx->stream_res.stream_enc->vpg;
4466
4467 if (is_dp_128b_132b_signal(pipe_ctx))
1
Assuming the condition is false
2
Taking false branch
4468 vpg = pipe_ctx->stream_res.hpo_dp_stream_enc->vpg;
4469
4470 DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
4471
4472 if (pipe_ctx->stream->sink) {
3
Assuming field 'sink' is null
4473 if (pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_VIRTUAL &&
4474 pipe_ctx->stream->sink->sink_signal != SIGNAL_TYPE_NONE) {
4475 DC_LOG_DC("%s pipe_ctx dispname=%s signal=%x\n", __func__,___drm_dbg(((void *)0), DRM_UT_KMS, "%s pipe_ctx dispname=%s signal=%x\n"
, __func__, pipe_ctx->stream->sink->edid_caps.display_name
, pipe_ctx->stream->signal)
4476 pipe_ctx->stream->sink->edid_caps.display_name,___drm_dbg(((void *)0), DRM_UT_KMS, "%s pipe_ctx dispname=%s signal=%x\n"
, __func__, pipe_ctx->stream->sink->edid_caps.display_name
, pipe_ctx->stream->signal)
4477 pipe_ctx->stream->signal)___drm_dbg(((void *)0), DRM_UT_KMS, "%s pipe_ctx dispname=%s signal=%x\n"
, __func__, pipe_ctx->stream->sink->edid_caps.display_name
, pipe_ctx->stream->signal)
;
4478 }
4479 }
4480
4481 if (!IS_DIAG_DC(dc->ctx->dce_environment)((dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) || (
dc->ctx->dce_environment == DCE_ENV_DIAG))
&&
4
Taking false branch
5
Assuming field 'dce_environment' is equal to DCE_ENV_FPGA_MAXIMUS
4482 dc_is_virtual_signal(pipe_ctx->stream->signal))
4483 return;
4484
4485 if (!pipe_ctx->stream->sink->edid_caps.panel_patch.skip_avmute) {
6
Dereference of null pointer
4486 if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
4487 core_link_set_avmute(pipe_ctx, true1);
4488 }
4489
4490 dc->hwss.disable_audio_stream(pipe_ctx);
4491
4492#if defined(CONFIG_DRM_AMD_DC_HDCP)
4493 update_psp_stream_config(pipe_ctx, true1);
4494#endif
4495 dc->hwss.blank_stream(pipe_ctx);
4496
4497 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
4498 deallocate_mst_payload(pipe_ctx);
4499 else if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
4500 is_dp_128b_132b_signal(pipe_ctx))
4501 dc_link_update_sst_payload(pipe_ctx, false0);
4502
4503 if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) {
4504 struct ext_hdmi_settings settings = {0};
4505 enum engine_id eng_id = pipe_ctx->stream_res.stream_enc->id;
4506
4507 unsigned short masked_chip_caps = link->chip_caps &
4508 EXT_DISPLAY_PATH_CAPS__EXT_CHIP_MASK;
4509 //Need to inform that sink is going to use legacy HDMI mode.
4510 dal_ddc_service_write_scdc_data(
4511 link->ddc,
4512 165000,//vbios only handles 165Mhz.
4513 false0);
4514 if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
4515 /* DP159, Retimer settings */
4516 if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings))
4517 write_i2c_retimer_setting(pipe_ctx,
4518 false0, false0, &settings);
4519 else
4520 write_i2c_default_retimer_setting(pipe_ctx,
4521 false0, false0);
4522 } else if (masked_chip_caps == EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {
4523 /* PI3EQX1204, Redriver settings */
4524 write_i2c_redriver_setting(pipe_ctx, false0);
4525 }
4526 }
4527
4528 if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT &&
4529 !is_dp_128b_132b_signal(pipe_ctx)) {
4530
4531 /* In DP1.x SST mode, our encoder will go to TPS1
4532 * when link is on but stream is off.
4533 * Disabling link before stream will avoid exposing TPS1 pattern
4534 * during the disable sequence as it will confuse some receivers
4535 * state machine.
4536 * In DP2 or MST mode, our encoder will stay video active
4537 */
4538 disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
4539 dc->hwss.disable_stream(pipe_ctx);
4540 } else {
4541 dc->hwss.disable_stream(pipe_ctx);
4542 disable_link(pipe_ctx->stream->link, &pipe_ctx->link_res, pipe_ctx->stream->signal);
4543 }
4544
4545 if (pipe_ctx->stream->timing.flags.DSC) {
4546 if (dc_is_dp_signal(pipe_ctx->stream->signal))
4547 dp_set_dsc_enable(pipe_ctx, false0);
4548 }
4549 if (is_dp_128b_132b_signal(pipe_ctx)) {
4550 if (pipe_ctx->stream_res.tg->funcs->set_out_mux)
4551 pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO);
4552 }
4553
4554 if (vpg && vpg->funcs->vpg_powerdown)
4555 vpg->funcs->vpg_powerdown(vpg);
4556}
4557
4558void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool_Bool enable)
4559{
4560 struct dc *dc = pipe_ctx->stream->ctx->dc;
4561
4562 if (!dc_is_hdmi_signal(pipe_ctx->stream->signal))
4563 return;
4564
4565 dc->hwss.set_avmute(pipe_ctx, enable);
4566}
4567
4568/**
4569 * dc_link_enable_hpd_filter:
4570 * If enable is true, programs HPD filter on associated HPD line using
4571 * delay_on_disconnect/delay_on_connect values dependent on
4572 * link->connector_signal
4573 *
4574 * If enable is false, programs HPD filter on associated HPD line with no
4575 * delays on connect or disconnect
4576 *
4577 * @link: pointer to the dc link
4578 * @enable: boolean specifying whether to enable hbd
4579 */
4580void dc_link_enable_hpd_filter(struct dc_link *link, bool_Bool enable)
4581{
4582 struct gpio *hpd;
4583
4584 if (enable) {
4585 link->is_hpd_filter_disabled = false0;
4586 program_hpd_filter(link);
4587 } else {
4588 link->is_hpd_filter_disabled = true1;
4589 /* Obtain HPD handle */
4590 hpd = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);
4591
4592 if (!hpd)
4593 return;
4594
4595 /* Setup HPD filtering */
4596 if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {
4597 struct gpio_hpd_config config;
4598
4599 config.delay_on_connect = 0;
4600 config.delay_on_disconnect = 0;
4601
4602 dal_irq_setup_hpd_filter(hpd, &config);
4603
4604 dal_gpio_close(hpd);
4605 } else {
4606 ASSERT_CRITICAL(false)do { if (({ int __ret = !!(!(0)); if (__ret) printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c"
, 4606); __builtin_expect(!!(__ret), 0); })) do {} while (0);
} while (0)
;
4607 }
4608 /* Release HPD handle */
4609 dal_gpio_destroy_irq(&hpd);
4610 }
4611}
4612
4613void dc_link_set_drive_settings(struct dc *dc,
4614 struct link_training_settings *lt_settings,
4615 const struct dc_link *link)
4616{
4617
4618 int i;
4619 struct link_resource link_res;
4620
4621 for (i = 0; i < dc->link_count; i++)
4622 if (dc->links[i] == link)
4623 break;
4624
4625 if (i >= dc->link_count)
4626 ASSERT_CRITICAL(false)do { if (({ int __ret = !!(!(0)); if (__ret) printf("WARNING %s failed at %s:%d\n"
, "!(0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c"
, 4626); __builtin_expect(!!(__ret), 0); })) do {} while (0);
} while (0)
;
4627
4628 dc_link_get_cur_link_res(link, &link_res);
4629 dc_link_dp_set_drive_settings(dc->links[i], &link_res, lt_settings);
4630}
4631
4632void dc_link_set_preferred_link_settings(struct dc *dc,
4633 struct dc_link_settings *link_setting,
4634 struct dc_link *link)
4635{
4636 int i;
4637 struct pipe_ctx *pipe;
4638 struct dc_stream_state *link_stream;
4639 struct dc_link_settings store_settings = *link_setting;
4640
4641 link->preferred_link_setting = store_settings;
4642
4643 /* Retrain with preferred link settings only relevant for
4644 * DP signal type
4645 * Check for non-DP signal or if passive dongle present
4646 */
4647 if (!dc_is_dp_signal(link->connector_signal) ||
4648 link->dongle_max_pix_clk > 0)
4649 return;
4650
4651 for (i = 0; i < MAX_PIPES6; i++) {
4652 pipe = &dc->current_state->res_ctx.pipe_ctx[i];
4653 if (pipe->stream && pipe->stream->link) {
4654 if (pipe->stream->link == link) {
4655 link_stream = pipe->stream;
4656 break;
4657 }
4658 }
4659 }
4660
4661 /* Stream not found */
4662 if (i == MAX_PIPES6)
4663 return;
4664
4665 /* Cannot retrain link if backend is off */
4666 if (link_stream->dpms_off)
4667 return;
4668
4669 if (decide_link_settings(link_stream, &store_settings))
4670 dp_retrain_link_dp_test(link, &store_settings, false0);
4671}
4672
4673void dc_link_set_preferred_training_settings(struct dc *dc,
4674 struct dc_link_settings *link_setting,
4675 struct dc_link_training_overrides *lt_overrides,
4676 struct dc_link *link,
4677 bool_Bool skip_immediate_retrain)
4678{
4679 if (lt_overrides != NULL((void *)0))
4680 link->preferred_training_settings = *lt_overrides;
4681 else
4682 memset(&link->preferred_training_settings, 0, sizeof(link->preferred_training_settings))__builtin_memset((&link->preferred_training_settings),
(0), (sizeof(link->preferred_training_settings)))
;
4683
4684 if (link_setting != NULL((void *)0)) {
4685 link->preferred_link_setting = *link_setting;
4686 if (dp_get_link_encoding_format(link_setting) == DP_128b_132b_ENCODING)
4687 /* TODO: add dc update for acquiring link res */
4688 skip_immediate_retrain = true1;
4689 } else {
4690 link->preferred_link_setting.lane_count = LANE_COUNT_UNKNOWN;
4691 link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
4692 }
4693
4694 /* Retrain now, or wait until next stream update to apply */
4695 if (skip_immediate_retrain == false0)
4696 dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
4697}
4698
4699void dc_link_enable_hpd(const struct dc_link *link)
4700{
4701 dc_link_dp_enable_hpd(link);
4702}
4703
4704void dc_link_disable_hpd(const struct dc_link *link)
4705{
4706 dc_link_dp_disable_hpd(link);
4707}
4708
4709void dc_link_set_test_pattern(struct dc_link *link,
4710 enum dp_test_pattern test_pattern,
4711 enum dp_test_pattern_color_space test_pattern_color_space,
4712 const struct link_training_settings *p_link_settings,
4713 const unsigned char *p_custom_pattern,
4714 unsigned int cust_pattern_size)
4715{
4716 if (link != NULL((void *)0))
4717 dc_link_dp_set_test_pattern(
4718 link,
4719 test_pattern,
4720 test_pattern_color_space,
4721 p_link_settings,
4722 p_custom_pattern,
4723 cust_pattern_size);
4724}
4725
4726uint32_t dc_link_bandwidth_kbps(
4727 const struct dc_link *link,
4728 const struct dc_link_settings *link_setting)
4729{
4730 uint32_t total_data_bw_efficiency_x10000 = 0;
4731 uint32_t link_rate_per_lane_kbps = 0;
4732
4733 switch (dp_get_link_encoding_format(link_setting)) {
4734 case DP_8b_10b_ENCODING:
4735 /* For 8b/10b encoding:
4736 * link rate is defined in the unit of LINK_RATE_REF_FREQ_IN_KHZ per DP byte per lane.
4737 * data bandwidth efficiency is 80% with additional 3% overhead if FEC is supported.
4738 */
4739 link_rate_per_lane_kbps = link_setting->link_rate * LINK_RATE_REF_FREQ_IN_KHZ * BITS_PER_DP_BYTE;
4740 total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_8b_10b_x10000;
4741 if (dc_link_should_enable_fec(link)) {
4742 total_data_bw_efficiency_x10000 /= 100;
4743 total_data_bw_efficiency_x10000 *= DATA_EFFICIENCY_8b_10b_FEC_EFFICIENCY_x100;
4744 }
4745 break;
4746 case DP_128b_132b_ENCODING:
4747 /* For 128b/132b encoding:
4748 * link rate is defined in the unit of 10mbps per lane.
4749 * total data bandwidth efficiency is always 96.71%.
4750 */
4751 link_rate_per_lane_kbps = link_setting->link_rate * 10000;
4752 total_data_bw_efficiency_x10000 = DATA_EFFICIENCY_128b_132b_x10000;
4753 break;
4754 default:
4755 break;
4756 }
4757
4758 /* overall effective link bandwidth = link rate per lane * lane count * total data bandwidth efficiency */
4759 return link_rate_per_lane_kbps * link_setting->lane_count / 10000 * total_data_bw_efficiency_x10000;
4760}
4761
4762const struct dc_link_settings *dc_link_get_link_cap(
4763 const struct dc_link *link)
4764{
4765 if (link->preferred_link_setting.lane_count != LANE_COUNT_UNKNOWN &&
4766 link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
4767 return &link->preferred_link_setting;
4768 return &link->verified_link_cap;
4769}
4770
4771void dc_link_overwrite_extended_receiver_cap(
4772 struct dc_link *link)
4773{
4774 dp_overwrite_extended_receiver_cap(link);
4775}
4776
4777bool_Bool dc_link_is_fec_supported(const struct dc_link *link)
4778{
4779 /* TODO - use asic cap instead of link_enc->features
4780 * we no longer know which link enc to use for this link before commit
4781 */
4782 struct link_encoder *link_enc = NULL((void *)0);
4783
4784 link_enc = link_enc_cfg_get_link_enc(link);
4785 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.c"
, 4785); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
4786
4787 return (dc_is_dp_signal(link->connector_signal) && link_enc &&
4788 link_enc->features.fec_supported &&
4789 link->dpcd_caps.fec_cap.bits.FEC_CAPABLE &&
4790 !IS_FPGA_MAXIMUS_DC(link->ctx->dce_environment)(link->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS));
4791}
4792
4793bool_Bool dc_link_should_enable_fec(const struct dc_link *link)
4794{
4795 bool_Bool force_disable = false0;
4796
4797 if (link->fec_state == dc_link_fec_enabled)
4798 force_disable = false0;
4799 else if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT_MST &&
4800 link->local_sink &&
4801 link->local_sink->edid_caps.panel_patch.disable_fec)
4802 force_disable = true1;
4803 else if (link->connector_signal == SIGNAL_TYPE_EDP
4804 && (link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.
4805 dsc_support.DSC_SUPPORT == false0
4806 || link->panel_config.dsc.disable_dsc_edp
4807 || !link->dc->caps.edp_dsc_support))
4808 force_disable = true1;
4809
4810 return !force_disable && dc_link_is_fec_supported(link);
4811}
4812
4813uint32_t dc_bandwidth_in_kbps_from_timing(
4814 const struct dc_crtc_timing *timing)
4815{
4816 uint32_t bits_per_channel = 0;
4817 uint32_t kbps;
4818
4819#if defined(CONFIG_DRM_AMD_DC_DCN1)
4820 if (timing->flags.DSC)
4821 return dc_dsc_stream_bandwidth_in_kbps(timing,
4822 timing->dsc_cfg.bits_per_pixel,
4823 timing->dsc_cfg.num_slices_h,
4824 timing->dsc_cfg.is_dp);
4825#endif /* CONFIG_DRM_AMD_DC_DCN */
4826
4827 switch (timing->display_color_depth) {
4828 case COLOR_DEPTH_666:
4829 bits_per_channel = 6;
4830 break;
4831 case COLOR_DEPTH_888:
4832 bits_per_channel = 8;
4833 break;
4834 case COLOR_DEPTH_101010:
4835 bits_per_channel = 10;
4836 break;
4837 case COLOR_DEPTH_121212:
4838 bits_per_channel = 12;
4839 break;
4840 case COLOR_DEPTH_141414:
4841 bits_per_channel = 14;
4842 break;
4843 case COLOR_DEPTH_161616:
4844 bits_per_channel = 16;
4845 break;
4846 default:
4847 ASSERT(bits_per_channel != 0)do { if (({ static int __warned; int __ret = !!(!(bits_per_channel
!= 0)); if (__ret && !__warned) { printf("WARNING %s failed at %s:%d\n"
, "!(bits_per_channel != 0)", "/usr/src/sys/dev/pci/drm/amd/display/dc/core/dc_link.c"
, 4847); __warned = 1; } __builtin_expect(!!(__ret), 0); })) do
{} while (0); } while (0)
;
4848 bits_per_channel = 8;
4849 break;
4850 }
4851
4852 kbps = timing->pix_clk_100hz / 10;
4853 kbps *= bits_per_channel;
4854
4855 if (timing->flags.Y_ONLY != 1) {
4856 /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/
4857 kbps *= 3;
4858 if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
4859 kbps /= 2;
4860 else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
4861 kbps = kbps * 2 / 3;
4862 }
4863
4864 return kbps;
4865
4866}
4867
4868void dc_link_get_cur_link_res(const struct dc_link *link,
4869 struct link_resource *link_res)
4870{
4871 int i;
4872 struct pipe_ctx *pipe = NULL((void *)0);
4873
4874 memset(link_res, 0, sizeof(*link_res))__builtin_memset((link_res), (0), (sizeof(*link_res)));
4875
4876 for (i = 0; i < MAX_PIPES6; i++) {
4877 pipe = &link->dc->current_state->res_ctx.pipe_ctx[i];
4878 if (pipe->stream && pipe->stream->link && pipe->top_pipe == NULL((void *)0)) {
4879 if (pipe->stream->link == link) {
4880 *link_res = pipe->link_res;
4881 break;
4882 }
4883 }
4884 }
4885
4886}
4887
4888/**
4889 * dc_get_cur_link_res_map() - take a snapshot of current link resource allocation state
4890 * @dc: pointer to dc of the dm calling this
4891 * @map: a dc link resource snapshot defined internally to dc.
4892 *
4893 * DM needs to capture a snapshot of current link resource allocation mapping
4894 * and store it in its persistent storage.
4895 *
4896 * Some of the link resource is using first come first serve policy.
4897 * The allocation mapping depends on original hotplug order. This information
4898 * is lost after driver is loaded next time. The snapshot is used in order to
4899 * restore link resource to its previous state so user will get consistent
4900 * link capability allocation across reboot.
4901 *
4902 * Return: none (void function)
4903 *
4904 */
4905void dc_get_cur_link_res_map(const struct dc *dc, uint32_t *map)
4906{
4907 struct dc_link *link;
4908 uint32_t i;
4909 uint32_t hpo_dp_recycle_map = 0;
4910
4911 *map = 0;
4912
4913 if (dc->caps.dp_hpo) {
4914 for (i = 0; i < dc->caps.max_links; i++) {
4915 link = dc->links[i];
4916 if (link->link_status.link_active &&
4917 dp_get_link_encoding_format(&link->reported_link_cap) == DP_128b_132b_ENCODING &&
4918 dp_get_link_encoding_format(&link->cur_link_settings) != DP_128b_132b_ENCODING)
4919 /* hpo dp link encoder is considered as recycled, when RX reports 128b/132b encoding capability
4920 * but current link doesn't use it.
4921 */
4922 hpo_dp_recycle_map |= (1 << i);
4923 }
4924 *map |= (hpo_dp_recycle_map << LINK_RES_HPO_DP_REC_MAP__SHIFT0);
4925 }
4926}
4927
4928/**
4929 * dc_restore_link_res_map() - restore link resource allocation state from a snapshot
4930 * @dc: pointer to dc of the dm calling this
4931 * @map: a dc link resource snapshot defined internally to dc.
4932 *
4933 * DM needs to call this function after initial link detection on boot and
4934 * before first commit streams to restore link resource allocation state
4935 * from previous boot session.
4936 *
4937 * Some of the link resource is using first come first serve policy.
4938 * The allocation mapping depends on original hotplug order. This information
4939 * is lost after driver is loaded next time. The snapshot is used in order to
4940 * restore link resource to its previous state so user will get consistent
4941 * link capability allocation across reboot.
4942 *
4943 * Return: none (void function)
4944 *
4945 */
4946void dc_restore_link_res_map(const struct dc *dc, uint32_t *map)
4947{
4948 struct dc_link *link;
4949 uint32_t i;
4950 unsigned int available_hpo_dp_count;
4951 uint32_t hpo_dp_recycle_map = (*map & LINK_RES_HPO_DP_REC_MAP__MASK0xFFFF)
4952 >> LINK_RES_HPO_DP_REC_MAP__SHIFT0;
4953
4954 if (dc->caps.dp_hpo) {
4955 available_hpo_dp_count = dc->res_pool->hpo_dp_link_enc_count;
4956 /* remove excess 128b/132b encoding support for not recycled links */
4957 for (i = 0; i < dc->caps.max_links; i++) {
4958 if ((hpo_dp_recycle_map & (1 << i)) == 0) {
4959 link = dc->links[i];
4960 if (link->type != dc_connection_none &&
4961 dp_get_link_encoding_format(&link->verified_link_cap) == DP_128b_132b_ENCODING) {
4962 if (available_hpo_dp_count > 0)
4963 available_hpo_dp_count--;
4964 else
4965 /* remove 128b/132b encoding capability by limiting verified link rate to HBR3 */
4966 link->verified_link_cap.link_rate = LINK_RATE_HIGH3;
4967 }
4968 }
4969 }
4970 /* remove excess 128b/132b encoding support for recycled links */
4971 for (i = 0; i < dc->caps.max_links; i++) {
4972 if ((hpo_dp_recycle_map & (1 << i)) != 0) {
4973 link = dc->links[i];
4974 if (link->type != dc_connection_none &&
4975 dp_get_link_encoding_format(&link->verified_link_cap) == DP_128b_132b_ENCODING) {
4976 if (available_hpo_dp_count > 0)
4977 available_hpo_dp_count--;
4978 else
4979 /* remove 128b/132b encoding capability by limiting verified link rate to HBR3 */
4980 link->verified_link_cap.link_rate = LINK_RATE_HIGH3;
4981 }
4982 }
4983 }
4984 }
4985}