1/*
2 * Copyright 2019 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 "dc_bios_types.h"
27#include "dcn31_hpo_dp_link_encoder.h"
28#include "reg_helper.h"
29#include "stream_encoder.h"
30
31#define DC_LOGGER \
32 enc3->base.ctx->logger
33
34#define REG(reg)\
35 (enc3->regs->reg)
36
37#undef FN
38#define FN(reg_name, field_name) \
39 enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name
40
41
42#define CTX \
43 enc3->base.ctx
44
45enum {
46 DP_SAT_UPDATE_MAX_RETRY = 200
47};
48
49void dcn31_hpo_dp_link_enc_enable(
50 struct hpo_dp_link_encoder *enc,
51 enum dc_lane_count num_lanes)
52{
53 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
54 uint32_t dp_link_enabled;
55
56 /* get current status of link enabled */
57 REG_GET(DP_DPHY_SYM32_STATUS,
58 STATUS, &dp_link_enabled);
59
60 /* Enable clocks first */
61 REG_UPDATE(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, 1);
62
63 /* Reset DPHY. Only reset if going from disable to enable */
64 if (!dp_link_enabled) {
65 REG_UPDATE(DP_DPHY_SYM32_CONTROL, DPHY_RESET, 1);
66 REG_UPDATE(DP_DPHY_SYM32_CONTROL, DPHY_RESET, 0);
67 }
68
69 /* Configure DPHY settings */
70 REG_UPDATE_3(DP_DPHY_SYM32_CONTROL,
71 DPHY_ENABLE, 1,
72 PRECODER_ENABLE, 1,
73 NUM_LANES, num_lanes == LANE_COUNT_ONE ? 0 : num_lanes == LANE_COUNT_TWO ? 1 : 3);
74}
75
76void dcn31_hpo_dp_link_enc_disable(
77 struct hpo_dp_link_encoder *enc)
78{
79 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
80
81 /* Configure DPHY settings */
82 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
83 DPHY_ENABLE, 0);
84
85 /* Shut down clock last */
86 REG_UPDATE(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC_CLOCK_EN, 0);
87}
88
89void dcn31_hpo_dp_link_enc_set_link_test_pattern(
90 struct hpo_dp_link_encoder *enc,
91 struct encoder_set_dp_phy_pattern_param *tp_params)
92{
93 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
94 uint32_t tp_custom;
95
96 switch (tp_params->dp_phy_pattern) {
97 case DP_TEST_PATTERN_VIDEO_MODE:
98 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
99 MODE, DP2_LINK_ACTIVE);
100 break;
101 case DP_TEST_PATTERN_128b_132b_TPS1_TRAINING_MODE:
102 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
103 MODE, DP2_LINK_TRAINING_TPS1);
104 break;
105 case DP_TEST_PATTERN_128b_132b_TPS2_TRAINING_MODE:
106 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
107 MODE, DP2_LINK_TRAINING_TPS2);
108 break;
109 case DP_TEST_PATTERN_128b_132b_TPS1:
110 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
111 TP_SELECT0, DP_DPHY_TP_SELECT_TPS1,
112 TP_SELECT1, DP_DPHY_TP_SELECT_TPS1,
113 TP_SELECT2, DP_DPHY_TP_SELECT_TPS1,
114 TP_SELECT3, DP_DPHY_TP_SELECT_TPS1);
115 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
116 MODE, DP2_TEST_PATTERN);
117 break;
118 case DP_TEST_PATTERN_128b_132b_TPS2:
119 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
120 TP_SELECT0, DP_DPHY_TP_SELECT_TPS2,
121 TP_SELECT1, DP_DPHY_TP_SELECT_TPS2,
122 TP_SELECT2, DP_DPHY_TP_SELECT_TPS2,
123 TP_SELECT3, DP_DPHY_TP_SELECT_TPS2);
124 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
125 MODE, DP2_TEST_PATTERN);
126 break;
127 case DP_TEST_PATTERN_PRBS7:
128 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
129 TP_PRBS_SEL0, DP_DPHY_TP_PRBS7,
130 TP_PRBS_SEL1, DP_DPHY_TP_PRBS7,
131 TP_PRBS_SEL2, DP_DPHY_TP_PRBS7,
132 TP_PRBS_SEL3, DP_DPHY_TP_PRBS7);
133 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
134 TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
135 TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
136 TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
137 TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
138 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
139 MODE, DP2_TEST_PATTERN);
140 break;
141 case DP_TEST_PATTERN_PRBS9:
142 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
143 TP_PRBS_SEL0, DP_DPHY_TP_PRBS9,
144 TP_PRBS_SEL1, DP_DPHY_TP_PRBS9,
145 TP_PRBS_SEL2, DP_DPHY_TP_PRBS9,
146 TP_PRBS_SEL3, DP_DPHY_TP_PRBS9);
147 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
148 TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
149 TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
150 TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
151 TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
152 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
153 MODE, DP2_TEST_PATTERN);
154 break;
155 case DP_TEST_PATTERN_PRBS11:
156 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
157 TP_PRBS_SEL0, DP_DPHY_TP_PRBS11,
158 TP_PRBS_SEL1, DP_DPHY_TP_PRBS11,
159 TP_PRBS_SEL2, DP_DPHY_TP_PRBS11,
160 TP_PRBS_SEL3, DP_DPHY_TP_PRBS11);
161 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
162 TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
163 TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
164 TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
165 TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
166 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
167 MODE, DP2_TEST_PATTERN);
168 break;
169 case DP_TEST_PATTERN_PRBS15:
170 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
171 TP_PRBS_SEL0, DP_DPHY_TP_PRBS15,
172 TP_PRBS_SEL1, DP_DPHY_TP_PRBS15,
173 TP_PRBS_SEL2, DP_DPHY_TP_PRBS15,
174 TP_PRBS_SEL3, DP_DPHY_TP_PRBS15);
175 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
176 TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
177 TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
178 TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
179 TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
180 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
181 MODE, DP2_TEST_PATTERN);
182 break;
183 case DP_TEST_PATTERN_PRBS23:
184 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
185 TP_PRBS_SEL0, DP_DPHY_TP_PRBS23,
186 TP_PRBS_SEL1, DP_DPHY_TP_PRBS23,
187 TP_PRBS_SEL2, DP_DPHY_TP_PRBS23,
188 TP_PRBS_SEL3, DP_DPHY_TP_PRBS23);
189 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
190 TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
191 TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
192 TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
193 TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
194 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
195 MODE, DP2_TEST_PATTERN);
196 break;
197 case DP_TEST_PATTERN_PRBS31:
198 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
199 TP_PRBS_SEL0, DP_DPHY_TP_PRBS31,
200 TP_PRBS_SEL1, DP_DPHY_TP_PRBS31,
201 TP_PRBS_SEL2, DP_DPHY_TP_PRBS31,
202 TP_PRBS_SEL3, DP_DPHY_TP_PRBS31);
203 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
204 TP_SELECT0, DP_DPHY_TP_SELECT_PRBS,
205 TP_SELECT1, DP_DPHY_TP_SELECT_PRBS,
206 TP_SELECT2, DP_DPHY_TP_SELECT_PRBS,
207 TP_SELECT3, DP_DPHY_TP_SELECT_PRBS);
208 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
209 MODE, DP2_TEST_PATTERN);
210 break;
211 case DP_TEST_PATTERN_264BIT_CUSTOM:
212 tp_custom = (tp_params->custom_pattern[2] << 16) | (tp_params->custom_pattern[1] << 8) | tp_params->custom_pattern[0];
213 REG_SET(DP_DPHY_SYM32_TP_CUSTOM0, 0, TP_CUSTOM, tp_custom);
214 tp_custom = (tp_params->custom_pattern[5] << 16) | (tp_params->custom_pattern[4] << 8) | tp_params->custom_pattern[3];
215 REG_SET(DP_DPHY_SYM32_TP_CUSTOM1, 0, TP_CUSTOM, tp_custom);
216 tp_custom = (tp_params->custom_pattern[8] << 16) | (tp_params->custom_pattern[7] << 8) | tp_params->custom_pattern[6];
217 REG_SET(DP_DPHY_SYM32_TP_CUSTOM2, 0, TP_CUSTOM, tp_custom);
218 tp_custom = (tp_params->custom_pattern[11] << 16) | (tp_params->custom_pattern[10] << 8) | tp_params->custom_pattern[9];
219 REG_SET(DP_DPHY_SYM32_TP_CUSTOM3, 0, TP_CUSTOM, tp_custom);
220 tp_custom = (tp_params->custom_pattern[14] << 16) | (tp_params->custom_pattern[13] << 8) | tp_params->custom_pattern[12];
221 REG_SET(DP_DPHY_SYM32_TP_CUSTOM4, 0, TP_CUSTOM, tp_custom);
222 tp_custom = (tp_params->custom_pattern[17] << 16) | (tp_params->custom_pattern[16] << 8) | tp_params->custom_pattern[15];
223 REG_SET(DP_DPHY_SYM32_TP_CUSTOM5, 0, TP_CUSTOM, tp_custom);
224 tp_custom = (tp_params->custom_pattern[20] << 16) | (tp_params->custom_pattern[19] << 8) | tp_params->custom_pattern[18];
225 REG_SET(DP_DPHY_SYM32_TP_CUSTOM6, 0, TP_CUSTOM, tp_custom);
226 tp_custom = (tp_params->custom_pattern[23] << 16) | (tp_params->custom_pattern[22] << 8) | tp_params->custom_pattern[21];
227 REG_SET(DP_DPHY_SYM32_TP_CUSTOM7, 0, TP_CUSTOM, tp_custom);
228 tp_custom = (tp_params->custom_pattern[26] << 16) | (tp_params->custom_pattern[25] << 8) | tp_params->custom_pattern[24];
229 REG_SET(DP_DPHY_SYM32_TP_CUSTOM8, 0, TP_CUSTOM, tp_custom);
230 tp_custom = (tp_params->custom_pattern[29] << 16) | (tp_params->custom_pattern[28] << 8) | tp_params->custom_pattern[27];
231 REG_SET(DP_DPHY_SYM32_TP_CUSTOM9, 0, TP_CUSTOM, tp_custom);
232 tp_custom = (tp_params->custom_pattern[32] << 16) | (tp_params->custom_pattern[31] << 8) | tp_params->custom_pattern[30];
233 REG_SET(DP_DPHY_SYM32_TP_CUSTOM10, 0, TP_CUSTOM, tp_custom);
234
235 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
236 TP_SELECT0, DP_DPHY_TP_SELECT_CUSTOM,
237 TP_SELECT1, DP_DPHY_TP_SELECT_CUSTOM,
238 TP_SELECT2, DP_DPHY_TP_SELECT_CUSTOM,
239 TP_SELECT3, DP_DPHY_TP_SELECT_CUSTOM);
240
241 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
242 MODE, DP2_TEST_PATTERN);
243 break;
244 case DP_TEST_PATTERN_SQUARE:
245 case DP_TEST_PATTERN_SQUARE_PRESHOOT_DISABLED:
246 case DP_TEST_PATTERN_SQUARE_DEEMPHASIS_DISABLED:
247 case DP_TEST_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED:
248 REG_SET(DP_DPHY_SYM32_TP_SQ_PULSE, 0,
249 TP_SQ_PULSE_WIDTH, tp_params->custom_pattern[0]);
250
251 REG_UPDATE_4(DP_DPHY_SYM32_TP_CONFIG,
252 TP_SELECT0, DP_DPHY_TP_SELECT_SQUARE,
253 TP_SELECT1, DP_DPHY_TP_SELECT_SQUARE,
254 TP_SELECT2, DP_DPHY_TP_SELECT_SQUARE,
255 TP_SELECT3, DP_DPHY_TP_SELECT_SQUARE);
256
257 REG_UPDATE(DP_DPHY_SYM32_CONTROL,
258 MODE, DP2_TEST_PATTERN);
259 break;
260 default:
261 break;
262 }
263}
264
265static void fill_stream_allocation_row_info(
266 const struct link_mst_stream_allocation *stream_allocation,
267 uint32_t *src,
268 uint32_t *slots)
269{
270 const struct hpo_dp_stream_encoder *stream_enc = stream_allocation->hpo_dp_stream_enc;
271
272 if (stream_enc && (stream_enc->id >= ENGINE_ID_HPO_DP_0)) {
273 *src = stream_enc->id - ENGINE_ID_HPO_DP_0;
274 *slots = stream_allocation->slot_count;
275 } else {
276 *src = 0;
277 *slots = 0;
278 }
279}
280
281/* programs DP VC payload allocation */
282void dcn31_hpo_dp_link_enc_update_stream_allocation_table(
283 struct hpo_dp_link_encoder *enc,
284 const struct link_mst_stream_allocation_table *table)
285{
286 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
287 uint32_t slots = 0;
288 uint32_t src = 0;
289
290 /* --- Set MSE Stream Attribute -
291 * Setup VC Payload Table on Tx Side,
292 * Issue allocation change trigger
293 * to commit payload on both tx and rx side
294 */
295
296 /* we should clean-up table each time */
297
298 if (table->stream_count >= 1) {
299 fill_stream_allocation_row_info(
300 stream_allocation: &table->stream_allocations[0],
301 src: &src,
302 slots: &slots);
303 } else {
304 src = 0;
305 slots = 0;
306 }
307
308 REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC0,
309 SAT_STREAM_SOURCE, src,
310 SAT_SLOT_COUNT, slots);
311
312 if (table->stream_count >= 2) {
313 fill_stream_allocation_row_info(
314 stream_allocation: &table->stream_allocations[1],
315 src: &src,
316 slots: &slots);
317 } else {
318 src = 0;
319 slots = 0;
320 }
321
322 REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC1,
323 SAT_STREAM_SOURCE, src,
324 SAT_SLOT_COUNT, slots);
325
326 if (table->stream_count >= 3) {
327 fill_stream_allocation_row_info(
328 stream_allocation: &table->stream_allocations[2],
329 src: &src,
330 slots: &slots);
331 } else {
332 src = 0;
333 slots = 0;
334 }
335
336 REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC2,
337 SAT_STREAM_SOURCE, src,
338 SAT_SLOT_COUNT, slots);
339
340 if (table->stream_count >= 4) {
341 fill_stream_allocation_row_info(
342 stream_allocation: &table->stream_allocations[3],
343 src: &src,
344 slots: &slots);
345 } else {
346 src = 0;
347 slots = 0;
348 }
349
350 REG_UPDATE_2(DP_DPHY_SYM32_SAT_VC3,
351 SAT_STREAM_SOURCE, src,
352 SAT_SLOT_COUNT, slots);
353
354 /* --- wait for transaction finish */
355
356 /* send allocation change trigger (ACT)
357 * this step first sends the ACT,
358 * then double buffers the SAT into the hardware
359 * making the new allocation active on the DP MST mode link
360 */
361
362 /* SAT_UPDATE:
363 * 0 - No Action
364 * 1 - Update SAT with trigger
365 * 2 - Update SAT without trigger
366 */
367 REG_UPDATE(DP_DPHY_SYM32_SAT_UPDATE,
368 SAT_UPDATE, 1);
369
370 /* wait for update to complete
371 * (i.e. SAT_UPDATE_PENDING field is set to 0)
372 * No need for HW to enforce keepout.
373 */
374 /* Best case and worst case wait time for SAT_UPDATE_PENDING
375 * best: 109 us
376 * worst: 868 us
377 */
378 REG_WAIT(DP_DPHY_SYM32_STATUS,
379 SAT_UPDATE_PENDING, 0,
380 10, DP_SAT_UPDATE_MAX_RETRY);
381}
382
383void dcn31_hpo_dp_link_enc_set_throttled_vcp_size(
384 struct hpo_dp_link_encoder *enc,
385 uint32_t stream_encoder_inst,
386 struct fixed31_32 avg_time_slots_per_mtp)
387{
388 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
389 uint32_t x = dc_fixpt_floor(
390 arg: avg_time_slots_per_mtp);
391 uint32_t y = dc_fixpt_ceil(
392 arg: dc_fixpt_shl(
393 arg: dc_fixpt_sub_int(
394 arg1: avg_time_slots_per_mtp,
395 arg2: x),
396 shift: 25));
397
398 switch (stream_encoder_inst) {
399 case 0:
400 REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0,
401 STREAM_VC_RATE_X, x,
402 STREAM_VC_RATE_Y, y);
403 break;
404 case 1:
405 REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL1, 0,
406 STREAM_VC_RATE_X, x,
407 STREAM_VC_RATE_Y, y);
408 break;
409 case 2:
410 REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL2, 0,
411 STREAM_VC_RATE_X, x,
412 STREAM_VC_RATE_Y, y);
413 break;
414 case 3:
415 REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL3, 0,
416 STREAM_VC_RATE_X, x,
417 STREAM_VC_RATE_Y, y);
418 break;
419 default:
420 ASSERT(0);
421 }
422
423 /* Best case and worst case wait time for RATE_UPDATE_PENDING
424 * best: 116 ns
425 * worst: 903 ns
426 */
427 /* wait for update to be completed on the link */
428 REG_WAIT(DP_DPHY_SYM32_STATUS,
429 RATE_UPDATE_PENDING, 0,
430 1, 10);
431}
432
433static bool dcn31_hpo_dp_link_enc_is_in_alt_mode(
434 struct hpo_dp_link_encoder *enc)
435{
436 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
437 uint32_t dp_alt_mode_disable = 0;
438
439 ASSERT((enc->transmitter >= TRANSMITTER_UNIPHY_A) && (enc->transmitter <= TRANSMITTER_UNIPHY_E));
440
441 /* if value == 1 alt mode is disabled, otherwise it is enabled */
442 REG_GET(RDPCSTX_PHY_CNTL6[enc->transmitter], RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
443 return (dp_alt_mode_disable == 0);
444}
445
446void dcn31_hpo_dp_link_enc_read_state(
447 struct hpo_dp_link_encoder *enc,
448 struct hpo_dp_link_enc_state *state)
449{
450 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
451
452 ASSERT(state);
453
454 REG_GET(DP_DPHY_SYM32_STATUS,
455 STATUS, &state->link_enc_enabled);
456 REG_GET(DP_DPHY_SYM32_CONTROL,
457 NUM_LANES, &state->lane_count);
458 REG_GET(DP_DPHY_SYM32_CONTROL,
459 MODE, (uint32_t *)&state->link_mode);
460
461 REG_GET_2(DP_DPHY_SYM32_SAT_VC0,
462 SAT_STREAM_SOURCE, &state->stream_src[0],
463 SAT_SLOT_COUNT, &state->slot_count[0]);
464 REG_GET_2(DP_DPHY_SYM32_SAT_VC1,
465 SAT_STREAM_SOURCE, &state->stream_src[1],
466 SAT_SLOT_COUNT, &state->slot_count[1]);
467 REG_GET_2(DP_DPHY_SYM32_SAT_VC2,
468 SAT_STREAM_SOURCE, &state->stream_src[2],
469 SAT_SLOT_COUNT, &state->slot_count[2]);
470 REG_GET_2(DP_DPHY_SYM32_SAT_VC3,
471 SAT_STREAM_SOURCE, &state->stream_src[3],
472 SAT_SLOT_COUNT, &state->slot_count[3]);
473
474 REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL0,
475 STREAM_VC_RATE_X, &state->vc_rate_x[0],
476 STREAM_VC_RATE_Y, &state->vc_rate_y[0]);
477 REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL1,
478 STREAM_VC_RATE_X, &state->vc_rate_x[1],
479 STREAM_VC_RATE_Y, &state->vc_rate_y[1]);
480 REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL2,
481 STREAM_VC_RATE_X, &state->vc_rate_x[2],
482 STREAM_VC_RATE_Y, &state->vc_rate_y[2]);
483 REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL3,
484 STREAM_VC_RATE_X, &state->vc_rate_x[3],
485 STREAM_VC_RATE_Y, &state->vc_rate_y[3]);
486}
487
488static enum bp_result link_transmitter_control(
489 struct dcn31_hpo_dp_link_encoder *enc3,
490 struct bp_transmitter_control *cntl)
491{
492 enum bp_result result;
493 struct dc_bios *bp = enc3->base.ctx->dc_bios;
494
495 result = bp->funcs->transmitter_control(bp, cntl);
496
497 return result;
498}
499
500/* enables DP PHY output for 128b132b encoding */
501void dcn31_hpo_dp_link_enc_enable_dp_output(
502 struct hpo_dp_link_encoder *enc,
503 const struct dc_link_settings *link_settings,
504 enum transmitter transmitter,
505 enum hpd_source_id hpd_source)
506{
507 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
508 struct bp_transmitter_control cntl = { 0 };
509 enum bp_result result;
510
511 /* Set the transmitter */
512 enc3->base.transmitter = transmitter;
513
514 /* Set the hpd source */
515 enc3->base.hpd_source = hpd_source;
516
517 /* Enable the PHY */
518 cntl.action = TRANSMITTER_CONTROL_ENABLE;
519 cntl.engine_id = ENGINE_ID_UNKNOWN;
520 cntl.transmitter = enc3->base.transmitter;
521 //cntl.pll_id = clock_source;
522 cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
523 cntl.lanes_number = link_settings->lane_count;
524 cntl.hpd_sel = enc3->base.hpd_source;
525 cntl.pixel_clock = link_settings->link_rate * 1000;
526 cntl.color_depth = COLOR_DEPTH_UNDEFINED;
527 cntl.hpo_engine_id = enc->inst + ENGINE_ID_HPO_DP_0;
528
529 result = link_transmitter_control(enc3, cntl: &cntl);
530
531 if (result != BP_RESULT_OK) {
532 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
533 __func__);
534 BREAK_TO_DEBUGGER();
535 }
536}
537
538void dcn31_hpo_dp_link_enc_disable_output(
539 struct hpo_dp_link_encoder *enc,
540 enum signal_type signal)
541{
542 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
543 struct bp_transmitter_control cntl = { 0 };
544 enum bp_result result;
545
546 /* disable transmitter */
547 cntl.action = TRANSMITTER_CONTROL_DISABLE;
548 cntl.transmitter = enc3->base.transmitter;
549 cntl.hpd_sel = enc3->base.hpd_source;
550 cntl.signal = signal;
551
552 result = link_transmitter_control(enc3, cntl: &cntl);
553
554 if (result != BP_RESULT_OK) {
555 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
556 __func__);
557 BREAK_TO_DEBUGGER();
558 return;
559 }
560
561 /* disable encoder */
562 dcn31_hpo_dp_link_enc_disable(enc);
563}
564
565void dcn31_hpo_dp_link_enc_set_ffe(
566 struct hpo_dp_link_encoder *enc,
567 const struct dc_link_settings *link_settings,
568 uint8_t ffe_preset)
569{
570 struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
571 struct bp_transmitter_control cntl = { 0 };
572 enum bp_result result;
573
574 /* disable transmitter */
575 cntl.transmitter = enc3->base.transmitter;
576 cntl.action = TRANSMITTER_CONTROL_SET_VOLTAGE_AND_PREEMPASIS;
577 cntl.signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
578 cntl.lanes_number = link_settings->lane_count;
579 cntl.pixel_clock = link_settings->link_rate * 1000;
580 cntl.lane_settings = ffe_preset;
581
582 result = link_transmitter_control(enc3, cntl: &cntl);
583
584 if (result != BP_RESULT_OK) {
585 DC_LOG_ERROR("%s: Failed to execute VBIOS command table!\n",
586 __func__);
587 BREAK_TO_DEBUGGER();
588 return;
589 }
590}
591
592static struct hpo_dp_link_encoder_funcs dcn31_hpo_dp_link_encoder_funcs = {
593 .enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output,
594 .disable_link_phy = dcn31_hpo_dp_link_enc_disable_output,
595 .link_enable = dcn31_hpo_dp_link_enc_enable,
596 .link_disable = dcn31_hpo_dp_link_enc_disable,
597 .set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern,
598 .update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table,
599 .set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size,
600 .is_in_alt_mode = dcn31_hpo_dp_link_enc_is_in_alt_mode,
601 .read_state = dcn31_hpo_dp_link_enc_read_state,
602 .set_ffe = dcn31_hpo_dp_link_enc_set_ffe,
603};
604
605void hpo_dp_link_encoder31_construct(struct dcn31_hpo_dp_link_encoder *enc31,
606 struct dc_context *ctx,
607 uint32_t inst,
608 const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
609 const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
610 const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask)
611{
612 enc31->base.ctx = ctx;
613
614 enc31->base.inst = inst;
615 enc31->base.funcs = &dcn31_hpo_dp_link_encoder_funcs;
616 enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN;
617 enc31->base.transmitter = TRANSMITTER_UNKNOWN;
618
619 enc31->regs = hpo_le_regs;
620 enc31->hpo_le_shift = hpo_le_shift;
621 enc31->hpo_le_mask = hpo_le_mask;
622}
623

source code of linux/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c