Line data Source code
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 "reg_helper.h"
27 :
28 : #include "core_types.h"
29 : #include "link_encoder.h"
30 : #include "dce_link_encoder.h"
31 : #include "stream_encoder.h"
32 : #include "i2caux_interface.h"
33 : #include "dc_bios_types.h"
34 :
35 : #include "gpio_service_interface.h"
36 :
37 : #include "dce/dce_11_0_d.h"
38 : #include "dce/dce_11_0_sh_mask.h"
39 : #include "dce/dce_11_0_enum.h"
40 :
41 : #ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT
42 : #define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE__SHIFT 0xa
43 : #endif
44 :
45 : #ifndef DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK
46 : #define DMU_MEM_PWR_CNTL__DMCU_IRAM_MEM_PWR_STATE_MASK 0x00000400L
47 : #endif
48 :
49 : #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK
50 : #define HPD0_DC_HPD_CONTROL__DC_HPD_EN_MASK 0x10000000L
51 : #endif
52 :
53 : #ifndef HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT
54 : #define HPD0_DC_HPD_CONTROL__DC_HPD_EN__SHIFT 0x1c
55 : #endif
56 :
57 : #define CTX \
58 : enc110->base.ctx
59 : #define DC_LOGGER \
60 : enc110->base.ctx->logger
61 :
62 : #define REG(reg)\
63 : (enc110->link_regs->reg)
64 :
65 : #define AUX_REG(reg)\
66 : (enc110->aux_regs->reg)
67 :
68 : #define HPD_REG(reg)\
69 : (enc110->hpd_regs->reg)
70 :
71 : #define DEFAULT_AUX_MAX_DATA_SIZE 16
72 : #define AUX_MAX_DEFER_WRITE_RETRY 20
73 : /*
74 : * @brief
75 : * Trigger Source Select
76 : * ASIC-dependent, actual values for register programming
77 : */
78 : #define DCE110_DIG_FE_SOURCE_SELECT_INVALID 0x0
79 : #define DCE110_DIG_FE_SOURCE_SELECT_DIGA 0x1
80 : #define DCE110_DIG_FE_SOURCE_SELECT_DIGB 0x2
81 : #define DCE110_DIG_FE_SOURCE_SELECT_DIGC 0x4
82 : #define DCE110_DIG_FE_SOURCE_SELECT_DIGD 0x08
83 : #define DCE110_DIG_FE_SOURCE_SELECT_DIGE 0x10
84 : #define DCE110_DIG_FE_SOURCE_SELECT_DIGF 0x20
85 : #define DCE110_DIG_FE_SOURCE_SELECT_DIGG 0x40
86 :
87 : enum {
88 : DP_MST_UPDATE_MAX_RETRY = 50
89 : };
90 :
91 : #define DIG_REG(reg)\
92 : (reg + enc110->offsets.dig)
93 :
94 : #define DP_REG(reg)\
95 : (reg + enc110->offsets.dp)
96 :
97 : static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
98 : .validate_output_with_stream =
99 : dce110_link_encoder_validate_output_with_stream,
100 : .hw_init = dce110_link_encoder_hw_init,
101 : .setup = dce110_link_encoder_setup,
102 : .enable_tmds_output = dce110_link_encoder_enable_tmds_output,
103 : .enable_dp_output = dce110_link_encoder_enable_dp_output,
104 : .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,
105 : .enable_lvds_output = dce110_link_encoder_enable_lvds_output,
106 : .disable_output = dce110_link_encoder_disable_output,
107 : .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
108 : .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
109 : .update_mst_stream_allocation_table =
110 : dce110_link_encoder_update_mst_stream_allocation_table,
111 : .psr_program_dp_dphy_fast_training =
112 : dce110_psr_program_dp_dphy_fast_training,
113 : .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
114 : .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
115 : .enable_hpd = dce110_link_encoder_enable_hpd,
116 : .disable_hpd = dce110_link_encoder_disable_hpd,
117 : .is_dig_enabled = dce110_is_dig_enabled,
118 : .destroy = dce110_link_encoder_destroy,
119 : .get_max_link_cap = dce110_link_encoder_get_max_link_cap,
120 : .get_dig_frontend = dce110_get_dig_frontend,
121 : };
122 :
123 : static enum bp_result link_transmitter_control(
124 : struct dce110_link_encoder *enc110,
125 : struct bp_transmitter_control *cntl)
126 : {
127 : enum bp_result result;
128 0 : struct dc_bios *bp = enc110->base.ctx->dc_bios;
129 :
130 0 : result = bp->funcs->transmitter_control(bp, cntl);
131 :
132 : return result;
133 : }
134 :
135 : static void enable_phy_bypass_mode(
136 : struct dce110_link_encoder *enc110,
137 : bool enable)
138 : {
139 : /* This register resides in DP back end block;
140 : * transmitter is used for the offset */
141 :
142 0 : REG_UPDATE(DP_DPHY_CNTL, DPHY_BYPASS, enable);
143 :
144 : }
145 :
146 0 : static void disable_prbs_symbols(
147 : struct dce110_link_encoder *enc110,
148 : bool disable)
149 : {
150 : /* This register resides in DP back end block;
151 : * transmitter is used for the offset */
152 :
153 0 : REG_UPDATE_4(DP_DPHY_CNTL,
154 : DPHY_ATEST_SEL_LANE0, disable,
155 : DPHY_ATEST_SEL_LANE1, disable,
156 : DPHY_ATEST_SEL_LANE2, disable,
157 : DPHY_ATEST_SEL_LANE3, disable);
158 0 : }
159 :
160 : static void disable_prbs_mode(
161 : struct dce110_link_encoder *enc110)
162 : {
163 0 : REG_UPDATE(DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, 0);
164 : }
165 :
166 0 : static void program_pattern_symbols(
167 : struct dce110_link_encoder *enc110,
168 : uint16_t pattern_symbols[8])
169 : {
170 : /* This register resides in DP back end block;
171 : * transmitter is used for the offset */
172 :
173 0 : REG_SET_3(DP_DPHY_SYM0, 0,
174 : DPHY_SYM1, pattern_symbols[0],
175 : DPHY_SYM2, pattern_symbols[1],
176 : DPHY_SYM3, pattern_symbols[2]);
177 :
178 : /* This register resides in DP back end block;
179 : * transmitter is used for the offset */
180 :
181 0 : REG_SET_3(DP_DPHY_SYM1, 0,
182 : DPHY_SYM4, pattern_symbols[3],
183 : DPHY_SYM5, pattern_symbols[4],
184 : DPHY_SYM6, pattern_symbols[5]);
185 :
186 : /* This register resides in DP back end block;
187 : * transmitter is used for the offset */
188 :
189 0 : REG_SET_2(DP_DPHY_SYM2, 0,
190 : DPHY_SYM7, pattern_symbols[6],
191 : DPHY_SYM8, pattern_symbols[7]);
192 0 : }
193 :
194 0 : static void set_dp_phy_pattern_d102(
195 : struct dce110_link_encoder *enc110)
196 : {
197 : /* Disable PHY Bypass mode to setup the test pattern */
198 0 : enable_phy_bypass_mode(enc110, false);
199 :
200 : /* For 10-bit PRBS or debug symbols
201 : * please use the following sequence: */
202 :
203 : /* Enable debug symbols on the lanes */
204 :
205 0 : disable_prbs_symbols(enc110, true);
206 :
207 : /* Disable PRBS mode */
208 0 : disable_prbs_mode(enc110);
209 :
210 : /* Program debug symbols to be output */
211 : {
212 0 : uint16_t pattern_symbols[8] = {
213 : 0x2AA, 0x2AA, 0x2AA, 0x2AA,
214 : 0x2AA, 0x2AA, 0x2AA, 0x2AA
215 : };
216 :
217 0 : program_pattern_symbols(enc110, pattern_symbols);
218 : }
219 :
220 : /* Enable phy bypass mode to enable the test pattern */
221 :
222 0 : enable_phy_bypass_mode(enc110, true);
223 0 : }
224 :
225 : static void set_link_training_complete(
226 : struct dce110_link_encoder *enc110,
227 : bool complete)
228 : {
229 : /* This register resides in DP back end block;
230 : * transmitter is used for the offset */
231 :
232 0 : REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, complete);
233 :
234 : }
235 :
236 0 : unsigned int dce110_get_dig_frontend(struct link_encoder *enc)
237 : {
238 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
239 : u32 value;
240 : enum engine_id result;
241 :
242 0 : REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value);
243 :
244 0 : switch (value) {
245 : case DCE110_DIG_FE_SOURCE_SELECT_DIGA:
246 : result = ENGINE_ID_DIGA;
247 : break;
248 : case DCE110_DIG_FE_SOURCE_SELECT_DIGB:
249 0 : result = ENGINE_ID_DIGB;
250 0 : break;
251 : case DCE110_DIG_FE_SOURCE_SELECT_DIGC:
252 0 : result = ENGINE_ID_DIGC;
253 0 : break;
254 : case DCE110_DIG_FE_SOURCE_SELECT_DIGD:
255 0 : result = ENGINE_ID_DIGD;
256 0 : break;
257 : case DCE110_DIG_FE_SOURCE_SELECT_DIGE:
258 0 : result = ENGINE_ID_DIGE;
259 0 : break;
260 : case DCE110_DIG_FE_SOURCE_SELECT_DIGF:
261 0 : result = ENGINE_ID_DIGF;
262 0 : break;
263 : case DCE110_DIG_FE_SOURCE_SELECT_DIGG:
264 0 : result = ENGINE_ID_DIGG;
265 0 : break;
266 : default:
267 : // invalid source select DIG
268 0 : result = ENGINE_ID_UNKNOWN;
269 : }
270 :
271 0 : return result;
272 : }
273 :
274 0 : void dce110_link_encoder_set_dp_phy_pattern_training_pattern(
275 : struct link_encoder *enc,
276 : uint32_t index)
277 : {
278 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
279 : /* Write Training Pattern */
280 :
281 0 : REG_WRITE(DP_DPHY_TRAINING_PATTERN_SEL, index);
282 :
283 : /* Set HW Register Training Complete to false */
284 :
285 0 : set_link_training_complete(enc110, false);
286 :
287 : /* Disable PHY Bypass mode to output Training Pattern */
288 :
289 0 : enable_phy_bypass_mode(enc110, false);
290 :
291 : /* Disable PRBS mode */
292 0 : disable_prbs_mode(enc110);
293 0 : }
294 :
295 0 : static void setup_panel_mode(
296 : struct dce110_link_encoder *enc110,
297 : enum dp_panel_mode panel_mode)
298 : {
299 : uint32_t value;
300 0 : struct dc_context *ctx = enc110->base.ctx;
301 :
302 : /* if psp set panel mode, dal should be program it */
303 0 : if (ctx->dc->caps.psp_setup_panel_mode)
304 : return;
305 :
306 0 : ASSERT(REG(DP_DPHY_INTERNAL_CTRL));
307 0 : value = REG_READ(DP_DPHY_INTERNAL_CTRL);
308 :
309 0 : switch (panel_mode) {
310 : case DP_PANEL_MODE_EDP:
311 : value = 0x1;
312 : break;
313 : case DP_PANEL_MODE_SPECIAL:
314 0 : value = 0x11;
315 : break;
316 : default:
317 0 : value = 0x0;
318 : break;
319 : }
320 :
321 0 : REG_WRITE(DP_DPHY_INTERNAL_CTRL, value);
322 : }
323 :
324 0 : static void set_dp_phy_pattern_symbol_error(
325 : struct dce110_link_encoder *enc110)
326 : {
327 : /* Disable PHY Bypass mode to setup the test pattern */
328 0 : enable_phy_bypass_mode(enc110, false);
329 :
330 : /* program correct panel mode*/
331 0 : setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
332 :
333 : /* A PRBS23 pattern is used for most DP electrical measurements. */
334 :
335 : /* Enable PRBS symbols on the lanes */
336 0 : disable_prbs_symbols(enc110, false);
337 :
338 : /* For PRBS23 Set bit DPHY_PRBS_SEL=1 and Set bit DPHY_PRBS_EN=1 */
339 0 : REG_UPDATE_2(DP_DPHY_PRBS_CNTL,
340 : DPHY_PRBS_SEL, 1,
341 : DPHY_PRBS_EN, 1);
342 :
343 : /* Enable phy bypass mode to enable the test pattern */
344 0 : enable_phy_bypass_mode(enc110, true);
345 0 : }
346 :
347 0 : static void set_dp_phy_pattern_prbs7(
348 : struct dce110_link_encoder *enc110)
349 : {
350 : /* Disable PHY Bypass mode to setup the test pattern */
351 0 : enable_phy_bypass_mode(enc110, false);
352 :
353 : /* A PRBS7 pattern is used for most DP electrical measurements. */
354 :
355 : /* Enable PRBS symbols on the lanes */
356 0 : disable_prbs_symbols(enc110, false);
357 :
358 : /* For PRBS7 Set bit DPHY_PRBS_SEL=0 and Set bit DPHY_PRBS_EN=1 */
359 0 : REG_UPDATE_2(DP_DPHY_PRBS_CNTL,
360 : DPHY_PRBS_SEL, 0,
361 : DPHY_PRBS_EN, 1);
362 :
363 : /* Enable phy bypass mode to enable the test pattern */
364 0 : enable_phy_bypass_mode(enc110, true);
365 0 : }
366 :
367 0 : static void set_dp_phy_pattern_80bit_custom(
368 : struct dce110_link_encoder *enc110,
369 : const uint8_t *pattern)
370 : {
371 : /* Disable PHY Bypass mode to setup the test pattern */
372 0 : enable_phy_bypass_mode(enc110, false);
373 :
374 : /* Enable debug symbols on the lanes */
375 :
376 0 : disable_prbs_symbols(enc110, true);
377 :
378 : /* Enable PHY bypass mode to enable the test pattern */
379 : /* TODO is it really needed ? */
380 :
381 0 : enable_phy_bypass_mode(enc110, true);
382 :
383 : /* Program 80 bit custom pattern */
384 : {
385 : uint16_t pattern_symbols[8];
386 :
387 0 : pattern_symbols[0] =
388 0 : ((pattern[1] & 0x03) << 8) | pattern[0];
389 0 : pattern_symbols[1] =
390 0 : ((pattern[2] & 0x0f) << 6) | ((pattern[1] >> 2) & 0x3f);
391 0 : pattern_symbols[2] =
392 0 : ((pattern[3] & 0x3f) << 4) | ((pattern[2] >> 4) & 0x0f);
393 0 : pattern_symbols[3] =
394 0 : (pattern[4] << 2) | ((pattern[3] >> 6) & 0x03);
395 0 : pattern_symbols[4] =
396 0 : ((pattern[6] & 0x03) << 8) | pattern[5];
397 0 : pattern_symbols[5] =
398 0 : ((pattern[7] & 0x0f) << 6) | ((pattern[6] >> 2) & 0x3f);
399 0 : pattern_symbols[6] =
400 0 : ((pattern[8] & 0x3f) << 4) | ((pattern[7] >> 4) & 0x0f);
401 0 : pattern_symbols[7] =
402 0 : (pattern[9] << 2) | ((pattern[8] >> 6) & 0x03);
403 :
404 0 : program_pattern_symbols(enc110, pattern_symbols);
405 : }
406 :
407 : /* Enable phy bypass mode to enable the test pattern */
408 :
409 0 : enable_phy_bypass_mode(enc110, true);
410 0 : }
411 :
412 0 : static void set_dp_phy_pattern_hbr2_compliance_cp2520_2(
413 : struct dce110_link_encoder *enc110,
414 : unsigned int cp2520_pattern)
415 : {
416 :
417 : /* previously there is a register DP_HBR2_EYE_PATTERN
418 : * that is enabled to get the pattern.
419 : * But it does not work with the latest spec change,
420 : * so we are programming the following registers manually.
421 : *
422 : * The following settings have been confirmed
423 : * by Nick Chorney and Sandra Liu */
424 :
425 : /* Disable PHY Bypass mode to setup the test pattern */
426 :
427 0 : enable_phy_bypass_mode(enc110, false);
428 :
429 : /* Setup DIG encoder in DP SST mode */
430 0 : enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);
431 :
432 : /* ensure normal panel mode. */
433 0 : setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
434 :
435 : /* no vbid after BS (SR)
436 : * DP_LINK_FRAMING_CNTL changed history Sandra Liu
437 : * 11000260 / 11000104 / 110000FC */
438 0 : REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
439 : DP_IDLE_BS_INTERVAL, 0xFC,
440 : DP_VBID_DISABLE, 1,
441 : DP_VID_ENHANCED_FRAME_MODE, 1);
442 :
443 : /* swap every BS with SR */
444 0 : REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0);
445 :
446 : /* select cp2520 patterns */
447 0 : if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))
448 0 : REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,
449 : DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);
450 : else
451 : /* pre-DCE11 can only generate CP2520 pattern 2 */
452 0 : ASSERT(cp2520_pattern == 2);
453 :
454 : /* set link training complete */
455 0 : set_link_training_complete(enc110, true);
456 :
457 : /* disable video stream */
458 0 : REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
459 :
460 : /* Disable PHY Bypass mode to setup the test pattern */
461 0 : enable_phy_bypass_mode(enc110, false);
462 0 : }
463 :
464 : #if defined(CONFIG_DRM_AMD_DC_SI)
465 : static void dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(
466 : struct dce110_link_encoder *enc110,
467 : unsigned int cp2520_pattern)
468 : {
469 :
470 : /* previously there is a register DP_HBR2_EYE_PATTERN
471 : * that is enabled to get the pattern.
472 : * But it does not work with the latest spec change,
473 : * so we are programming the following registers manually.
474 : *
475 : * The following settings have been confirmed
476 : * by Nick Chorney and Sandra Liu */
477 :
478 : /* Disable PHY Bypass mode to setup the test pattern */
479 :
480 : enable_phy_bypass_mode(enc110, false);
481 :
482 : /* Setup DIG encoder in DP SST mode */
483 : enc110->base.funcs->setup(&enc110->base, SIGNAL_TYPE_DISPLAY_PORT);
484 :
485 : /* ensure normal panel mode. */
486 : setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
487 :
488 : /* no vbid after BS (SR)
489 : * DP_LINK_FRAMING_CNTL changed history Sandra Liu
490 : * 11000260 / 11000104 / 110000FC */
491 : REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
492 : DP_IDLE_BS_INTERVAL, 0xFC,
493 : DP_VBID_DISABLE, 1,
494 : DP_VID_ENHANCED_FRAME_MODE, 1);
495 :
496 : /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip swap BS with SR */
497 :
498 : /* select cp2520 patterns */
499 : if (REG(DP_DPHY_HBR2_PATTERN_CONTROL))
500 : REG_UPDATE(DP_DPHY_HBR2_PATTERN_CONTROL,
501 : DP_DPHY_HBR2_PATTERN_CONTROL, cp2520_pattern);
502 : else
503 : /* pre-DCE11 can only generate CP2520 pattern 2 */
504 : ASSERT(cp2520_pattern == 2);
505 :
506 : /* set link training complete */
507 : set_link_training_complete(enc110, true);
508 :
509 : /* disable video stream */
510 : REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
511 :
512 : /* Disable PHY Bypass mode to setup the test pattern */
513 : enable_phy_bypass_mode(enc110, false);
514 : }
515 : #endif
516 :
517 0 : static void set_dp_phy_pattern_passthrough_mode(
518 : struct dce110_link_encoder *enc110,
519 : enum dp_panel_mode panel_mode)
520 : {
521 : /* program correct panel mode */
522 0 : setup_panel_mode(enc110, panel_mode);
523 :
524 : /* restore LINK_FRAMING_CNTL and DPHY_SCRAMBLER_BS_COUNT
525 : * in case we were doing HBR2 compliance pattern before
526 : */
527 0 : REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
528 : DP_IDLE_BS_INTERVAL, 0x2000,
529 : DP_VBID_DISABLE, 0,
530 : DP_VID_ENHANCED_FRAME_MODE, 1);
531 :
532 0 : REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, 0x1FF);
533 :
534 : /* set link training complete */
535 0 : set_link_training_complete(enc110, true);
536 :
537 : /* Disable PHY Bypass mode to setup the test pattern */
538 0 : enable_phy_bypass_mode(enc110, false);
539 :
540 : /* Disable PRBS mode */
541 0 : disable_prbs_mode(enc110);
542 0 : }
543 :
544 : #if defined(CONFIG_DRM_AMD_DC_SI)
545 : static void dce60_set_dp_phy_pattern_passthrough_mode(
546 : struct dce110_link_encoder *enc110,
547 : enum dp_panel_mode panel_mode)
548 : {
549 : /* program correct panel mode */
550 : setup_panel_mode(enc110, panel_mode);
551 :
552 : /* restore LINK_FRAMING_CNTL
553 : * in case we were doing HBR2 compliance pattern before
554 : */
555 : REG_UPDATE_3(DP_LINK_FRAMING_CNTL,
556 : DP_IDLE_BS_INTERVAL, 0x2000,
557 : DP_VBID_DISABLE, 0,
558 : DP_VID_ENHANCED_FRAME_MODE, 1);
559 :
560 : /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip DPHY_SCRAMBLER_BS_COUNT restore */
561 :
562 : /* set link training complete */
563 : set_link_training_complete(enc110, true);
564 :
565 : /* Disable PHY Bypass mode to setup the test pattern */
566 : enable_phy_bypass_mode(enc110, false);
567 :
568 : /* Disable PRBS mode */
569 : disable_prbs_mode(enc110);
570 : }
571 : #endif
572 :
573 : /* return value is bit-vector */
574 0 : static uint8_t get_frontend_source(
575 : enum engine_id engine)
576 : {
577 0 : switch (engine) {
578 : case ENGINE_ID_DIGA:
579 : return DCE110_DIG_FE_SOURCE_SELECT_DIGA;
580 : case ENGINE_ID_DIGB:
581 0 : return DCE110_DIG_FE_SOURCE_SELECT_DIGB;
582 : case ENGINE_ID_DIGC:
583 0 : return DCE110_DIG_FE_SOURCE_SELECT_DIGC;
584 : case ENGINE_ID_DIGD:
585 0 : return DCE110_DIG_FE_SOURCE_SELECT_DIGD;
586 : case ENGINE_ID_DIGE:
587 0 : return DCE110_DIG_FE_SOURCE_SELECT_DIGE;
588 : case ENGINE_ID_DIGF:
589 0 : return DCE110_DIG_FE_SOURCE_SELECT_DIGF;
590 : case ENGINE_ID_DIGG:
591 0 : return DCE110_DIG_FE_SOURCE_SELECT_DIGG;
592 : default:
593 0 : ASSERT_CRITICAL(false);
594 0 : return DCE110_DIG_FE_SOURCE_SELECT_INVALID;
595 : }
596 : }
597 :
598 0 : static void configure_encoder(
599 : struct dce110_link_encoder *enc110,
600 : const struct dc_link_settings *link_settings)
601 : {
602 : /* set number of lanes */
603 :
604 0 : REG_SET(DP_CONFIG, 0,
605 : DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);
606 :
607 : /* setup scrambler */
608 0 : REG_UPDATE(DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, 1);
609 0 : }
610 :
611 : #if defined(CONFIG_DRM_AMD_DC_SI)
612 : static void dce60_configure_encoder(
613 : struct dce110_link_encoder *enc110,
614 : const struct dc_link_settings *link_settings)
615 : {
616 : /* set number of lanes */
617 :
618 : REG_SET(DP_CONFIG, 0,
619 : DP_UDI_LANES, link_settings->lane_count - LANE_COUNT_ONE);
620 :
621 : /* DCE6 has no DP_DPHY_SCRAM_CNTL register, skip setup scrambler */
622 : }
623 : #endif
624 :
625 0 : static void aux_initialize(
626 : struct dce110_link_encoder *enc110)
627 : {
628 0 : struct dc_context *ctx = enc110->base.ctx;
629 0 : enum hpd_source_id hpd_source = enc110->base.hpd_source;
630 0 : uint32_t addr = AUX_REG(AUX_CONTROL);
631 0 : uint32_t value = dm_read_reg(ctx, addr);
632 :
633 0 : set_reg_field_value(value, hpd_source, AUX_CONTROL, AUX_HPD_SEL);
634 0 : set_reg_field_value(value, 0, AUX_CONTROL, AUX_LS_READ_EN);
635 0 : dm_write_reg(ctx, addr, value);
636 :
637 0 : addr = AUX_REG(AUX_DPHY_RX_CONTROL0);
638 0 : value = dm_read_reg(ctx, addr);
639 :
640 : /* 1/4 window (the maximum allowed) */
641 0 : set_reg_field_value(value, 1,
642 : AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW);
643 0 : dm_write_reg(ctx, addr, value);
644 :
645 0 : }
646 :
647 0 : void dce110_psr_program_dp_dphy_fast_training(struct link_encoder *enc,
648 : bool exit_link_training_required)
649 : {
650 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
651 :
652 0 : if (exit_link_training_required)
653 0 : REG_UPDATE(DP_DPHY_FAST_TRAINING,
654 : DPHY_RX_FAST_TRAINING_CAPABLE, 1);
655 : else {
656 0 : REG_UPDATE(DP_DPHY_FAST_TRAINING,
657 : DPHY_RX_FAST_TRAINING_CAPABLE, 0);
658 : /*In DCE 11, we are able to pre-program a Force SR register
659 : * to be able to trigger SR symbol after 5 idle patterns
660 : * transmitted. Upon PSR Exit, DMCU can trigger
661 : * DPHY_LOAD_BS_COUNT_START = 1. Upon writing 1 to
662 : * DPHY_LOAD_BS_COUNT_START and the internal counter
663 : * reaches DPHY_LOAD_BS_COUNT, the next BS symbol will be
664 : * replaced by SR symbol once.
665 : */
666 :
667 0 : REG_UPDATE(DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, 0x5);
668 : }
669 0 : }
670 :
671 0 : void dce110_psr_program_secondary_packet(struct link_encoder *enc,
672 : unsigned int sdp_transmit_line_num_deadline)
673 : {
674 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
675 :
676 0 : REG_UPDATE_2(DP_SEC_CNTL1,
677 : DP_SEC_GSP0_LINE_NUM, sdp_transmit_line_num_deadline,
678 : DP_SEC_GSP0_PRIORITY, 1);
679 0 : }
680 :
681 0 : bool dce110_is_dig_enabled(struct link_encoder *enc)
682 : {
683 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
684 : uint32_t value;
685 :
686 0 : REG_GET(DIG_BE_EN_CNTL, DIG_ENABLE, &value);
687 0 : return value;
688 : }
689 :
690 0 : static void link_encoder_disable(struct dce110_link_encoder *enc110)
691 : {
692 : /* reset training pattern */
693 0 : REG_SET(DP_DPHY_TRAINING_PATTERN_SEL, 0,
694 : DPHY_TRAINING_PATTERN_SEL, 0);
695 :
696 : /* reset training complete */
697 0 : REG_UPDATE(DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, 0);
698 :
699 : /* reset panel mode */
700 0 : setup_panel_mode(enc110, DP_PANEL_MODE_DEFAULT);
701 0 : }
702 :
703 0 : static void hpd_initialize(
704 : struct dce110_link_encoder *enc110)
705 : {
706 : /* Associate HPD with DIG_BE */
707 0 : enum hpd_source_id hpd_source = enc110->base.hpd_source;
708 :
709 0 : REG_UPDATE(DIG_BE_CNTL, DIG_HPD_SELECT, hpd_source);
710 0 : }
711 :
712 0 : bool dce110_link_encoder_validate_dvi_output(
713 : const struct dce110_link_encoder *enc110,
714 : enum signal_type connector_signal,
715 : enum signal_type signal,
716 : const struct dc_crtc_timing *crtc_timing)
717 : {
718 0 : uint32_t max_pixel_clock = TMDS_MAX_PIXEL_CLOCK;
719 :
720 0 : if (signal == SIGNAL_TYPE_DVI_DUAL_LINK)
721 0 : max_pixel_clock *= 2;
722 :
723 : /* This handles the case of HDMI downgrade to DVI we don't want to
724 : * we don't want to cap the pixel clock if the DDI is not DVI.
725 : */
726 0 : if (connector_signal != SIGNAL_TYPE_DVI_DUAL_LINK &&
727 : connector_signal != SIGNAL_TYPE_DVI_SINGLE_LINK)
728 0 : max_pixel_clock = enc110->base.features.max_hdmi_pixel_clock;
729 :
730 : /* DVI only support RGB pixel encoding */
731 0 : if (crtc_timing->pixel_encoding != PIXEL_ENCODING_RGB)
732 : return false;
733 :
734 : /*connect DVI via adpater's HDMI connector*/
735 0 : if ((connector_signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
736 0 : connector_signal == SIGNAL_TYPE_HDMI_TYPE_A) &&
737 0 : signal != SIGNAL_TYPE_HDMI_TYPE_A &&
738 0 : crtc_timing->pix_clk_100hz > (TMDS_MAX_PIXEL_CLOCK * 10))
739 : return false;
740 0 : if (crtc_timing->pix_clk_100hz < (TMDS_MIN_PIXEL_CLOCK * 10))
741 : return false;
742 :
743 0 : if (crtc_timing->pix_clk_100hz > (max_pixel_clock * 10))
744 : return false;
745 :
746 : /* DVI supports 6/8bpp single-link and 10/16bpp dual-link */
747 0 : switch (crtc_timing->display_color_depth) {
748 : case COLOR_DEPTH_666:
749 : case COLOR_DEPTH_888:
750 : break;
751 : case COLOR_DEPTH_101010:
752 : case COLOR_DEPTH_161616:
753 0 : if (signal != SIGNAL_TYPE_DVI_DUAL_LINK)
754 : return false;
755 : break;
756 : default:
757 : return false;
758 : }
759 :
760 0 : return true;
761 : }
762 :
763 0 : static bool dce110_link_encoder_validate_hdmi_output(
764 : const struct dce110_link_encoder *enc110,
765 : const struct dc_crtc_timing *crtc_timing,
766 : int adjusted_pix_clk_khz)
767 : {
768 0 : enum dc_color_depth max_deep_color =
769 : enc110->base.features.max_hdmi_deep_color;
770 :
771 0 : if (max_deep_color < crtc_timing->display_color_depth)
772 : return false;
773 :
774 0 : if (crtc_timing->display_color_depth < COLOR_DEPTH_888)
775 : return false;
776 0 : if (adjusted_pix_clk_khz < TMDS_MIN_PIXEL_CLOCK)
777 : return false;
778 :
779 0 : if ((adjusted_pix_clk_khz == 0) ||
780 0 : (adjusted_pix_clk_khz > enc110->base.features.max_hdmi_pixel_clock))
781 : return false;
782 :
783 : /* DCE11 HW does not support 420 */
784 0 : if (!enc110->base.features.hdmi_ycbcr420_supported &&
785 0 : crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
786 : return false;
787 :
788 0 : if ((!enc110->base.features.flags.bits.HDMI_6GB_EN ||
789 0 : enc110->base.ctx->dc->debug.hdmi20_disable) &&
790 : adjusted_pix_clk_khz >= 300000)
791 : return false;
792 0 : if (enc110->base.ctx->dc->debug.hdmi20_disable &&
793 0 : crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
794 : return false;
795 : return true;
796 : }
797 :
798 0 : bool dce110_link_encoder_validate_dp_output(
799 : const struct dce110_link_encoder *enc110,
800 : const struct dc_crtc_timing *crtc_timing)
801 : {
802 0 : if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
803 : return false;
804 :
805 0 : return true;
806 : }
807 :
808 0 : void dce110_link_encoder_construct(
809 : struct dce110_link_encoder *enc110,
810 : const struct encoder_init_data *init_data,
811 : const struct encoder_feature_support *enc_features,
812 : const struct dce110_link_enc_registers *link_regs,
813 : const struct dce110_link_enc_aux_registers *aux_regs,
814 : const struct dce110_link_enc_hpd_registers *hpd_regs)
815 : {
816 0 : struct bp_encoder_cap_info bp_cap_info = {0};
817 0 : const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
818 0 : enum bp_result result = BP_RESULT_OK;
819 :
820 0 : enc110->base.funcs = &dce110_lnk_enc_funcs;
821 0 : enc110->base.ctx = init_data->ctx;
822 0 : enc110->base.id = init_data->encoder;
823 :
824 0 : enc110->base.hpd_source = init_data->hpd_source;
825 0 : enc110->base.connector = init_data->connector;
826 :
827 0 : enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
828 :
829 0 : enc110->base.features = *enc_features;
830 :
831 0 : enc110->base.transmitter = init_data->transmitter;
832 :
833 : /* set the flag to indicate whether driver poll the I2C data pin
834 : * while doing the DP sink detect
835 : */
836 :
837 : /* if (dal_adapter_service_is_feature_supported(as,
838 : FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
839 : enc110->base.features.flags.bits.
840 : DP_SINK_DETECT_POLL_DATA_PIN = true;*/
841 :
842 0 : enc110->base.output_signals =
843 : SIGNAL_TYPE_DVI_SINGLE_LINK |
844 : SIGNAL_TYPE_DVI_DUAL_LINK |
845 : SIGNAL_TYPE_LVDS |
846 : SIGNAL_TYPE_DISPLAY_PORT |
847 : SIGNAL_TYPE_DISPLAY_PORT_MST |
848 : SIGNAL_TYPE_EDP |
849 : SIGNAL_TYPE_HDMI_TYPE_A;
850 :
851 : /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.
852 : * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.
853 : * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer
854 : * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.
855 : * Prefer DIG assignment is decided by board design.
856 : * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design
857 : * and VBIOS will filter out 7 UNIPHY for DCE 8.0.
858 : * By this, adding DIGG should not hurt DCE 8.0.
859 : * This will let DCE 8.1 share DCE 8.0 as much as possible
860 : */
861 :
862 0 : enc110->link_regs = link_regs;
863 0 : enc110->aux_regs = aux_regs;
864 0 : enc110->hpd_regs = hpd_regs;
865 :
866 0 : switch (enc110->base.transmitter) {
867 : case TRANSMITTER_UNIPHY_A:
868 0 : enc110->base.preferred_engine = ENGINE_ID_DIGA;
869 0 : break;
870 : case TRANSMITTER_UNIPHY_B:
871 0 : enc110->base.preferred_engine = ENGINE_ID_DIGB;
872 0 : break;
873 : case TRANSMITTER_UNIPHY_C:
874 0 : enc110->base.preferred_engine = ENGINE_ID_DIGC;
875 0 : break;
876 : case TRANSMITTER_UNIPHY_D:
877 0 : enc110->base.preferred_engine = ENGINE_ID_DIGD;
878 0 : break;
879 : case TRANSMITTER_UNIPHY_E:
880 0 : enc110->base.preferred_engine = ENGINE_ID_DIGE;
881 0 : break;
882 : case TRANSMITTER_UNIPHY_F:
883 0 : enc110->base.preferred_engine = ENGINE_ID_DIGF;
884 0 : break;
885 : case TRANSMITTER_UNIPHY_G:
886 0 : enc110->base.preferred_engine = ENGINE_ID_DIGG;
887 0 : break;
888 : default:
889 0 : ASSERT_CRITICAL(false);
890 0 : enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
891 : }
892 :
893 : /* default to one to mirror Windows behavior */
894 0 : enc110->base.features.flags.bits.HDMI_6GB_EN = 1;
895 :
896 0 : result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,
897 : enc110->base.id, &bp_cap_info);
898 :
899 : /* Override features with DCE-specific values */
900 0 : if (BP_RESULT_OK == result) {
901 0 : enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
902 0 : bp_cap_info.DP_HBR2_EN;
903 0 : enc110->base.features.flags.bits.IS_HBR3_CAPABLE =
904 0 : bp_cap_info.DP_HBR3_EN;
905 0 : enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
906 : } else {
907 0 : DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
908 : __func__,
909 : result);
910 : }
911 0 : if (enc110->base.ctx->dc->debug.hdmi20_disable) {
912 0 : enc110->base.features.flags.bits.HDMI_6GB_EN = 0;
913 : }
914 0 : }
915 :
916 0 : bool dce110_link_encoder_validate_output_with_stream(
917 : struct link_encoder *enc,
918 : const struct dc_stream_state *stream)
919 : {
920 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
921 : bool is_valid;
922 :
923 0 : switch (stream->signal) {
924 : case SIGNAL_TYPE_DVI_SINGLE_LINK:
925 : case SIGNAL_TYPE_DVI_DUAL_LINK:
926 0 : is_valid = dce110_link_encoder_validate_dvi_output(
927 : enc110,
928 0 : stream->link->connector_signal,
929 : stream->signal,
930 : &stream->timing);
931 0 : break;
932 : case SIGNAL_TYPE_HDMI_TYPE_A:
933 0 : is_valid = dce110_link_encoder_validate_hdmi_output(
934 : enc110,
935 : &stream->timing,
936 : stream->phy_pix_clk);
937 0 : break;
938 : case SIGNAL_TYPE_DISPLAY_PORT:
939 : case SIGNAL_TYPE_DISPLAY_PORT_MST:
940 0 : is_valid = dce110_link_encoder_validate_dp_output(
941 : enc110, &stream->timing);
942 : break;
943 : case SIGNAL_TYPE_EDP:
944 : case SIGNAL_TYPE_LVDS:
945 0 : is_valid =
946 0 : (stream->timing.
947 : pixel_encoding == PIXEL_ENCODING_RGB) ? true : false;
948 0 : break;
949 : case SIGNAL_TYPE_VIRTUAL:
950 : is_valid = true;
951 : break;
952 : default:
953 0 : is_valid = false;
954 0 : break;
955 : }
956 :
957 0 : return is_valid;
958 : }
959 :
960 0 : void dce110_link_encoder_hw_init(
961 : struct link_encoder *enc)
962 : {
963 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
964 0 : struct bp_transmitter_control cntl = { 0 };
965 : enum bp_result result;
966 :
967 0 : cntl.action = TRANSMITTER_CONTROL_INIT;
968 0 : cntl.engine_id = ENGINE_ID_UNKNOWN;
969 0 : cntl.transmitter = enc110->base.transmitter;
970 0 : cntl.connector_obj_id = enc110->base.connector;
971 0 : cntl.lanes_number = LANE_COUNT_FOUR;
972 : cntl.coherent = false;
973 0 : cntl.hpd_sel = enc110->base.hpd_source;
974 :
975 0 : if (enc110->base.connector.id == CONNECTOR_ID_EDP)
976 0 : cntl.signal = SIGNAL_TYPE_EDP;
977 :
978 0 : result = link_transmitter_control(enc110, &cntl);
979 :
980 0 : if (result != BP_RESULT_OK) {
981 0 : DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
982 : __func__);
983 0 : BREAK_TO_DEBUGGER();
984 0 : return;
985 : }
986 :
987 0 : if (enc110->base.connector.id == CONNECTOR_ID_LVDS) {
988 0 : cntl.action = TRANSMITTER_CONTROL_BACKLIGHT_BRIGHTNESS;
989 :
990 0 : result = link_transmitter_control(enc110, &cntl);
991 :
992 0 : ASSERT(result == BP_RESULT_OK);
993 :
994 : }
995 0 : aux_initialize(enc110);
996 :
997 : /* reinitialize HPD.
998 : * hpd_initialize() will pass DIG_FE id to HW context.
999 : * All other routine within HW context will use fe_engine_offset
1000 : * as DIG_FE id even caller pass DIG_FE id.
1001 : * So this routine must be called first. */
1002 0 : hpd_initialize(enc110);
1003 : }
1004 :
1005 0 : void dce110_link_encoder_destroy(struct link_encoder **enc)
1006 : {
1007 0 : kfree(TO_DCE110_LINK_ENC(*enc));
1008 0 : *enc = NULL;
1009 0 : }
1010 :
1011 0 : void dce110_link_encoder_setup(
1012 : struct link_encoder *enc,
1013 : enum signal_type signal)
1014 : {
1015 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1016 :
1017 0 : switch (signal) {
1018 : case SIGNAL_TYPE_EDP:
1019 : case SIGNAL_TYPE_DISPLAY_PORT:
1020 : /* DP SST */
1021 0 : REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 0);
1022 0 : break;
1023 : case SIGNAL_TYPE_LVDS:
1024 : /* LVDS */
1025 0 : REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 1);
1026 0 : break;
1027 : case SIGNAL_TYPE_DVI_SINGLE_LINK:
1028 : case SIGNAL_TYPE_DVI_DUAL_LINK:
1029 : /* TMDS-DVI */
1030 0 : REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 2);
1031 0 : break;
1032 : case SIGNAL_TYPE_HDMI_TYPE_A:
1033 : /* TMDS-HDMI */
1034 0 : REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 3);
1035 0 : break;
1036 : case SIGNAL_TYPE_DISPLAY_PORT_MST:
1037 : /* DP MST */
1038 0 : REG_UPDATE(DIG_BE_CNTL, DIG_MODE, 5);
1039 0 : break;
1040 : default:
1041 0 : ASSERT_CRITICAL(false);
1042 : /* invalid mode ! */
1043 0 : break;
1044 : }
1045 :
1046 0 : }
1047 :
1048 : /* TODO: still need depth or just pass in adjusted pixel clock? */
1049 0 : void dce110_link_encoder_enable_tmds_output(
1050 : struct link_encoder *enc,
1051 : enum clock_source_id clock_source,
1052 : enum dc_color_depth color_depth,
1053 : enum signal_type signal,
1054 : uint32_t pixel_clock)
1055 : {
1056 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1057 0 : struct bp_transmitter_control cntl = { 0 };
1058 : enum bp_result result;
1059 :
1060 : /* Enable the PHY */
1061 0 : cntl.connector_obj_id = enc110->base.connector;
1062 0 : cntl.action = TRANSMITTER_CONTROL_ENABLE;
1063 0 : cntl.engine_id = enc->preferred_engine;
1064 0 : cntl.transmitter = enc110->base.transmitter;
1065 0 : cntl.pll_id = clock_source;
1066 0 : cntl.signal = signal;
1067 0 : if (cntl.signal == SIGNAL_TYPE_DVI_DUAL_LINK)
1068 0 : cntl.lanes_number = 8;
1069 : else
1070 0 : cntl.lanes_number = 4;
1071 :
1072 0 : cntl.hpd_sel = enc110->base.hpd_source;
1073 :
1074 0 : cntl.pixel_clock = pixel_clock;
1075 0 : cntl.color_depth = color_depth;
1076 :
1077 0 : result = link_transmitter_control(enc110, &cntl);
1078 :
1079 0 : if (result != BP_RESULT_OK) {
1080 0 : DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1081 : __func__);
1082 0 : BREAK_TO_DEBUGGER();
1083 : }
1084 0 : }
1085 :
1086 : /* TODO: still need depth or just pass in adjusted pixel clock? */
1087 0 : void dce110_link_encoder_enable_lvds_output(
1088 : struct link_encoder *enc,
1089 : enum clock_source_id clock_source,
1090 : uint32_t pixel_clock)
1091 : {
1092 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1093 0 : struct bp_transmitter_control cntl = { 0 };
1094 : enum bp_result result;
1095 :
1096 : /* Enable the PHY */
1097 0 : cntl.connector_obj_id = enc110->base.connector;
1098 0 : cntl.action = TRANSMITTER_CONTROL_ENABLE;
1099 0 : cntl.engine_id = enc->preferred_engine;
1100 0 : cntl.transmitter = enc110->base.transmitter;
1101 0 : cntl.pll_id = clock_source;
1102 0 : cntl.signal = SIGNAL_TYPE_LVDS;
1103 0 : cntl.lanes_number = 4;
1104 :
1105 0 : cntl.hpd_sel = enc110->base.hpd_source;
1106 :
1107 0 : cntl.pixel_clock = pixel_clock;
1108 :
1109 0 : result = link_transmitter_control(enc110, &cntl);
1110 :
1111 0 : if (result != BP_RESULT_OK) {
1112 0 : DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1113 : __func__);
1114 0 : BREAK_TO_DEBUGGER();
1115 : }
1116 0 : }
1117 :
1118 : /* enables DP PHY output */
1119 0 : void dce110_link_encoder_enable_dp_output(
1120 : struct link_encoder *enc,
1121 : const struct dc_link_settings *link_settings,
1122 : enum clock_source_id clock_source)
1123 : {
1124 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1125 0 : struct bp_transmitter_control cntl = { 0 };
1126 : enum bp_result result;
1127 :
1128 : /* Enable the PHY */
1129 :
1130 : /* number_of_lanes is used for pixel clock adjust,
1131 : * but it's not passed to asic_control.
1132 : * We need to set number of lanes manually.
1133 : */
1134 0 : configure_encoder(enc110, link_settings);
1135 0 : cntl.connector_obj_id = enc110->base.connector;
1136 0 : cntl.action = TRANSMITTER_CONTROL_ENABLE;
1137 0 : cntl.engine_id = enc->preferred_engine;
1138 0 : cntl.transmitter = enc110->base.transmitter;
1139 0 : cntl.pll_id = clock_source;
1140 0 : cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;
1141 0 : cntl.lanes_number = link_settings->lane_count;
1142 0 : cntl.hpd_sel = enc110->base.hpd_source;
1143 0 : cntl.pixel_clock = link_settings->link_rate
1144 0 : * LINK_RATE_REF_FREQ_IN_KHZ;
1145 : /* TODO: check if undefined works */
1146 0 : cntl.color_depth = COLOR_DEPTH_UNDEFINED;
1147 :
1148 0 : result = link_transmitter_control(enc110, &cntl);
1149 :
1150 0 : if (result != BP_RESULT_OK) {
1151 0 : DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1152 : __func__);
1153 0 : BREAK_TO_DEBUGGER();
1154 : }
1155 0 : }
1156 :
1157 : /* enables DP PHY output in MST mode */
1158 0 : void dce110_link_encoder_enable_dp_mst_output(
1159 : struct link_encoder *enc,
1160 : const struct dc_link_settings *link_settings,
1161 : enum clock_source_id clock_source)
1162 : {
1163 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1164 0 : struct bp_transmitter_control cntl = { 0 };
1165 : enum bp_result result;
1166 :
1167 : /* Enable the PHY */
1168 :
1169 : /* number_of_lanes is used for pixel clock adjust,
1170 : * but it's not passed to asic_control.
1171 : * We need to set number of lanes manually.
1172 : */
1173 0 : configure_encoder(enc110, link_settings);
1174 :
1175 0 : cntl.action = TRANSMITTER_CONTROL_ENABLE;
1176 0 : cntl.engine_id = ENGINE_ID_UNKNOWN;
1177 0 : cntl.transmitter = enc110->base.transmitter;
1178 0 : cntl.pll_id = clock_source;
1179 0 : cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
1180 0 : cntl.lanes_number = link_settings->lane_count;
1181 0 : cntl.hpd_sel = enc110->base.hpd_source;
1182 0 : cntl.pixel_clock = link_settings->link_rate
1183 0 : * LINK_RATE_REF_FREQ_IN_KHZ;
1184 : /* TODO: check if undefined works */
1185 0 : cntl.color_depth = COLOR_DEPTH_UNDEFINED;
1186 :
1187 0 : result = link_transmitter_control(enc110, &cntl);
1188 :
1189 0 : if (result != BP_RESULT_OK) {
1190 0 : DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1191 : __func__);
1192 0 : BREAK_TO_DEBUGGER();
1193 : }
1194 0 : }
1195 :
1196 : #if defined(CONFIG_DRM_AMD_DC_SI)
1197 : /* enables DP PHY output */
1198 : static void dce60_link_encoder_enable_dp_output(
1199 : struct link_encoder *enc,
1200 : const struct dc_link_settings *link_settings,
1201 : enum clock_source_id clock_source)
1202 : {
1203 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1204 : struct bp_transmitter_control cntl = { 0 };
1205 : enum bp_result result;
1206 :
1207 : /* Enable the PHY */
1208 :
1209 : /* number_of_lanes is used for pixel clock adjust,
1210 : * but it's not passed to asic_control.
1211 : * We need to set number of lanes manually.
1212 : */
1213 : dce60_configure_encoder(enc110, link_settings);
1214 : cntl.connector_obj_id = enc110->base.connector;
1215 : cntl.action = TRANSMITTER_CONTROL_ENABLE;
1216 : cntl.engine_id = enc->preferred_engine;
1217 : cntl.transmitter = enc110->base.transmitter;
1218 : cntl.pll_id = clock_source;
1219 : cntl.signal = SIGNAL_TYPE_DISPLAY_PORT;
1220 : cntl.lanes_number = link_settings->lane_count;
1221 : cntl.hpd_sel = enc110->base.hpd_source;
1222 : cntl.pixel_clock = link_settings->link_rate
1223 : * LINK_RATE_REF_FREQ_IN_KHZ;
1224 : /* TODO: check if undefined works */
1225 : cntl.color_depth = COLOR_DEPTH_UNDEFINED;
1226 :
1227 : result = link_transmitter_control(enc110, &cntl);
1228 :
1229 : if (result != BP_RESULT_OK) {
1230 : DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1231 : __func__);
1232 : BREAK_TO_DEBUGGER();
1233 : }
1234 : }
1235 :
1236 : /* enables DP PHY output in MST mode */
1237 : static void dce60_link_encoder_enable_dp_mst_output(
1238 : struct link_encoder *enc,
1239 : const struct dc_link_settings *link_settings,
1240 : enum clock_source_id clock_source)
1241 : {
1242 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1243 : struct bp_transmitter_control cntl = { 0 };
1244 : enum bp_result result;
1245 :
1246 : /* Enable the PHY */
1247 :
1248 : /* number_of_lanes is used for pixel clock adjust,
1249 : * but it's not passed to asic_control.
1250 : * We need to set number of lanes manually.
1251 : */
1252 : dce60_configure_encoder(enc110, link_settings);
1253 :
1254 : cntl.action = TRANSMITTER_CONTROL_ENABLE;
1255 : cntl.engine_id = ENGINE_ID_UNKNOWN;
1256 : cntl.transmitter = enc110->base.transmitter;
1257 : cntl.pll_id = clock_source;
1258 : cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
1259 : cntl.lanes_number = link_settings->lane_count;
1260 : cntl.hpd_sel = enc110->base.hpd_source;
1261 : cntl.pixel_clock = link_settings->link_rate
1262 : * LINK_RATE_REF_FREQ_IN_KHZ;
1263 : /* TODO: check if undefined works */
1264 : cntl.color_depth = COLOR_DEPTH_UNDEFINED;
1265 :
1266 : result = link_transmitter_control(enc110, &cntl);
1267 :
1268 : if (result != BP_RESULT_OK) {
1269 : DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1270 : __func__);
1271 : BREAK_TO_DEBUGGER();
1272 : }
1273 : }
1274 : #endif
1275 :
1276 : /*
1277 : * @brief
1278 : * Disable transmitter and its encoder
1279 : */
1280 0 : void dce110_link_encoder_disable_output(
1281 : struct link_encoder *enc,
1282 : enum signal_type signal)
1283 : {
1284 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1285 0 : struct bp_transmitter_control cntl = { 0 };
1286 : enum bp_result result;
1287 :
1288 0 : if (!dce110_is_dig_enabled(enc)) {
1289 : /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */
1290 0 : return;
1291 : }
1292 : /* Power-down RX and disable GPU PHY should be paired.
1293 : * Disabling PHY without powering down RX may cause
1294 : * symbol lock loss, on which we will get DP Sink interrupt. */
1295 :
1296 : /* There is a case for the DP active dongles
1297 : * where we want to disable the PHY but keep RX powered,
1298 : * for those we need to ignore DP Sink interrupt
1299 : * by checking lane count that has been set
1300 : * on the last do_enable_output(). */
1301 :
1302 : /* disable transmitter */
1303 0 : cntl.action = TRANSMITTER_CONTROL_DISABLE;
1304 0 : cntl.transmitter = enc110->base.transmitter;
1305 0 : cntl.hpd_sel = enc110->base.hpd_source;
1306 0 : cntl.signal = signal;
1307 0 : cntl.connector_obj_id = enc110->base.connector;
1308 :
1309 0 : result = link_transmitter_control(enc110, &cntl);
1310 :
1311 0 : if (result != BP_RESULT_OK) {
1312 0 : DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
1313 : __func__);
1314 0 : BREAK_TO_DEBUGGER();
1315 0 : return;
1316 : }
1317 :
1318 : /* disable encoder */
1319 0 : if (dc_is_dp_signal(signal))
1320 0 : link_encoder_disable(enc110);
1321 : }
1322 :
1323 0 : void dce110_link_encoder_dp_set_lane_settings(
1324 : struct link_encoder *enc,
1325 : const struct dc_link_settings *link_settings,
1326 : const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
1327 : {
1328 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1329 0 : union dpcd_training_lane_set training_lane_set = { { 0 } };
1330 0 : int32_t lane = 0;
1331 0 : struct bp_transmitter_control cntl = { 0 };
1332 :
1333 0 : if (!link_settings) {
1334 0 : BREAK_TO_DEBUGGER();
1335 0 : return;
1336 : }
1337 :
1338 0 : cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
1339 0 : cntl.transmitter = enc110->base.transmitter;
1340 0 : cntl.connector_obj_id = enc110->base.connector;
1341 0 : cntl.lanes_number = link_settings->lane_count;
1342 0 : cntl.hpd_sel = enc110->base.hpd_source;
1343 0 : cntl.pixel_clock = link_settings->link_rate *
1344 : LINK_RATE_REF_FREQ_IN_KHZ;
1345 :
1346 0 : for (lane = 0; lane < link_settings->lane_count; lane++) {
1347 : /* translate lane settings */
1348 :
1349 0 : training_lane_set.bits.VOLTAGE_SWING_SET =
1350 0 : lane_settings[lane].VOLTAGE_SWING;
1351 0 : training_lane_set.bits.PRE_EMPHASIS_SET =
1352 0 : lane_settings[lane].PRE_EMPHASIS;
1353 :
1354 : /* post cursor 2 setting only applies to HBR2 link rate */
1355 0 : if (link_settings->link_rate == LINK_RATE_HIGH2) {
1356 : /* this is passed to VBIOS
1357 : * to program post cursor 2 level */
1358 :
1359 0 : training_lane_set.bits.POST_CURSOR2_SET =
1360 0 : lane_settings[lane].POST_CURSOR2;
1361 : }
1362 :
1363 0 : cntl.lane_select = lane;
1364 0 : cntl.lane_settings = training_lane_set.raw;
1365 :
1366 : /* call VBIOS table to set voltage swing and pre-emphasis */
1367 0 : link_transmitter_control(enc110, &cntl);
1368 : }
1369 : }
1370 :
1371 : /* set DP PHY test and training patterns */
1372 0 : void dce110_link_encoder_dp_set_phy_pattern(
1373 : struct link_encoder *enc,
1374 : const struct encoder_set_dp_phy_pattern_param *param)
1375 : {
1376 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1377 :
1378 0 : switch (param->dp_phy_pattern) {
1379 : case DP_TEST_PATTERN_TRAINING_PATTERN1:
1380 0 : dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0);
1381 0 : break;
1382 : case DP_TEST_PATTERN_TRAINING_PATTERN2:
1383 0 : dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1);
1384 0 : break;
1385 : case DP_TEST_PATTERN_TRAINING_PATTERN3:
1386 0 : dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2);
1387 0 : break;
1388 : case DP_TEST_PATTERN_TRAINING_PATTERN4:
1389 0 : dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3);
1390 0 : break;
1391 : case DP_TEST_PATTERN_D102:
1392 0 : set_dp_phy_pattern_d102(enc110);
1393 0 : break;
1394 : case DP_TEST_PATTERN_SYMBOL_ERROR:
1395 0 : set_dp_phy_pattern_symbol_error(enc110);
1396 0 : break;
1397 : case DP_TEST_PATTERN_PRBS7:
1398 0 : set_dp_phy_pattern_prbs7(enc110);
1399 0 : break;
1400 : case DP_TEST_PATTERN_80BIT_CUSTOM:
1401 0 : set_dp_phy_pattern_80bit_custom(
1402 : enc110, param->custom_pattern);
1403 0 : break;
1404 : case DP_TEST_PATTERN_CP2520_1:
1405 0 : set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1);
1406 0 : break;
1407 : case DP_TEST_PATTERN_CP2520_2:
1408 0 : set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2);
1409 0 : break;
1410 : case DP_TEST_PATTERN_CP2520_3:
1411 0 : set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3);
1412 0 : break;
1413 : case DP_TEST_PATTERN_VIDEO_MODE: {
1414 0 : set_dp_phy_pattern_passthrough_mode(
1415 : enc110, param->dp_panel_mode);
1416 0 : break;
1417 : }
1418 :
1419 : default:
1420 : /* invalid phy pattern */
1421 0 : ASSERT_CRITICAL(false);
1422 0 : break;
1423 : }
1424 0 : }
1425 :
1426 : #if defined(CONFIG_DRM_AMD_DC_SI)
1427 : /* set DP PHY test and training patterns */
1428 : static void dce60_link_encoder_dp_set_phy_pattern(
1429 : struct link_encoder *enc,
1430 : const struct encoder_set_dp_phy_pattern_param *param)
1431 : {
1432 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1433 :
1434 : switch (param->dp_phy_pattern) {
1435 : case DP_TEST_PATTERN_TRAINING_PATTERN1:
1436 : dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 0);
1437 : break;
1438 : case DP_TEST_PATTERN_TRAINING_PATTERN2:
1439 : dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 1);
1440 : break;
1441 : case DP_TEST_PATTERN_TRAINING_PATTERN3:
1442 : dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 2);
1443 : break;
1444 : case DP_TEST_PATTERN_TRAINING_PATTERN4:
1445 : dce110_link_encoder_set_dp_phy_pattern_training_pattern(enc, 3);
1446 : break;
1447 : case DP_TEST_PATTERN_D102:
1448 : set_dp_phy_pattern_d102(enc110);
1449 : break;
1450 : case DP_TEST_PATTERN_SYMBOL_ERROR:
1451 : set_dp_phy_pattern_symbol_error(enc110);
1452 : break;
1453 : case DP_TEST_PATTERN_PRBS7:
1454 : set_dp_phy_pattern_prbs7(enc110);
1455 : break;
1456 : case DP_TEST_PATTERN_80BIT_CUSTOM:
1457 : set_dp_phy_pattern_80bit_custom(
1458 : enc110, param->custom_pattern);
1459 : break;
1460 : case DP_TEST_PATTERN_CP2520_1:
1461 : dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 1);
1462 : break;
1463 : case DP_TEST_PATTERN_CP2520_2:
1464 : dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 2);
1465 : break;
1466 : case DP_TEST_PATTERN_CP2520_3:
1467 : dce60_set_dp_phy_pattern_hbr2_compliance_cp2520_2(enc110, 3);
1468 : break;
1469 : case DP_TEST_PATTERN_VIDEO_MODE: {
1470 : dce60_set_dp_phy_pattern_passthrough_mode(
1471 : enc110, param->dp_panel_mode);
1472 : break;
1473 : }
1474 :
1475 : default:
1476 : /* invalid phy pattern */
1477 : ASSERT_CRITICAL(false);
1478 : break;
1479 : }
1480 : }
1481 : #endif
1482 :
1483 : static void fill_stream_allocation_row_info(
1484 : const struct link_mst_stream_allocation *stream_allocation,
1485 : uint32_t *src,
1486 : uint32_t *slots)
1487 : {
1488 0 : const struct stream_encoder *stream_enc = stream_allocation->stream_enc;
1489 :
1490 0 : if (stream_enc) {
1491 0 : *src = stream_enc->id;
1492 0 : *slots = stream_allocation->slot_count;
1493 : } else {
1494 : *src = 0;
1495 : *slots = 0;
1496 : }
1497 : }
1498 :
1499 : /* programs DP MST VC payload allocation */
1500 0 : void dce110_link_encoder_update_mst_stream_allocation_table(
1501 : struct link_encoder *enc,
1502 : const struct link_mst_stream_allocation_table *table)
1503 : {
1504 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1505 0 : uint32_t value1 = 0;
1506 0 : uint32_t value2 = 0;
1507 0 : uint32_t slots = 0;
1508 0 : uint32_t src = 0;
1509 0 : uint32_t retries = 0;
1510 :
1511 : /* For CZ, there are only 3 pipes. So Virtual channel is up 3.*/
1512 :
1513 : /* --- Set MSE Stream Attribute -
1514 : * Setup VC Payload Table on Tx Side,
1515 : * Issue allocation change trigger
1516 : * to commit payload on both tx and rx side */
1517 :
1518 : /* we should clean-up table each time */
1519 :
1520 0 : if (table->stream_count >= 1) {
1521 0 : fill_stream_allocation_row_info(
1522 : &table->stream_allocations[0],
1523 : &src,
1524 : &slots);
1525 : } else {
1526 : src = 0;
1527 : slots = 0;
1528 : }
1529 :
1530 0 : REG_UPDATE_2(DP_MSE_SAT0,
1531 : DP_MSE_SAT_SRC0, src,
1532 : DP_MSE_SAT_SLOT_COUNT0, slots);
1533 :
1534 0 : if (table->stream_count >= 2) {
1535 0 : fill_stream_allocation_row_info(
1536 : &table->stream_allocations[1],
1537 : &src,
1538 : &slots);
1539 : } else {
1540 : src = 0;
1541 : slots = 0;
1542 : }
1543 :
1544 0 : REG_UPDATE_2(DP_MSE_SAT0,
1545 : DP_MSE_SAT_SRC1, src,
1546 : DP_MSE_SAT_SLOT_COUNT1, slots);
1547 :
1548 0 : if (table->stream_count >= 3) {
1549 0 : fill_stream_allocation_row_info(
1550 : &table->stream_allocations[2],
1551 : &src,
1552 : &slots);
1553 : } else {
1554 : src = 0;
1555 : slots = 0;
1556 : }
1557 :
1558 0 : REG_UPDATE_2(DP_MSE_SAT1,
1559 : DP_MSE_SAT_SRC2, src,
1560 : DP_MSE_SAT_SLOT_COUNT2, slots);
1561 :
1562 0 : if (table->stream_count >= 4) {
1563 0 : fill_stream_allocation_row_info(
1564 : &table->stream_allocations[3],
1565 : &src,
1566 : &slots);
1567 : } else {
1568 : src = 0;
1569 : slots = 0;
1570 : }
1571 :
1572 0 : REG_UPDATE_2(DP_MSE_SAT1,
1573 : DP_MSE_SAT_SRC3, src,
1574 : DP_MSE_SAT_SLOT_COUNT3, slots);
1575 :
1576 : /* --- wait for transaction finish */
1577 :
1578 : /* send allocation change trigger (ACT) ?
1579 : * this step first sends the ACT,
1580 : * then double buffers the SAT into the hardware
1581 : * making the new allocation active on the DP MST mode link */
1582 :
1583 :
1584 : /* DP_MSE_SAT_UPDATE:
1585 : * 0 - No Action
1586 : * 1 - Update SAT with trigger
1587 : * 2 - Update SAT without trigger */
1588 :
1589 0 : REG_UPDATE(DP_MSE_SAT_UPDATE,
1590 : DP_MSE_SAT_UPDATE, 1);
1591 :
1592 : /* wait for update to complete
1593 : * (i.e. DP_MSE_SAT_UPDATE field is reset to 0)
1594 : * then wait for the transmission
1595 : * of at least 16 MTP headers on immediate local link.
1596 : * i.e. DP_MSE_16_MTP_KEEPOUT field (read only) is reset to 0
1597 : * a value of 1 indicates that DP MST mode
1598 : * is in the 16 MTP keepout region after a VC has been added.
1599 : * MST stream bandwidth (VC rate) can be configured
1600 : * after this bit is cleared */
1601 :
1602 : do {
1603 0 : udelay(10);
1604 :
1605 0 : REG_READ(DP_MSE_SAT_UPDATE);
1606 :
1607 0 : REG_GET(DP_MSE_SAT_UPDATE,
1608 : DP_MSE_SAT_UPDATE, &value1);
1609 :
1610 0 : REG_GET(DP_MSE_SAT_UPDATE,
1611 : DP_MSE_16_MTP_KEEPOUT, &value2);
1612 :
1613 : /* bit field DP_MSE_SAT_UPDATE is set to 1 already */
1614 0 : if (!value1 && !value2)
1615 : break;
1616 0 : ++retries;
1617 0 : } while (retries < DP_MST_UPDATE_MAX_RETRY);
1618 0 : }
1619 :
1620 0 : void dce110_link_encoder_connect_dig_be_to_fe(
1621 : struct link_encoder *enc,
1622 : enum engine_id engine,
1623 : bool connect)
1624 : {
1625 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1626 : uint32_t field;
1627 :
1628 0 : if (engine != ENGINE_ID_UNKNOWN) {
1629 :
1630 0 : REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &field);
1631 :
1632 0 : if (connect)
1633 0 : field |= get_frontend_source(engine);
1634 : else
1635 0 : field &= ~get_frontend_source(engine);
1636 :
1637 0 : REG_UPDATE(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, field);
1638 : }
1639 0 : }
1640 :
1641 0 : void dce110_link_encoder_enable_hpd(struct link_encoder *enc)
1642 : {
1643 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1644 0 : struct dc_context *ctx = enc110->base.ctx;
1645 0 : uint32_t addr = HPD_REG(DC_HPD_CONTROL);
1646 0 : uint32_t hpd_enable = 0;
1647 0 : uint32_t value = dm_read_reg(ctx, addr);
1648 :
1649 0 : get_reg_field_value(hpd_enable, DC_HPD_CONTROL, DC_HPD_EN);
1650 :
1651 : if (hpd_enable == 0)
1652 0 : set_reg_field_value(value, 1, DC_HPD_CONTROL, DC_HPD_EN);
1653 0 : }
1654 :
1655 0 : void dce110_link_encoder_disable_hpd(struct link_encoder *enc)
1656 : {
1657 0 : struct dce110_link_encoder *enc110 = TO_DCE110_LINK_ENC(enc);
1658 0 : struct dc_context *ctx = enc110->base.ctx;
1659 0 : uint32_t addr = HPD_REG(DC_HPD_CONTROL);
1660 0 : uint32_t value = dm_read_reg(ctx, addr);
1661 :
1662 0 : set_reg_field_value(value, 0, DC_HPD_CONTROL, DC_HPD_EN);
1663 0 : }
1664 :
1665 0 : void dce110_link_encoder_get_max_link_cap(struct link_encoder *enc,
1666 : struct dc_link_settings *link_settings)
1667 : {
1668 : /* Set Default link settings */
1669 0 : struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
1670 : LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};
1671 :
1672 : /* Higher link settings based on feature supported */
1673 0 : if (enc->features.flags.bits.IS_HBR2_CAPABLE)
1674 0 : max_link_cap.link_rate = LINK_RATE_HIGH2;
1675 :
1676 0 : if (enc->features.flags.bits.IS_HBR3_CAPABLE)
1677 0 : max_link_cap.link_rate = LINK_RATE_HIGH3;
1678 :
1679 0 : *link_settings = max_link_cap;
1680 0 : }
1681 :
1682 : #if defined(CONFIG_DRM_AMD_DC_SI)
1683 : static const struct link_encoder_funcs dce60_lnk_enc_funcs = {
1684 : .validate_output_with_stream =
1685 : dce110_link_encoder_validate_output_with_stream,
1686 : .hw_init = dce110_link_encoder_hw_init,
1687 : .setup = dce110_link_encoder_setup,
1688 : .enable_tmds_output = dce110_link_encoder_enable_tmds_output,
1689 : .enable_dp_output = dce60_link_encoder_enable_dp_output,
1690 : .enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output,
1691 : .enable_lvds_output = dce110_link_encoder_enable_lvds_output,
1692 : .disable_output = dce110_link_encoder_disable_output,
1693 : .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
1694 : .dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern,
1695 : .update_mst_stream_allocation_table =
1696 : dce110_link_encoder_update_mst_stream_allocation_table,
1697 : .psr_program_dp_dphy_fast_training =
1698 : dce110_psr_program_dp_dphy_fast_training,
1699 : .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
1700 : .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
1701 : .enable_hpd = dce110_link_encoder_enable_hpd,
1702 : .disable_hpd = dce110_link_encoder_disable_hpd,
1703 : .is_dig_enabled = dce110_is_dig_enabled,
1704 : .destroy = dce110_link_encoder_destroy,
1705 : .get_max_link_cap = dce110_link_encoder_get_max_link_cap,
1706 : .get_dig_frontend = dce110_get_dig_frontend
1707 : };
1708 :
1709 : void dce60_link_encoder_construct(
1710 : struct dce110_link_encoder *enc110,
1711 : const struct encoder_init_data *init_data,
1712 : const struct encoder_feature_support *enc_features,
1713 : const struct dce110_link_enc_registers *link_regs,
1714 : const struct dce110_link_enc_aux_registers *aux_regs,
1715 : const struct dce110_link_enc_hpd_registers *hpd_regs)
1716 : {
1717 : struct bp_encoder_cap_info bp_cap_info = {0};
1718 : const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
1719 : enum bp_result result = BP_RESULT_OK;
1720 :
1721 : enc110->base.funcs = &dce60_lnk_enc_funcs;
1722 : enc110->base.ctx = init_data->ctx;
1723 : enc110->base.id = init_data->encoder;
1724 :
1725 : enc110->base.hpd_source = init_data->hpd_source;
1726 : enc110->base.connector = init_data->connector;
1727 :
1728 : enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
1729 :
1730 : enc110->base.features = *enc_features;
1731 :
1732 : enc110->base.transmitter = init_data->transmitter;
1733 :
1734 : /* set the flag to indicate whether driver poll the I2C data pin
1735 : * while doing the DP sink detect
1736 : */
1737 :
1738 : /* if (dal_adapter_service_is_feature_supported(as,
1739 : FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
1740 : enc110->base.features.flags.bits.
1741 : DP_SINK_DETECT_POLL_DATA_PIN = true;*/
1742 :
1743 : enc110->base.output_signals =
1744 : SIGNAL_TYPE_DVI_SINGLE_LINK |
1745 : SIGNAL_TYPE_DVI_DUAL_LINK |
1746 : SIGNAL_TYPE_LVDS |
1747 : SIGNAL_TYPE_DISPLAY_PORT |
1748 : SIGNAL_TYPE_DISPLAY_PORT_MST |
1749 : SIGNAL_TYPE_EDP |
1750 : SIGNAL_TYPE_HDMI_TYPE_A;
1751 :
1752 : /* For DCE 8.0 and 8.1, by design, UNIPHY is hardwired to DIG_BE.
1753 : * SW always assign DIG_FE 1:1 mapped to DIG_FE for non-MST UNIPHY.
1754 : * SW assign DIG_FE to non-MST UNIPHY first and MST last. So prefer
1755 : * DIG is per UNIPHY and used by SST DP, eDP, HDMI, DVI and LVDS.
1756 : * Prefer DIG assignment is decided by board design.
1757 : * For DCE 8.0, there are only max 6 UNIPHYs, we assume board design
1758 : * and VBIOS will filter out 7 UNIPHY for DCE 8.0.
1759 : * By this, adding DIGG should not hurt DCE 8.0.
1760 : * This will let DCE 8.1 share DCE 8.0 as much as possible
1761 : */
1762 :
1763 : enc110->link_regs = link_regs;
1764 : enc110->aux_regs = aux_regs;
1765 : enc110->hpd_regs = hpd_regs;
1766 :
1767 : switch (enc110->base.transmitter) {
1768 : case TRANSMITTER_UNIPHY_A:
1769 : enc110->base.preferred_engine = ENGINE_ID_DIGA;
1770 : break;
1771 : case TRANSMITTER_UNIPHY_B:
1772 : enc110->base.preferred_engine = ENGINE_ID_DIGB;
1773 : break;
1774 : case TRANSMITTER_UNIPHY_C:
1775 : enc110->base.preferred_engine = ENGINE_ID_DIGC;
1776 : break;
1777 : case TRANSMITTER_UNIPHY_D:
1778 : enc110->base.preferred_engine = ENGINE_ID_DIGD;
1779 : break;
1780 : case TRANSMITTER_UNIPHY_E:
1781 : enc110->base.preferred_engine = ENGINE_ID_DIGE;
1782 : break;
1783 : case TRANSMITTER_UNIPHY_F:
1784 : enc110->base.preferred_engine = ENGINE_ID_DIGF;
1785 : break;
1786 : case TRANSMITTER_UNIPHY_G:
1787 : enc110->base.preferred_engine = ENGINE_ID_DIGG;
1788 : break;
1789 : default:
1790 : ASSERT_CRITICAL(false);
1791 : enc110->base.preferred_engine = ENGINE_ID_UNKNOWN;
1792 : }
1793 :
1794 : /* default to one to mirror Windows behavior */
1795 : enc110->base.features.flags.bits.HDMI_6GB_EN = 1;
1796 :
1797 : result = bp_funcs->get_encoder_cap_info(enc110->base.ctx->dc_bios,
1798 : enc110->base.id, &bp_cap_info);
1799 :
1800 : /* Override features with DCE-specific values */
1801 : if (BP_RESULT_OK == result) {
1802 : enc110->base.features.flags.bits.IS_HBR2_CAPABLE =
1803 : bp_cap_info.DP_HBR2_EN;
1804 : enc110->base.features.flags.bits.IS_HBR3_CAPABLE =
1805 : bp_cap_info.DP_HBR3_EN;
1806 : enc110->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
1807 : } else {
1808 : DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
1809 : __func__,
1810 : result);
1811 : }
1812 : if (enc110->base.ctx->dc->debug.hdmi20_disable) {
1813 : enc110->base.features.flags.bits.HDMI_6GB_EN = 0;
1814 : }
1815 : }
1816 : #endif
|