1 | /* |
2 | * Copyright 2020 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 | |
27 | #include "dc_bios_types.h" |
28 | #include "dcn30_dio_stream_encoder.h" |
29 | #include "reg_helper.h" |
30 | #include "hw_shared.h" |
31 | #include "dc.h" |
32 | #include "core_types.h" |
33 | #include <linux/delay.h> |
34 | |
35 | |
36 | #define DC_LOGGER \ |
37 | enc1->base.ctx->logger |
38 | |
39 | #define REG(reg)\ |
40 | (enc1->regs->reg) |
41 | |
42 | #undef FN |
43 | #define FN(reg_name, field_name) \ |
44 | enc1->se_shift->field_name, enc1->se_mask->field_name |
45 | |
46 | #define VBI_LINE_0 0 |
47 | #define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000 |
48 | |
49 | #define CTX \ |
50 | enc1->base.ctx |
51 | |
52 | |
53 | static void enc3_update_hdmi_info_packet( |
54 | struct dcn10_stream_encoder *enc1, |
55 | uint32_t packet_index, |
56 | const struct dc_info_packet *info_packet) |
57 | { |
58 | uint32_t cont, send, line; |
59 | |
60 | if (info_packet->valid) { |
61 | enc1->base.vpg->funcs->update_generic_info_packet( |
62 | enc1->base.vpg, |
63 | packet_index, |
64 | info_packet, |
65 | true); |
66 | |
67 | /* enable transmission of packet(s) - |
68 | * packet transmission begins on the next frame */ |
69 | cont = 1; |
70 | /* send packet(s) every frame */ |
71 | send = 1; |
72 | /* select line number to send packets on */ |
73 | line = 2; |
74 | } else { |
75 | cont = 0; |
76 | send = 0; |
77 | line = 0; |
78 | } |
79 | |
80 | /* DP_SEC_GSP[x]_LINE_REFERENCE - keep default value REFER_TO_DP_SOF */ |
81 | |
82 | /* choose which generic packet control to use */ |
83 | switch (packet_index) { |
84 | case 0: |
85 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, |
86 | HDMI_GENERIC0_CONT, cont, |
87 | HDMI_GENERIC0_SEND, send); |
88 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, |
89 | HDMI_GENERIC0_LINE, line); |
90 | break; |
91 | case 1: |
92 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, |
93 | HDMI_GENERIC1_CONT, cont, |
94 | HDMI_GENERIC1_SEND, send); |
95 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL1, |
96 | HDMI_GENERIC1_LINE, line); |
97 | break; |
98 | case 2: |
99 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, |
100 | HDMI_GENERIC2_CONT, cont, |
101 | HDMI_GENERIC2_SEND, send); |
102 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, |
103 | HDMI_GENERIC2_LINE, line); |
104 | break; |
105 | case 3: |
106 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, |
107 | HDMI_GENERIC3_CONT, cont, |
108 | HDMI_GENERIC3_SEND, send); |
109 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL2, |
110 | HDMI_GENERIC3_LINE, line); |
111 | break; |
112 | case 4: |
113 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, |
114 | HDMI_GENERIC4_CONT, cont, |
115 | HDMI_GENERIC4_SEND, send); |
116 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, |
117 | HDMI_GENERIC4_LINE, line); |
118 | break; |
119 | case 5: |
120 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, |
121 | HDMI_GENERIC5_CONT, cont, |
122 | HDMI_GENERIC5_SEND, send); |
123 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL3, |
124 | HDMI_GENERIC5_LINE, line); |
125 | break; |
126 | case 6: |
127 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, |
128 | HDMI_GENERIC6_CONT, cont, |
129 | HDMI_GENERIC6_SEND, send); |
130 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, |
131 | HDMI_GENERIC6_LINE, line); |
132 | break; |
133 | case 7: |
134 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL0, |
135 | HDMI_GENERIC7_CONT, cont, |
136 | HDMI_GENERIC7_SEND, send); |
137 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL4, |
138 | HDMI_GENERIC7_LINE, line); |
139 | break; |
140 | case 8: |
141 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, |
142 | HDMI_GENERIC8_CONT, cont, |
143 | HDMI_GENERIC8_SEND, send); |
144 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, |
145 | HDMI_GENERIC8_LINE, line); |
146 | break; |
147 | case 9: |
148 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, |
149 | HDMI_GENERIC9_CONT, cont, |
150 | HDMI_GENERIC9_SEND, send); |
151 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL7, |
152 | HDMI_GENERIC9_LINE, line); |
153 | break; |
154 | case 10: |
155 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, |
156 | HDMI_GENERIC10_CONT, cont, |
157 | HDMI_GENERIC10_SEND, send); |
158 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, |
159 | HDMI_GENERIC10_LINE, line); |
160 | break; |
161 | case 11: |
162 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, |
163 | HDMI_GENERIC11_CONT, cont, |
164 | HDMI_GENERIC11_SEND, send); |
165 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL8, |
166 | HDMI_GENERIC11_LINE, line); |
167 | break; |
168 | case 12: |
169 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, |
170 | HDMI_GENERIC12_CONT, cont, |
171 | HDMI_GENERIC12_SEND, send); |
172 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, |
173 | HDMI_GENERIC12_LINE, line); |
174 | break; |
175 | case 13: |
176 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, |
177 | HDMI_GENERIC13_CONT, cont, |
178 | HDMI_GENERIC13_SEND, send); |
179 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL9, |
180 | HDMI_GENERIC13_LINE, line); |
181 | break; |
182 | case 14: |
183 | REG_UPDATE_2(HDMI_GENERIC_PACKET_CONTROL6, |
184 | HDMI_GENERIC14_CONT, cont, |
185 | HDMI_GENERIC14_SEND, send); |
186 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, |
187 | HDMI_GENERIC14_LINE, line); |
188 | break; |
189 | default: |
190 | /* invalid HW packet index */ |
191 | DC_LOG_WARNING( |
192 | "Invalid HW packet index: %s()\n" , |
193 | __func__); |
194 | return; |
195 | } |
196 | } |
197 | |
198 | void enc3_stream_encoder_update_hdmi_info_packets( |
199 | struct stream_encoder *enc, |
200 | const struct encoder_info_frame *info_frame) |
201 | { |
202 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
203 | |
204 | /* for bring up, disable dp double TODO */ |
205 | REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1); |
206 | REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); |
207 | |
208 | /*Always add mandatory packets first followed by optional ones*/ |
209 | enc3_update_hdmi_info_packet(enc1, packet_index: 0, info_packet: &info_frame->avi); |
210 | enc3_update_hdmi_info_packet(enc1, packet_index: 5, info_packet: &info_frame->hfvsif); |
211 | enc3_update_hdmi_info_packet(enc1, packet_index: 2, info_packet: &info_frame->gamut); |
212 | enc3_update_hdmi_info_packet(enc1, packet_index: 1, info_packet: &info_frame->vendor); |
213 | enc3_update_hdmi_info_packet(enc1, packet_index: 3, info_packet: &info_frame->spd); |
214 | enc3_update_hdmi_info_packet(enc1, packet_index: 4, info_packet: &info_frame->hdrsmd); |
215 | enc3_update_hdmi_info_packet(enc1, packet_index: 6, info_packet: &info_frame->vtem); |
216 | } |
217 | |
218 | void enc3_stream_encoder_stop_hdmi_info_packets( |
219 | struct stream_encoder *enc) |
220 | { |
221 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
222 | |
223 | /* stop generic packets 0,1 on HDMI */ |
224 | REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, |
225 | HDMI_GENERIC0_CONT, 0, |
226 | HDMI_GENERIC0_SEND, 0, |
227 | HDMI_GENERIC1_CONT, 0, |
228 | HDMI_GENERIC1_SEND, 0); |
229 | REG_SET_2(HDMI_GENERIC_PACKET_CONTROL1, 0, |
230 | HDMI_GENERIC0_LINE, 0, |
231 | HDMI_GENERIC1_LINE, 0); |
232 | |
233 | /* stop generic packets 2,3 on HDMI */ |
234 | REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, |
235 | HDMI_GENERIC2_CONT, 0, |
236 | HDMI_GENERIC2_SEND, 0, |
237 | HDMI_GENERIC3_CONT, 0, |
238 | HDMI_GENERIC3_SEND, 0); |
239 | REG_SET_2(HDMI_GENERIC_PACKET_CONTROL2, 0, |
240 | HDMI_GENERIC2_LINE, 0, |
241 | HDMI_GENERIC3_LINE, 0); |
242 | |
243 | /* stop generic packets 4,5 on HDMI */ |
244 | REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, |
245 | HDMI_GENERIC4_CONT, 0, |
246 | HDMI_GENERIC4_SEND, 0, |
247 | HDMI_GENERIC5_CONT, 0, |
248 | HDMI_GENERIC5_SEND, 0); |
249 | REG_SET_2(HDMI_GENERIC_PACKET_CONTROL3, 0, |
250 | HDMI_GENERIC4_LINE, 0, |
251 | HDMI_GENERIC5_LINE, 0); |
252 | |
253 | /* stop generic packets 6,7 on HDMI */ |
254 | REG_SET_4(HDMI_GENERIC_PACKET_CONTROL0, 0, |
255 | HDMI_GENERIC6_CONT, 0, |
256 | HDMI_GENERIC6_SEND, 0, |
257 | HDMI_GENERIC7_CONT, 0, |
258 | HDMI_GENERIC7_SEND, 0); |
259 | REG_SET_2(HDMI_GENERIC_PACKET_CONTROL4, 0, |
260 | HDMI_GENERIC6_LINE, 0, |
261 | HDMI_GENERIC7_LINE, 0); |
262 | |
263 | /* stop generic packets 8,9 on HDMI */ |
264 | REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, |
265 | HDMI_GENERIC8_CONT, 0, |
266 | HDMI_GENERIC8_SEND, 0, |
267 | HDMI_GENERIC9_CONT, 0, |
268 | HDMI_GENERIC9_SEND, 0); |
269 | REG_SET_2(HDMI_GENERIC_PACKET_CONTROL7, 0, |
270 | HDMI_GENERIC8_LINE, 0, |
271 | HDMI_GENERIC9_LINE, 0); |
272 | |
273 | /* stop generic packets 10,11 on HDMI */ |
274 | REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, |
275 | HDMI_GENERIC10_CONT, 0, |
276 | HDMI_GENERIC10_SEND, 0, |
277 | HDMI_GENERIC11_CONT, 0, |
278 | HDMI_GENERIC11_SEND, 0); |
279 | REG_SET_2(HDMI_GENERIC_PACKET_CONTROL8, 0, |
280 | HDMI_GENERIC10_LINE, 0, |
281 | HDMI_GENERIC11_LINE, 0); |
282 | |
283 | /* stop generic packets 12,13 on HDMI */ |
284 | REG_SET_4(HDMI_GENERIC_PACKET_CONTROL6, 0, |
285 | HDMI_GENERIC12_CONT, 0, |
286 | HDMI_GENERIC12_SEND, 0, |
287 | HDMI_GENERIC13_CONT, 0, |
288 | HDMI_GENERIC13_SEND, 0); |
289 | REG_SET_2(HDMI_GENERIC_PACKET_CONTROL9, 0, |
290 | HDMI_GENERIC12_LINE, 0, |
291 | HDMI_GENERIC13_LINE, 0); |
292 | |
293 | /* stop generic packet 14 on HDMI */ |
294 | REG_SET_2(HDMI_GENERIC_PACKET_CONTROL6, 0, |
295 | HDMI_GENERIC14_CONT, 0, |
296 | HDMI_GENERIC14_SEND, 0); |
297 | REG_UPDATE(HDMI_GENERIC_PACKET_CONTROL10, |
298 | HDMI_GENERIC14_LINE, 0); |
299 | } |
300 | |
301 | /* Set DSC-related configuration. |
302 | * dsc_mode: 0 disables DSC, other values enable DSC in specified format |
303 | * sc_bytes_per_pixel: Bytes per pixel in u3.28 format |
304 | * dsc_slice_width: Slice width in pixels |
305 | */ |
306 | static void enc3_dp_set_dsc_config(struct stream_encoder *enc, |
307 | enum optc_dsc_mode dsc_mode, |
308 | uint32_t dsc_bytes_per_pixel, |
309 | uint32_t dsc_slice_width) |
310 | { |
311 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
312 | |
313 | REG_UPDATE_2(DP_DSC_CNTL, |
314 | DP_DSC_MODE, dsc_mode, |
315 | DP_DSC_SLICE_WIDTH, dsc_slice_width); |
316 | |
317 | REG_SET(DP_DSC_BYTES_PER_PIXEL, 0, |
318 | DP_DSC_BYTES_PER_PIXEL, dsc_bytes_per_pixel); |
319 | } |
320 | |
321 | |
322 | void enc3_dp_set_dsc_pps_info_packet(struct stream_encoder *enc, |
323 | bool enable, |
324 | uint8_t *dsc_packed_pps, |
325 | bool immediate_update) |
326 | { |
327 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
328 | |
329 | if (enable) { |
330 | struct dc_info_packet pps_sdp; |
331 | int i; |
332 | |
333 | /* Configure for PPS packet size (128 bytes) */ |
334 | REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1); |
335 | |
336 | /* We need turn on clock before programming AFMT block |
337 | * |
338 | * TODO: We may not need this here anymore since update_generic_info_packet |
339 | * no longer touches AFMT |
340 | */ |
341 | REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1); |
342 | |
343 | /* Load PPS into infoframe (SDP) registers */ |
344 | pps_sdp.valid = true; |
345 | pps_sdp.hb0 = 0; |
346 | pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; |
347 | pps_sdp.hb2 = 127; |
348 | pps_sdp.hb3 = 0; |
349 | |
350 | for (i = 0; i < 4; i++) { |
351 | memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); |
352 | enc1->base.vpg->funcs->update_generic_info_packet( |
353 | enc1->base.vpg, |
354 | 11 + i, |
355 | &pps_sdp, |
356 | immediate_update); |
357 | } |
358 | |
359 | /* SW should make sure VBID[6] update line number is bigger |
360 | * than PPS transmit line number |
361 | */ |
362 | REG_UPDATE(DP_GSP11_CNTL, |
363 | DP_SEC_GSP11_LINE_NUM, 2); |
364 | REG_UPDATE_2(DP_MSA_VBID_MISC, |
365 | DP_VBID6_LINE_REFERENCE, 0, |
366 | DP_VBID6_LINE_NUM, 3); |
367 | |
368 | /* Send PPS data at the line number specified above. |
369 | * DP spec requires PPS to be sent only when it changes, however since |
370 | * decoder has to be able to handle its change on every frame, we're |
371 | * sending it always (i.e. on every frame) to reduce the chance it'd be |
372 | * missed by decoder. If it turns out required to send PPS only when it |
373 | * changes, we can use DP_SEC_GSP11_SEND register. |
374 | */ |
375 | REG_UPDATE(DP_GSP11_CNTL, |
376 | DP_SEC_GSP11_ENABLE, 1); |
377 | REG_UPDATE(DP_SEC_CNTL, |
378 | DP_SEC_STREAM_ENABLE, 1); |
379 | } else { |
380 | /* Disable Generic Stream Packet 11 (GSP) transmission */ |
381 | REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0); |
382 | REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0); |
383 | } |
384 | } |
385 | |
386 | |
387 | /* this function read dsc related register fields to be logged later in dcn10_log_hw_state |
388 | * into a dcn_dsc_state struct. |
389 | */ |
390 | static void enc3_read_state(struct stream_encoder *enc, struct enc_state *s) |
391 | { |
392 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
393 | |
394 | //if dsc is enabled, continue to read |
395 | REG_GET(DP_DSC_CNTL, DP_DSC_MODE, &s->dsc_mode); |
396 | if (s->dsc_mode) { |
397 | REG_GET(DP_DSC_CNTL, DP_DSC_SLICE_WIDTH, &s->dsc_slice_width); |
398 | REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, &s->sec_gsp_pps_line_num); |
399 | |
400 | REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, &s->vbid6_line_reference); |
401 | REG_GET(DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, &s->vbid6_line_num); |
402 | |
403 | REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, &s->sec_gsp_pps_enable); |
404 | REG_GET(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, &s->sec_stream_enable); |
405 | } |
406 | } |
407 | |
408 | void enc3_stream_encoder_update_dp_info_packets_sdp_line_num( |
409 | struct stream_encoder *enc, |
410 | struct encoder_info_frame *info_frame) |
411 | { |
412 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
413 | |
414 | if (info_frame->adaptive_sync.valid == true && |
415 | info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { |
416 | //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF |
417 | REG_UPDATE(DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, 1); |
418 | |
419 | REG_UPDATE(DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, |
420 | info_frame->sdp_line_num.adaptive_sync_line_num); |
421 | } |
422 | } |
423 | |
424 | void enc3_stream_encoder_update_dp_info_packets( |
425 | struct stream_encoder *enc, |
426 | const struct encoder_info_frame *info_frame) |
427 | { |
428 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
429 | uint32_t value = 0; |
430 | uint32_t dmdata_packet_enabled = 0; |
431 | |
432 | if (info_frame->vsc.valid) { |
433 | enc->vpg->funcs->update_generic_info_packet( |
434 | enc->vpg, |
435 | 0, /* packetIndex */ |
436 | &info_frame->vsc, |
437 | true); |
438 | } |
439 | /* TODO: VSC SDP at packetIndex 1 should be retricted only if PSR-SU on. |
440 | * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. |
441 | * In addition, currently the driver check the valid bit then update and |
442 | * send the corresponding Infopacket. For PSR-SU, the SDP only be sent |
443 | * while entering PSR-SU mode. So we need another parameter(e.g. send) |
444 | * in dc_info_packet to indicate which infopacket should be enabled by |
445 | * default here. |
446 | */ |
447 | if (info_frame->vsc.valid) { |
448 | enc->vpg->funcs->update_generic_info_packet( |
449 | enc->vpg, |
450 | 1, /* packetIndex */ |
451 | &info_frame->vsc, |
452 | true); |
453 | } |
454 | /* TODO: VSC SDP at packetIndex 1 should be restricted only if PSR-SU on. |
455 | * There should have another Infopacket type (e.g. vsc_psrsu) for PSR_SU. |
456 | * In addition, currently the driver check the valid bit then update and |
457 | * send the corresponding Infopacket. For PSR-SU, the SDP only be sent |
458 | * while entering PSR-SU mode. So we need another parameter(e.g. send) |
459 | * in dc_info_packet to indicate which infopacket should be enabled by |
460 | * default here. |
461 | */ |
462 | if (info_frame->vsc.valid) { |
463 | enc->vpg->funcs->update_generic_info_packet( |
464 | enc->vpg, |
465 | 1, /* packetIndex */ |
466 | &info_frame->vsc, |
467 | true); |
468 | } |
469 | if (info_frame->spd.valid) { |
470 | enc->vpg->funcs->update_generic_info_packet( |
471 | enc->vpg, |
472 | 2, /* packetIndex */ |
473 | &info_frame->spd, |
474 | true); |
475 | } |
476 | if (info_frame->hdrsmd.valid) { |
477 | enc->vpg->funcs->update_generic_info_packet( |
478 | enc->vpg, |
479 | 3, /* packetIndex */ |
480 | &info_frame->hdrsmd, |
481 | true); |
482 | } |
483 | /* packetIndex 4 is used for send immediate sdp message, and please |
484 | * use other packetIndex (such as 5,6) for other info packet |
485 | */ |
486 | |
487 | if (info_frame->adaptive_sync.valid) |
488 | enc->vpg->funcs->update_generic_info_packet( |
489 | enc->vpg, |
490 | 5, /* packetIndex */ |
491 | &info_frame->adaptive_sync, |
492 | true); |
493 | |
494 | /* enable/disable transmission of packet(s). |
495 | * If enabled, packet transmission begins on the next frame |
496 | */ |
497 | REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, info_frame->vsc.valid); |
498 | REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, info_frame->spd.valid); |
499 | REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, info_frame->hdrsmd.valid); |
500 | REG_UPDATE(DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, info_frame->adaptive_sync.valid); |
501 | |
502 | /* This bit is the master enable bit. |
503 | * When enabling secondary stream engine, |
504 | * this master bit must also be set. |
505 | * This register shared with audio info frame. |
506 | * Therefore we need to enable master bit |
507 | * if at least on of the fields is not 0 |
508 | */ |
509 | value = REG_READ(DP_SEC_CNTL); |
510 | if (value) |
511 | REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); |
512 | |
513 | /* check if dynamic metadata packet transmission is enabled */ |
514 | REG_GET(DP_SEC_METADATA_TRANSMISSION, |
515 | DP_SEC_METADATA_PACKET_ENABLE, &dmdata_packet_enabled); |
516 | |
517 | if (dmdata_packet_enabled) |
518 | REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1); |
519 | } |
520 | |
521 | static void enc3_dp_set_odm_combine( |
522 | struct stream_encoder *enc, |
523 | bool odm_combine) |
524 | { |
525 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
526 | |
527 | REG_UPDATE(DP_PIXEL_FORMAT, DP_PIXEL_COMBINE, odm_combine); |
528 | } |
529 | |
530 | /* setup stream encoder in dvi mode */ |
531 | static void enc3_stream_encoder_dvi_set_stream_attribute( |
532 | struct stream_encoder *enc, |
533 | struct dc_crtc_timing *crtc_timing, |
534 | bool is_dual_link) |
535 | { |
536 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
537 | |
538 | if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { |
539 | struct bp_encoder_control cntl = {0}; |
540 | |
541 | cntl.action = ENCODER_CONTROL_SETUP; |
542 | cntl.engine_id = enc1->base.id; |
543 | cntl.signal = is_dual_link ? |
544 | SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; |
545 | cntl.enable_dp_audio = false; |
546 | cntl.pixel_clock = crtc_timing->pix_clk_100hz / 10; |
547 | cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; |
548 | |
549 | if (enc1->base.bp->funcs->encoder_control( |
550 | enc1->base.bp, &cntl) != BP_RESULT_OK) |
551 | return; |
552 | |
553 | } else { |
554 | |
555 | //Set pattern for clock channel, default vlue 0x63 does not work |
556 | REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); |
557 | |
558 | //DIG_BE_TMDS_DVI_MODE : TMDS-DVI mode is already set in link_encoder_setup |
559 | |
560 | //DIG_SOURCE_SELECT is already set in dig_connect_to_otg |
561 | |
562 | /* set DIG_START to 0x1 to reset FIFO */ |
563 | REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); |
564 | udelay(1); |
565 | |
566 | /* write 0 to take the FIFO out of reset */ |
567 | REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); |
568 | udelay(1); |
569 | } |
570 | |
571 | ASSERT(crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB); |
572 | ASSERT(crtc_timing->display_color_depth == COLOR_DEPTH_888); |
573 | enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); |
574 | } |
575 | |
576 | /* setup stream encoder in hdmi mode */ |
577 | static void enc3_stream_encoder_hdmi_set_stream_attribute( |
578 | struct stream_encoder *enc, |
579 | struct dc_crtc_timing *crtc_timing, |
580 | int actual_pix_clk_khz, |
581 | bool enable_audio) |
582 | { |
583 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
584 | |
585 | if (!enc->ctx->dc->debug.avoid_vbios_exec_table) { |
586 | struct bp_encoder_control cntl = {0}; |
587 | |
588 | cntl.action = ENCODER_CONTROL_SETUP; |
589 | cntl.engine_id = enc1->base.id; |
590 | cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A; |
591 | cntl.enable_dp_audio = enable_audio; |
592 | cntl.pixel_clock = actual_pix_clk_khz; |
593 | cntl.lanes_number = LANE_COUNT_FOUR; |
594 | |
595 | if (enc1->base.bp->funcs->encoder_control( |
596 | enc1->base.bp, &cntl) != BP_RESULT_OK) |
597 | return; |
598 | |
599 | } else { |
600 | |
601 | //Set pattern for clock channel, default vlue 0x63 does not work |
602 | REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F); |
603 | |
604 | //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup |
605 | |
606 | //DIG_SOURCE_SELECT is already set in dig_connect_to_otg |
607 | |
608 | /* set DIG_START to 0x1 to reset FIFO */ |
609 | REG_UPDATE(DIG_FE_CNTL, DIG_START, 1); |
610 | udelay(1); |
611 | |
612 | /* write 0 to take the FIFO out of reset */ |
613 | REG_UPDATE(DIG_FE_CNTL, DIG_START, 0); |
614 | udelay(1); |
615 | } |
616 | |
617 | /* Configure pixel encoding */ |
618 | enc1_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing); |
619 | |
620 | /* setup HDMI engine */ |
621 | REG_UPDATE_6(HDMI_CONTROL, |
622 | HDMI_PACKET_GEN_VERSION, 1, |
623 | HDMI_KEEPOUT_MODE, 1, |
624 | HDMI_DEEP_COLOR_ENABLE, 0, |
625 | HDMI_DATA_SCRAMBLE_EN, 0, |
626 | HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1, |
627 | HDMI_CLOCK_CHANNEL_RATE, 0); |
628 | |
629 | /* Configure color depth */ |
630 | switch (crtc_timing->display_color_depth) { |
631 | case COLOR_DEPTH_888: |
632 | REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0); |
633 | break; |
634 | case COLOR_DEPTH_101010: |
635 | if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { |
636 | REG_UPDATE_2(HDMI_CONTROL, |
637 | HDMI_DEEP_COLOR_DEPTH, 1, |
638 | HDMI_DEEP_COLOR_ENABLE, 0); |
639 | } else { |
640 | REG_UPDATE_2(HDMI_CONTROL, |
641 | HDMI_DEEP_COLOR_DEPTH, 1, |
642 | HDMI_DEEP_COLOR_ENABLE, 1); |
643 | } |
644 | break; |
645 | case COLOR_DEPTH_121212: |
646 | if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { |
647 | REG_UPDATE_2(HDMI_CONTROL, |
648 | HDMI_DEEP_COLOR_DEPTH, 2, |
649 | HDMI_DEEP_COLOR_ENABLE, 0); |
650 | } else { |
651 | REG_UPDATE_2(HDMI_CONTROL, |
652 | HDMI_DEEP_COLOR_DEPTH, 2, |
653 | HDMI_DEEP_COLOR_ENABLE, 1); |
654 | } |
655 | break; |
656 | case COLOR_DEPTH_161616: |
657 | REG_UPDATE_2(HDMI_CONTROL, |
658 | HDMI_DEEP_COLOR_DEPTH, 3, |
659 | HDMI_DEEP_COLOR_ENABLE, 1); |
660 | break; |
661 | default: |
662 | break; |
663 | } |
664 | |
665 | if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) { |
666 | /* enable HDMI data scrambler |
667 | * HDMI_CLOCK_CHANNEL_RATE_MORE_340M |
668 | * Clock channel frequency is 1/4 of character rate. |
669 | */ |
670 | REG_UPDATE_2(HDMI_CONTROL, |
671 | HDMI_DATA_SCRAMBLE_EN, 1, |
672 | HDMI_CLOCK_CHANNEL_RATE, 1); |
673 | } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) { |
674 | |
675 | /* TODO: New feature for DCE11, still need to implement */ |
676 | |
677 | /* enable HDMI data scrambler |
678 | * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE |
679 | * Clock channel frequency is the same |
680 | * as character rate |
681 | */ |
682 | REG_UPDATE_2(HDMI_CONTROL, |
683 | HDMI_DATA_SCRAMBLE_EN, 1, |
684 | HDMI_CLOCK_CHANNEL_RATE, 0); |
685 | } |
686 | |
687 | |
688 | /* Enable transmission of General Control packet on every frame */ |
689 | REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL, |
690 | HDMI_GC_CONT, 1, |
691 | HDMI_GC_SEND, 1, |
692 | HDMI_NULL_SEND, 1); |
693 | |
694 | /* Disable Audio Content Protection packet transmission */ |
695 | REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0); |
696 | |
697 | /* following belongs to audio */ |
698 | /* Enable Audio InfoFrame packet transmission. */ |
699 | REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1); |
700 | |
701 | /* update double-buffered AUDIO_INFO registers immediately */ |
702 | ASSERT (enc->afmt); |
703 | enc->afmt->funcs->audio_info_immediate_update(enc->afmt); |
704 | |
705 | /* Select line number on which to send Audio InfoFrame packets */ |
706 | REG_UPDATE(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, |
707 | VBI_LINE_0 + 2); |
708 | |
709 | /* set HDMI GC AVMUTE */ |
710 | REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0); |
711 | } |
712 | |
713 | void enc3_audio_mute_control( |
714 | struct stream_encoder *enc, |
715 | bool mute) |
716 | { |
717 | ASSERT (enc->afmt); |
718 | enc->afmt->funcs->audio_mute_control(enc->afmt, mute); |
719 | } |
720 | |
721 | void enc3_se_dp_audio_setup( |
722 | struct stream_encoder *enc, |
723 | unsigned int az_inst, |
724 | struct audio_info *info) |
725 | { |
726 | ASSERT (enc->afmt); |
727 | enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); |
728 | } |
729 | |
730 | #define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000 |
731 | #define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1 |
732 | |
733 | static void enc3_se_setup_dp_audio( |
734 | struct stream_encoder *enc) |
735 | { |
736 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
737 | |
738 | /* --- DP Audio packet configurations --- */ |
739 | |
740 | /* ATP Configuration */ |
741 | REG_SET(DP_SEC_AUD_N, 0, |
742 | DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT); |
743 | |
744 | /* Async/auto-calc timestamp mode */ |
745 | REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE, |
746 | DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC); |
747 | |
748 | ASSERT (enc->afmt); |
749 | enc->afmt->funcs->setup_dp_audio(enc->afmt); |
750 | } |
751 | |
752 | void enc3_se_dp_audio_enable( |
753 | struct stream_encoder *enc) |
754 | { |
755 | enc1_se_enable_audio_clock(enc, enable: true); |
756 | enc3_se_setup_dp_audio(enc); |
757 | enc1_se_enable_dp_audio(enc); |
758 | } |
759 | |
760 | static void enc3_se_setup_hdmi_audio( |
761 | struct stream_encoder *enc, |
762 | const struct audio_crtc_info *crtc_info) |
763 | { |
764 | struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); |
765 | |
766 | struct audio_clock_info audio_clock_info = {0}; |
767 | |
768 | /* Setup audio in AFMT - program AFMT block associated with DIO */ |
769 | ASSERT (enc->afmt); |
770 | enc->afmt->funcs->setup_hdmi_audio(enc->afmt); |
771 | |
772 | /* HDMI_AUDIO_PACKET_CONTROL */ |
773 | REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL, |
774 | HDMI_AUDIO_DELAY_EN, 1); |
775 | |
776 | /* HDMI_ACR_PACKET_CONTROL */ |
777 | REG_UPDATE_3(HDMI_ACR_PACKET_CONTROL, |
778 | HDMI_ACR_AUTO_SEND, 1, |
779 | HDMI_ACR_SOURCE, 0, |
780 | HDMI_ACR_AUDIO_PRIORITY, 0); |
781 | |
782 | /* Program audio clock sample/regeneration parameters */ |
783 | get_audio_clock_info(color_depth: crtc_info->color_depth, |
784 | crtc_pixel_clock_100Hz: crtc_info->requested_pixel_clock_100Hz, |
785 | actual_pixel_clock_100Hz: crtc_info->calculated_pixel_clock_100Hz, |
786 | audio_clock_info: &audio_clock_info); |
787 | DC_LOG_HW_AUDIO( |
788 | "\n%s:Input::requested_pixel_clock_100Hz = %d" \ |
789 | "calculated_pixel_clock_100Hz = %d \n" , __func__, \ |
790 | crtc_info->requested_pixel_clock_100Hz, \ |
791 | crtc_info->calculated_pixel_clock_100Hz); |
792 | |
793 | /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */ |
794 | REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz); |
795 | |
796 | /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */ |
797 | REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz); |
798 | |
799 | /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */ |
800 | REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz); |
801 | |
802 | /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */ |
803 | REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz); |
804 | |
805 | /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */ |
806 | REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz); |
807 | |
808 | /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */ |
809 | REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz); |
810 | |
811 | /* Video driver cannot know in advance which sample rate will |
812 | * be used by HD Audio driver |
813 | * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is |
814 | * programmed below in interruppt callback |
815 | */ |
816 | } |
817 | |
818 | void enc3_se_hdmi_audio_setup( |
819 | struct stream_encoder *enc, |
820 | unsigned int az_inst, |
821 | struct audio_info *info, |
822 | struct audio_crtc_info *audio_crtc_info) |
823 | { |
824 | enc1_se_enable_audio_clock(enc, enable: true); |
825 | enc3_se_setup_hdmi_audio(enc, crtc_info: audio_crtc_info); |
826 | ASSERT (enc->afmt); |
827 | enc->afmt->funcs->se_audio_setup(enc->afmt, az_inst, info); |
828 | } |
829 | |
830 | |
831 | static const struct stream_encoder_funcs dcn30_str_enc_funcs = { |
832 | .dp_set_odm_combine = |
833 | enc3_dp_set_odm_combine, |
834 | .dp_set_stream_attribute = |
835 | enc2_stream_encoder_dp_set_stream_attribute, |
836 | .hdmi_set_stream_attribute = |
837 | enc3_stream_encoder_hdmi_set_stream_attribute, |
838 | .dvi_set_stream_attribute = |
839 | enc3_stream_encoder_dvi_set_stream_attribute, |
840 | .set_throttled_vcp_size = |
841 | enc1_stream_encoder_set_throttled_vcp_size, |
842 | .update_hdmi_info_packets = |
843 | enc3_stream_encoder_update_hdmi_info_packets, |
844 | .stop_hdmi_info_packets = |
845 | enc3_stream_encoder_stop_hdmi_info_packets, |
846 | .update_dp_info_packets_sdp_line_num = |
847 | enc3_stream_encoder_update_dp_info_packets_sdp_line_num, |
848 | .update_dp_info_packets = |
849 | enc3_stream_encoder_update_dp_info_packets, |
850 | .stop_dp_info_packets = |
851 | enc1_stream_encoder_stop_dp_info_packets, |
852 | .dp_blank = |
853 | enc1_stream_encoder_dp_blank, |
854 | .dp_unblank = |
855 | enc2_stream_encoder_dp_unblank, |
856 | .audio_mute_control = enc3_audio_mute_control, |
857 | |
858 | .dp_audio_setup = enc3_se_dp_audio_setup, |
859 | .dp_audio_enable = enc3_se_dp_audio_enable, |
860 | .dp_audio_disable = enc1_se_dp_audio_disable, |
861 | |
862 | .hdmi_audio_setup = enc3_se_hdmi_audio_setup, |
863 | .hdmi_audio_disable = enc1_se_hdmi_audio_disable, |
864 | .setup_stereo_sync = enc1_setup_stereo_sync, |
865 | .set_avmute = enc1_stream_encoder_set_avmute, |
866 | .dig_connect_to_otg = enc1_dig_connect_to_otg, |
867 | .dig_source_otg = enc1_dig_source_otg, |
868 | |
869 | .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, |
870 | |
871 | .enc_read_state = enc3_read_state, |
872 | .dp_set_dsc_config = enc3_dp_set_dsc_config, |
873 | .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, |
874 | .set_dynamic_metadata = enc2_set_dynamic_metadata, |
875 | .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, |
876 | |
877 | .get_fifo_cal_average_level = enc2_get_fifo_cal_average_level, |
878 | }; |
879 | |
880 | void dcn30_dio_stream_encoder_construct( |
881 | struct dcn10_stream_encoder *enc1, |
882 | struct dc_context *ctx, |
883 | struct dc_bios *bp, |
884 | enum engine_id eng_id, |
885 | struct vpg *vpg, |
886 | struct afmt *afmt, |
887 | const struct dcn10_stream_enc_registers *regs, |
888 | const struct dcn10_stream_encoder_shift *se_shift, |
889 | const struct dcn10_stream_encoder_mask *se_mask) |
890 | { |
891 | enc1->base.funcs = &dcn30_str_enc_funcs; |
892 | enc1->base.ctx = ctx; |
893 | enc1->base.id = eng_id; |
894 | enc1->base.bp = bp; |
895 | enc1->base.vpg = vpg; |
896 | enc1->base.afmt = afmt; |
897 | enc1->regs = regs; |
898 | enc1->se_shift = se_shift; |
899 | enc1->se_mask = se_mask; |
900 | enc1->base.stream_enc_inst = vpg->inst; |
901 | } |
902 | |
903 | |