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