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 | |
45 | enum { |
46 | DP_SAT_UPDATE_MAX_RETRY = 200 |
47 | }; |
48 | |
49 | void 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 | |
76 | void 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 | |
89 | void 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 | |
265 | static 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 */ |
282 | void 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 | |
383 | void 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 | |
433 | static 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 | |
446 | void 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 | |
488 | static 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 */ |
501 | void 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 | |
538 | void 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 | |
565 | void 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 | |
592 | static 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 | |
605 | void 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 | |