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_stream_encoder.h" |
28 | #include "reg_helper.h" |
29 | #include "dc.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_se_shift->field_name, enc3->hpo_se_mask->field_name |
40 | |
41 | #define CTX \ |
42 | enc3->base.ctx |
43 | |
44 | |
45 | enum dp2_pixel_encoding { |
46 | DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444, |
47 | DP_SYM32_ENC_PIXEL_ENCODING_YCBCR422, |
48 | DP_SYM32_ENC_PIXEL_ENCODING_YCBCR420, |
49 | DP_SYM32_ENC_PIXEL_ENCODING_Y_ONLY |
50 | }; |
51 | |
52 | enum dp2_uncompressed_component_depth { |
53 | DP_SYM32_ENC_COMPONENT_DEPTH_6BPC, |
54 | DP_SYM32_ENC_COMPONENT_DEPTH_8BPC, |
55 | DP_SYM32_ENC_COMPONENT_DEPTH_10BPC, |
56 | DP_SYM32_ENC_COMPONENT_DEPTH_12BPC |
57 | }; |
58 | |
59 | |
60 | static void dcn31_hpo_dp_stream_enc_enable_stream( |
61 | struct hpo_dp_stream_encoder *enc) |
62 | { |
63 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
64 | |
65 | /* Enable all clocks in the DP_STREAM_ENC */ |
66 | REG_UPDATE(DP_STREAM_ENC_CLOCK_CONTROL, |
67 | DP_STREAM_ENC_CLOCK_EN, 1); |
68 | |
69 | /* Assert reset to the DP_SYM32_ENC logic */ |
70 | REG_UPDATE(DP_SYM32_ENC_CONTROL, |
71 | DP_SYM32_ENC_RESET, 1); |
72 | /* Wait for reset to complete (to assert) */ |
73 | REG_WAIT(DP_SYM32_ENC_CONTROL, |
74 | DP_SYM32_ENC_RESET_DONE, 1, |
75 | 1, 10); |
76 | |
77 | /* De-assert reset to the DP_SYM32_ENC logic */ |
78 | REG_UPDATE(DP_SYM32_ENC_CONTROL, |
79 | DP_SYM32_ENC_RESET, 0); |
80 | /* Wait for reset to de-assert */ |
81 | REG_WAIT(DP_SYM32_ENC_CONTROL, |
82 | DP_SYM32_ENC_RESET_DONE, 0, |
83 | 1, 10); |
84 | |
85 | /* Enable idle pattern generation */ |
86 | REG_UPDATE(DP_SYM32_ENC_CONTROL, |
87 | DP_SYM32_ENC_ENABLE, 1); |
88 | } |
89 | |
90 | static void dcn31_hpo_dp_stream_enc_dp_unblank( |
91 | struct hpo_dp_stream_encoder *enc, |
92 | uint32_t stream_source) |
93 | { |
94 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
95 | |
96 | /* Set the input mux for video stream source */ |
97 | REG_UPDATE(DP_STREAM_ENC_INPUT_MUX_CONTROL, |
98 | DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, stream_source); |
99 | |
100 | /* Enable video transmission in main framer */ |
101 | REG_UPDATE(DP_SYM32_ENC_VID_STREAM_CONTROL, |
102 | VID_STREAM_ENABLE, 1); |
103 | |
104 | /* Reset and Enable Pixel to Symbol FIFO */ |
105 | REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL, |
106 | PIXEL_TO_SYMBOL_FIFO_RESET, 1); |
107 | REG_WAIT(DP_SYM32_ENC_VID_FIFO_CONTROL, |
108 | PIXEL_TO_SYMBOL_FIFO_RESET_DONE, 1, |
109 | 1, 10); |
110 | REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL, |
111 | PIXEL_TO_SYMBOL_FIFO_RESET, 0); |
112 | REG_WAIT(DP_SYM32_ENC_VID_FIFO_CONTROL, /* Disable Clock Ramp Adjuster FIFO */ |
113 | PIXEL_TO_SYMBOL_FIFO_RESET_DONE, 0, |
114 | 1, 10); |
115 | REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL, |
116 | PIXEL_TO_SYMBOL_FIFO_ENABLE, 1); |
117 | |
118 | /* Reset and Enable Clock Ramp Adjuster FIFO */ |
119 | REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, |
120 | FIFO_RESET, 1); |
121 | REG_WAIT(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, |
122 | FIFO_RESET_DONE, 1, |
123 | 1, 10); |
124 | REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, |
125 | FIFO_RESET, 0); |
126 | REG_WAIT(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, |
127 | FIFO_RESET_DONE, 0, |
128 | 1, 10); |
129 | |
130 | /* For Debug -- Enable CRC */ |
131 | REG_UPDATE_2(DP_SYM32_ENC_VID_CRC_CONTROL, |
132 | CRC_ENABLE, 1, |
133 | CRC_CONT_MODE_ENABLE, 1); |
134 | |
135 | REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, |
136 | FIFO_ENABLE, 1); |
137 | } |
138 | |
139 | static void dcn31_hpo_dp_stream_enc_dp_blank( |
140 | struct hpo_dp_stream_encoder *enc) |
141 | { |
142 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
143 | |
144 | /* Disable video transmission */ |
145 | REG_UPDATE(DP_SYM32_ENC_VID_STREAM_CONTROL, |
146 | VID_STREAM_ENABLE, 0); |
147 | |
148 | /* Wait for video stream transmission disabled |
149 | * Larger delay to wait until VBLANK - use max retry of |
150 | * 10us*5000=50ms. This covers 41.7ms of minimum 24 Hz mode + |
151 | * a little more because we may not trust delay accuracy. |
152 | */ |
153 | REG_WAIT(DP_SYM32_ENC_VID_STREAM_CONTROL, |
154 | VID_STREAM_STATUS, 0, |
155 | 10, 5000); |
156 | |
157 | /* Disable SDP transmission */ |
158 | REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, |
159 | SDP_STREAM_ENABLE, 0); |
160 | |
161 | /* Disable Pixel to Symbol FIFO */ |
162 | REG_UPDATE(DP_SYM32_ENC_VID_FIFO_CONTROL, |
163 | PIXEL_TO_SYMBOL_FIFO_ENABLE, 0); |
164 | |
165 | /* Disable Clock Ramp Adjuster FIFO */ |
166 | REG_UPDATE(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, |
167 | FIFO_ENABLE, 0); |
168 | } |
169 | |
170 | static void dcn31_hpo_dp_stream_enc_disable( |
171 | struct hpo_dp_stream_encoder *enc) |
172 | { |
173 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
174 | |
175 | /* Disable DP_SYM32_ENC */ |
176 | REG_UPDATE(DP_SYM32_ENC_CONTROL, |
177 | DP_SYM32_ENC_ENABLE, 0); |
178 | |
179 | /* Disable clocks in the DP_STREAM_ENC */ |
180 | REG_UPDATE(DP_STREAM_ENC_CLOCK_CONTROL, |
181 | DP_STREAM_ENC_CLOCK_EN, 0); |
182 | } |
183 | |
184 | static void dcn31_hpo_dp_stream_enc_set_stream_attribute( |
185 | struct hpo_dp_stream_encoder *enc, |
186 | struct dc_crtc_timing *crtc_timing, |
187 | enum dc_color_space output_color_space, |
188 | bool use_vsc_sdp_for_colorimetry, |
189 | bool compressed_format, |
190 | bool double_buffer_en) |
191 | { |
192 | enum dp2_pixel_encoding pixel_encoding; |
193 | enum dp2_uncompressed_component_depth component_depth; |
194 | uint32_t h_active_start; |
195 | uint32_t v_active_start; |
196 | uint32_t h_blank; |
197 | uint32_t h_back_porch; |
198 | uint32_t h_width; |
199 | uint32_t v_height; |
200 | uint64_t v_freq; |
201 | uint8_t misc0 = 0; |
202 | uint8_t misc1 = 0; |
203 | uint8_t hsp; |
204 | uint8_t vsp; |
205 | |
206 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
207 | struct dc_crtc_timing hw_crtc_timing = *crtc_timing; |
208 | |
209 | /* MISC0[0] = 0 video and link clocks are asynchronous |
210 | * MISC1[0] = 0 interlace not supported |
211 | * MISC1[2:1] = 0 stereo field is handled by hardware |
212 | * MISC1[5:3] = 0 Reserved |
213 | */ |
214 | |
215 | /* Interlaced not supported */ |
216 | if (hw_crtc_timing.flags.INTERLACE) { |
217 | BREAK_TO_DEBUGGER(); |
218 | } |
219 | |
220 | /* Double buffer enable for MSA and pixel format registers |
221 | * Only double buffer for changing stream attributes for active streams |
222 | * Do not double buffer when initially enabling a stream |
223 | */ |
224 | REG_UPDATE(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, |
225 | MSA_DOUBLE_BUFFER_ENABLE, double_buffer_en); |
226 | REG_UPDATE(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, |
227 | PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE, double_buffer_en); |
228 | |
229 | /* Pixel Encoding */ |
230 | switch (hw_crtc_timing.pixel_encoding) { |
231 | case PIXEL_ENCODING_YCBCR422: |
232 | pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_YCBCR422; |
233 | misc0 = misc0 | 0x2; // MISC0[2:1] = 01 |
234 | break; |
235 | case PIXEL_ENCODING_YCBCR444: |
236 | pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444; |
237 | misc0 = misc0 | 0x4; // MISC0[2:1] = 10 |
238 | |
239 | if (hw_crtc_timing.flags.Y_ONLY) { |
240 | pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_Y_ONLY; |
241 | if (hw_crtc_timing.display_color_depth != COLOR_DEPTH_666) { |
242 | /* HW testing only, no use case yet. |
243 | * Color depth of Y-only could be |
244 | * 8, 10, 12, 16 bits |
245 | */ |
246 | misc1 = misc1 | 0x80; // MISC1[7] = 1 |
247 | } |
248 | } |
249 | break; |
250 | case PIXEL_ENCODING_YCBCR420: |
251 | pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_YCBCR420; |
252 | misc1 = misc1 | 0x40; // MISC1[6] = 1 |
253 | break; |
254 | case PIXEL_ENCODING_RGB: |
255 | default: |
256 | pixel_encoding = DP_SYM32_ENC_PIXEL_ENCODING_RGB_YCBCR444; |
257 | break; |
258 | } |
259 | |
260 | /* For YCbCr420 and BT2020 Colorimetry Formats, VSC SDP shall be used. |
261 | * When MISC1, bit 6, is Set to 1, a Source device uses a VSC SDP to indicate the |
262 | * Pixel Encoding/Colorimetry Format and that a Sink device shall ignore MISC1, bit 7, |
263 | * and MISC0, bits 7:1 (MISC1, bit 7, and MISC0, bits 7:1, become "don't care"). |
264 | */ |
265 | if (use_vsc_sdp_for_colorimetry) |
266 | misc1 = misc1 | 0x40; |
267 | else |
268 | misc1 = misc1 & ~0x40; |
269 | |
270 | /* Color depth */ |
271 | switch (hw_crtc_timing.display_color_depth) { |
272 | case COLOR_DEPTH_666: |
273 | component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_6BPC; |
274 | // MISC0[7:5] = 000 |
275 | break; |
276 | case COLOR_DEPTH_888: |
277 | component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_8BPC; |
278 | misc0 = misc0 | 0x20; // MISC0[7:5] = 001 |
279 | break; |
280 | case COLOR_DEPTH_101010: |
281 | component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_10BPC; |
282 | misc0 = misc0 | 0x40; // MISC0[7:5] = 010 |
283 | break; |
284 | case COLOR_DEPTH_121212: |
285 | component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_12BPC; |
286 | misc0 = misc0 | 0x60; // MISC0[7:5] = 011 |
287 | break; |
288 | default: |
289 | component_depth = DP_SYM32_ENC_COMPONENT_DEPTH_6BPC; |
290 | break; |
291 | } |
292 | |
293 | REG_UPDATE_3(DP_SYM32_ENC_VID_PIXEL_FORMAT, |
294 | PIXEL_ENCODING_TYPE, compressed_format, |
295 | UNCOMPRESSED_PIXEL_ENCODING, pixel_encoding, |
296 | UNCOMPRESSED_COMPONENT_DEPTH, component_depth); |
297 | |
298 | switch (output_color_space) { |
299 | case COLOR_SPACE_SRGB: |
300 | misc1 = misc1 & ~0x80; /* bit7 = 0*/ |
301 | break; |
302 | case COLOR_SPACE_SRGB_LIMITED: |
303 | misc0 = misc0 | 0x8; /* bit3=1 */ |
304 | misc1 = misc1 & ~0x80; /* bit7 = 0*/ |
305 | break; |
306 | case COLOR_SPACE_YCBCR601: |
307 | case COLOR_SPACE_YCBCR601_LIMITED: |
308 | misc0 = misc0 | 0x8; /* bit3=1, bit4=0 */ |
309 | misc1 = misc1 & ~0x80; /* bit7 = 0*/ |
310 | if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) |
311 | misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ |
312 | else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) |
313 | misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ |
314 | break; |
315 | case COLOR_SPACE_YCBCR709: |
316 | case COLOR_SPACE_YCBCR709_LIMITED: |
317 | misc0 = misc0 | 0x18; /* bit3=1, bit4=1 */ |
318 | misc1 = misc1 & ~0x80; /* bit7 = 0*/ |
319 | if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) |
320 | misc0 = misc0 | 0x2; /* bit2=0, bit1=1 */ |
321 | else if (hw_crtc_timing.pixel_encoding == PIXEL_ENCODING_YCBCR444) |
322 | misc0 = misc0 | 0x4; /* bit2=1, bit1=0 */ |
323 | break; |
324 | case COLOR_SPACE_2020_RGB_LIMITEDRANGE: |
325 | case COLOR_SPACE_2020_RGB_FULLRANGE: |
326 | case COLOR_SPACE_2020_YCBCR: |
327 | case COLOR_SPACE_XR_RGB: |
328 | case COLOR_SPACE_MSREF_SCRGB: |
329 | case COLOR_SPACE_ADOBERGB: |
330 | case COLOR_SPACE_DCIP3: |
331 | case COLOR_SPACE_XV_YCC_709: |
332 | case COLOR_SPACE_XV_YCC_601: |
333 | case COLOR_SPACE_DISPLAYNATIVE: |
334 | case COLOR_SPACE_DOLBYVISION: |
335 | case COLOR_SPACE_APPCTRL: |
336 | case COLOR_SPACE_CUSTOMPOINTS: |
337 | case COLOR_SPACE_UNKNOWN: |
338 | case COLOR_SPACE_YCBCR709_BLACK: |
339 | /* do nothing */ |
340 | break; |
341 | } |
342 | |
343 | /* calculate from vesa timing parameters |
344 | * h_active_start related to leading edge of sync |
345 | */ |
346 | h_blank = hw_crtc_timing.h_total - hw_crtc_timing.h_border_left - |
347 | hw_crtc_timing.h_addressable - hw_crtc_timing.h_border_right; |
348 | |
349 | h_back_porch = h_blank - hw_crtc_timing.h_front_porch - |
350 | hw_crtc_timing.h_sync_width; |
351 | |
352 | /* start at beginning of left border */ |
353 | h_active_start = hw_crtc_timing.h_sync_width + h_back_porch; |
354 | |
355 | v_active_start = hw_crtc_timing.v_total - hw_crtc_timing.v_border_top - |
356 | hw_crtc_timing.v_addressable - hw_crtc_timing.v_border_bottom - |
357 | hw_crtc_timing.v_front_porch; |
358 | |
359 | h_width = hw_crtc_timing.h_border_left + hw_crtc_timing.h_addressable + hw_crtc_timing.h_border_right; |
360 | v_height = hw_crtc_timing.v_border_top + hw_crtc_timing.v_addressable + hw_crtc_timing.v_border_bottom; |
361 | hsp = hw_crtc_timing.flags.HSYNC_POSITIVE_POLARITY ? 0 : 0x80; |
362 | vsp = hw_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? 0 : 0x80; |
363 | v_freq = (uint64_t)hw_crtc_timing.pix_clk_100hz * 100; |
364 | |
365 | /* MSA Packet Mapping to 32-bit Link Symbols - DP2 spec, section 2.7.4.1 |
366 | * |
367 | * Lane 0 Lane 1 Lane 2 Lane 3 |
368 | * MSA[0] = { 0, 0, 0, VFREQ[47:40]} |
369 | * MSA[1] = { 0, 0, 0, VFREQ[39:32]} |
370 | * MSA[2] = { 0, 0, 0, VFREQ[31:24]} |
371 | * MSA[3] = { HTotal[15:8], HStart[15:8], HWidth[15:8], VFREQ[23:16]} |
372 | * MSA[4] = { HTotal[ 7:0], HStart[ 7:0], HWidth[ 7:0], VFREQ[15: 8]} |
373 | * MSA[5] = { VTotal[15:8], VStart[15:8], VHeight[15:8], VFREQ[ 7: 0]} |
374 | * MSA[6] = { VTotal[ 7:0], VStart[ 7:0], VHeight[ 7:0], MISC0[ 7: 0]} |
375 | * MSA[7] = { HSP|HSW[14:8], VSP|VSW[14:8], 0, MISC1[ 7: 0]} |
376 | * MSA[8] = { HSW[ 7:0], VSW[ 7:0], 0, 0} |
377 | */ |
378 | REG_SET_4(DP_SYM32_ENC_VID_MSA0, 0, |
379 | MSA_DATA_LANE_0, 0, |
380 | MSA_DATA_LANE_1, 0, |
381 | MSA_DATA_LANE_2, 0, |
382 | MSA_DATA_LANE_3, v_freq >> 40); |
383 | |
384 | REG_SET_4(DP_SYM32_ENC_VID_MSA1, 0, |
385 | MSA_DATA_LANE_0, 0, |
386 | MSA_DATA_LANE_1, 0, |
387 | MSA_DATA_LANE_2, 0, |
388 | MSA_DATA_LANE_3, (v_freq >> 32) & 0xff); |
389 | |
390 | REG_SET_4(DP_SYM32_ENC_VID_MSA2, 0, |
391 | MSA_DATA_LANE_0, 0, |
392 | MSA_DATA_LANE_1, 0, |
393 | MSA_DATA_LANE_2, 0, |
394 | MSA_DATA_LANE_3, (v_freq >> 24) & 0xff); |
395 | |
396 | REG_SET_4(DP_SYM32_ENC_VID_MSA3, 0, |
397 | MSA_DATA_LANE_0, hw_crtc_timing.h_total >> 8, |
398 | MSA_DATA_LANE_1, h_active_start >> 8, |
399 | MSA_DATA_LANE_2, h_width >> 8, |
400 | MSA_DATA_LANE_3, (v_freq >> 16) & 0xff); |
401 | |
402 | REG_SET_4(DP_SYM32_ENC_VID_MSA4, 0, |
403 | MSA_DATA_LANE_0, hw_crtc_timing.h_total & 0xff, |
404 | MSA_DATA_LANE_1, h_active_start & 0xff, |
405 | MSA_DATA_LANE_2, h_width & 0xff, |
406 | MSA_DATA_LANE_3, (v_freq >> 8) & 0xff); |
407 | |
408 | REG_SET_4(DP_SYM32_ENC_VID_MSA5, 0, |
409 | MSA_DATA_LANE_0, hw_crtc_timing.v_total >> 8, |
410 | MSA_DATA_LANE_1, v_active_start >> 8, |
411 | MSA_DATA_LANE_2, v_height >> 8, |
412 | MSA_DATA_LANE_3, v_freq & 0xff); |
413 | |
414 | REG_SET_4(DP_SYM32_ENC_VID_MSA6, 0, |
415 | MSA_DATA_LANE_0, hw_crtc_timing.v_total & 0xff, |
416 | MSA_DATA_LANE_1, v_active_start & 0xff, |
417 | MSA_DATA_LANE_2, v_height & 0xff, |
418 | MSA_DATA_LANE_3, misc0); |
419 | |
420 | REG_SET_4(DP_SYM32_ENC_VID_MSA7, 0, |
421 | MSA_DATA_LANE_0, hsp | (hw_crtc_timing.h_sync_width >> 8), |
422 | MSA_DATA_LANE_1, vsp | (hw_crtc_timing.v_sync_width >> 8), |
423 | MSA_DATA_LANE_2, 0, |
424 | MSA_DATA_LANE_3, misc1); |
425 | |
426 | REG_SET_4(DP_SYM32_ENC_VID_MSA8, 0, |
427 | MSA_DATA_LANE_0, hw_crtc_timing.h_sync_width & 0xff, |
428 | MSA_DATA_LANE_1, hw_crtc_timing.v_sync_width & 0xff, |
429 | MSA_DATA_LANE_2, 0, |
430 | MSA_DATA_LANE_3, 0); |
431 | } |
432 | |
433 | static void dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num( |
434 | struct hpo_dp_stream_encoder *enc, |
435 | struct encoder_info_frame *info_frame) |
436 | { |
437 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
438 | |
439 | if (info_frame->adaptive_sync.valid == true && |
440 | info_frame->sdp_line_num.adaptive_sync_line_num_valid == true) { |
441 | //00: REFER_TO_DP_SOF, 01: REFER_TO_OTG_SOF |
442 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, 1); |
443 | |
444 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER, |
445 | info_frame->sdp_line_num.adaptive_sync_line_num); |
446 | } |
447 | } |
448 | |
449 | static void dcn31_hpo_dp_stream_enc_update_dp_info_packets( |
450 | struct hpo_dp_stream_encoder *enc, |
451 | const struct encoder_info_frame *info_frame) |
452 | { |
453 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
454 | uint32_t dmdata_packet_enabled = 0; |
455 | |
456 | if (info_frame->vsc.valid) |
457 | enc->vpg->funcs->update_generic_info_packet( |
458 | enc->vpg, |
459 | 0, /* packetIndex */ |
460 | &info_frame->vsc, |
461 | true); |
462 | |
463 | if (info_frame->spd.valid) |
464 | enc->vpg->funcs->update_generic_info_packet( |
465 | enc->vpg, |
466 | 2, /* packetIndex */ |
467 | &info_frame->spd, |
468 | true); |
469 | |
470 | if (info_frame->hdrsmd.valid) |
471 | enc->vpg->funcs->update_generic_info_packet( |
472 | enc->vpg, |
473 | 3, /* packetIndex */ |
474 | &info_frame->hdrsmd, |
475 | true); |
476 | |
477 | if (info_frame->adaptive_sync.valid) |
478 | enc->vpg->funcs->update_generic_info_packet( |
479 | enc->vpg, |
480 | 5, /* packetIndex */ |
481 | &info_frame->adaptive_sync, |
482 | true); |
483 | |
484 | /* enable/disable transmission of packet(s). |
485 | * If enabled, packet transmission begins on the next frame |
486 | */ |
487 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->vsc.valid); |
488 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->spd.valid); |
489 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->hdrsmd.valid); |
490 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, info_frame->adaptive_sync.valid); |
491 | |
492 | /* check if dynamic metadata packet transmission is enabled */ |
493 | REG_GET(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, |
494 | METADATA_PACKET_ENABLE, &dmdata_packet_enabled); |
495 | |
496 | /* Enable secondary data path */ |
497 | REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, |
498 | SDP_STREAM_ENABLE, 1); |
499 | } |
500 | |
501 | static void dcn31_hpo_dp_stream_enc_stop_dp_info_packets( |
502 | struct hpo_dp_stream_encoder *enc) |
503 | { |
504 | /* stop generic packets on DP */ |
505 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
506 | uint32_t asp_enable = 0; |
507 | uint32_t atp_enable = 0; |
508 | uint32_t aip_enable = 0; |
509 | uint32_t acm_enable = 0; |
510 | |
511 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0); |
512 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0); |
513 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0); |
514 | |
515 | /* Disable secondary data path if audio is also disabled */ |
516 | REG_GET_4(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, |
517 | ASP_ENABLE, &asp_enable, |
518 | ATP_ENABLE, &atp_enable, |
519 | AIP_ENABLE, &aip_enable, |
520 | ACM_ENABLE, &acm_enable); |
521 | if (!(asp_enable || atp_enable || aip_enable || acm_enable)) |
522 | REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, |
523 | SDP_STREAM_ENABLE, 0); |
524 | } |
525 | |
526 | static uint32_t hpo_dp_is_gsp_enabled( |
527 | struct hpo_dp_stream_encoder *enc) |
528 | { |
529 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
530 | uint32_t gsp0_enabled = 0; |
531 | uint32_t gsp2_enabled = 0; |
532 | uint32_t gsp3_enabled = 0; |
533 | uint32_t gsp11_enabled = 0; |
534 | |
535 | REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp0_enabled); |
536 | REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL2, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp2_enabled); |
537 | REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL3, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp3_enabled); |
538 | REG_GET(DP_SYM32_ENC_SDP_GSP_CONTROL11, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, &gsp11_enabled); |
539 | |
540 | return (gsp0_enabled || gsp2_enabled || gsp3_enabled || gsp11_enabled); |
541 | } |
542 | |
543 | static void dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet( |
544 | struct hpo_dp_stream_encoder *enc, |
545 | bool enable, |
546 | uint8_t *dsc_packed_pps, |
547 | bool immediate_update) |
548 | { |
549 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
550 | |
551 | if (enable) { |
552 | struct dc_info_packet pps_sdp; |
553 | int i; |
554 | |
555 | /* Configure for PPS packet size (128 bytes) */ |
556 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL11, |
557 | GSP_PAYLOAD_SIZE, 3); |
558 | |
559 | /* Load PPS into infoframe (SDP) registers */ |
560 | pps_sdp.valid = true; |
561 | pps_sdp.hb0 = 0; |
562 | pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS; |
563 | pps_sdp.hb2 = 127; |
564 | pps_sdp.hb3 = 0; |
565 | |
566 | for (i = 0; i < 4; i++) { |
567 | memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32); |
568 | enc3->base.vpg->funcs->update_generic_info_packet( |
569 | enc3->base.vpg, |
570 | 11 + i, |
571 | &pps_sdp, |
572 | immediate_update); |
573 | } |
574 | |
575 | /* SW should make sure VBID[6] update line number is bigger |
576 | * than PPS transmit line number |
577 | */ |
578 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL11, |
579 | GSP_TRANSMISSION_LINE_NUMBER, 2); |
580 | |
581 | REG_UPDATE_2(DP_SYM32_ENC_VID_VBID_CONTROL, |
582 | VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE, 0, |
583 | VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER, 3); |
584 | |
585 | /* Send PPS data at the line number specified above. */ |
586 | REG_UPDATE(DP_SYM32_ENC_SDP_GSP_CONTROL11, |
587 | GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 1); |
588 | REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, |
589 | SDP_STREAM_ENABLE, 1); |
590 | } else { |
591 | /* Disable Generic Stream Packet 11 (GSP) transmission */ |
592 | REG_UPDATE_2(DP_SYM32_ENC_SDP_GSP_CONTROL11, |
593 | GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, 0, |
594 | GSP_PAYLOAD_SIZE, 0); |
595 | } |
596 | } |
597 | |
598 | static void dcn31_hpo_dp_stream_enc_map_stream_to_link( |
599 | struct hpo_dp_stream_encoder *enc, |
600 | uint32_t stream_enc_inst, |
601 | uint32_t link_enc_inst) |
602 | { |
603 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
604 | |
605 | ASSERT(stream_enc_inst < 4 && link_enc_inst < 2); |
606 | |
607 | switch (stream_enc_inst) { |
608 | case 0: |
609 | REG_UPDATE(DP_STREAM_MAPPER_CONTROL0, |
610 | DP_STREAM_LINK_TARGET, link_enc_inst); |
611 | break; |
612 | case 1: |
613 | REG_UPDATE(DP_STREAM_MAPPER_CONTROL1, |
614 | DP_STREAM_LINK_TARGET, link_enc_inst); |
615 | break; |
616 | case 2: |
617 | REG_UPDATE(DP_STREAM_MAPPER_CONTROL2, |
618 | DP_STREAM_LINK_TARGET, link_enc_inst); |
619 | break; |
620 | case 3: |
621 | REG_UPDATE(DP_STREAM_MAPPER_CONTROL3, |
622 | DP_STREAM_LINK_TARGET, link_enc_inst); |
623 | break; |
624 | } |
625 | } |
626 | |
627 | static void dcn31_hpo_dp_stream_enc_audio_setup( |
628 | struct hpo_dp_stream_encoder *enc, |
629 | unsigned int az_inst, |
630 | struct audio_info *info) |
631 | { |
632 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
633 | |
634 | /* Set the input mux for video stream source */ |
635 | REG_UPDATE(DP_STREAM_ENC_AUDIO_CONTROL, |
636 | DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst); |
637 | |
638 | ASSERT(enc->apg); |
639 | enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info); |
640 | } |
641 | |
642 | static void dcn31_hpo_dp_stream_enc_audio_enable( |
643 | struct hpo_dp_stream_encoder *enc) |
644 | { |
645 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
646 | |
647 | /* Enable Audio packets */ |
648 | REG_UPDATE(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ASP_ENABLE, 1); |
649 | |
650 | /* Program the ATP and AIP next */ |
651 | REG_UPDATE_2(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, |
652 | ATP_ENABLE, 1, |
653 | AIP_ENABLE, 1); |
654 | |
655 | /* Enable secondary data path */ |
656 | REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, |
657 | SDP_STREAM_ENABLE, 1); |
658 | |
659 | /* Enable APG block */ |
660 | enc->apg->funcs->enable_apg(enc->apg); |
661 | } |
662 | |
663 | static void dcn31_hpo_dp_stream_enc_audio_disable( |
664 | struct hpo_dp_stream_encoder *enc) |
665 | { |
666 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
667 | |
668 | /* Disable Audio packets */ |
669 | REG_UPDATE_4(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, |
670 | ASP_ENABLE, 0, |
671 | ATP_ENABLE, 0, |
672 | AIP_ENABLE, 0, |
673 | ACM_ENABLE, 0); |
674 | |
675 | /* Disable STP Stream Enable if other SDP GSP are also disabled */ |
676 | if (!(hpo_dp_is_gsp_enabled(enc))) |
677 | REG_UPDATE(DP_SYM32_ENC_SDP_CONTROL, |
678 | SDP_STREAM_ENABLE, 0); |
679 | |
680 | /* Disable APG block */ |
681 | enc->apg->funcs->disable_apg(enc->apg); |
682 | } |
683 | |
684 | static void dcn31_hpo_dp_stream_enc_read_state( |
685 | struct hpo_dp_stream_encoder *enc, |
686 | struct hpo_dp_stream_encoder_state *s) |
687 | { |
688 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
689 | |
690 | REG_GET(DP_SYM32_ENC_CONTROL, |
691 | DP_SYM32_ENC_ENABLE, &s->stream_enc_enabled); |
692 | REG_GET(DP_SYM32_ENC_VID_STREAM_CONTROL, |
693 | VID_STREAM_ENABLE, &s->vid_stream_enabled); |
694 | REG_GET(DP_STREAM_ENC_INPUT_MUX_CONTROL, |
695 | DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, &s->otg_inst); |
696 | |
697 | REG_GET_3(DP_SYM32_ENC_VID_PIXEL_FORMAT, |
698 | PIXEL_ENCODING_TYPE, &s->compressed_format, |
699 | UNCOMPRESSED_PIXEL_ENCODING, &s->pixel_encoding, |
700 | UNCOMPRESSED_COMPONENT_DEPTH, &s->component_depth); |
701 | |
702 | REG_GET(DP_SYM32_ENC_SDP_CONTROL, |
703 | SDP_STREAM_ENABLE, &s->sdp_enabled); |
704 | |
705 | switch (enc->inst) { |
706 | case 0: |
707 | REG_GET(DP_STREAM_MAPPER_CONTROL0, |
708 | DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc); |
709 | break; |
710 | case 1: |
711 | REG_GET(DP_STREAM_MAPPER_CONTROL1, |
712 | DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc); |
713 | break; |
714 | case 2: |
715 | REG_GET(DP_STREAM_MAPPER_CONTROL2, |
716 | DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc); |
717 | break; |
718 | case 3: |
719 | REG_GET(DP_STREAM_MAPPER_CONTROL3, |
720 | DP_STREAM_LINK_TARGET, &s->mapped_to_link_enc); |
721 | break; |
722 | } |
723 | } |
724 | |
725 | static void dcn31_set_hblank_min_symbol_width( |
726 | struct hpo_dp_stream_encoder *enc, |
727 | uint16_t width) |
728 | { |
729 | struct dcn31_hpo_dp_stream_encoder *enc3 = DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(enc); |
730 | |
731 | REG_SET(DP_SYM32_ENC_HBLANK_CONTROL, 0, |
732 | HBLANK_MINIMUM_SYMBOL_WIDTH, width); |
733 | } |
734 | |
735 | static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = { |
736 | .enable_stream = dcn31_hpo_dp_stream_enc_enable_stream, |
737 | .dp_unblank = dcn31_hpo_dp_stream_enc_dp_unblank, |
738 | .dp_blank = dcn31_hpo_dp_stream_enc_dp_blank, |
739 | .disable = dcn31_hpo_dp_stream_enc_disable, |
740 | .set_stream_attribute = dcn31_hpo_dp_stream_enc_set_stream_attribute, |
741 | .update_dp_info_packets_sdp_line_num = dcn31_hpo_dp_stream_enc_update_dp_info_packets_sdp_line_num, |
742 | .update_dp_info_packets = dcn31_hpo_dp_stream_enc_update_dp_info_packets, |
743 | .stop_dp_info_packets = dcn31_hpo_dp_stream_enc_stop_dp_info_packets, |
744 | .dp_set_dsc_pps_info_packet = dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet, |
745 | .map_stream_to_link = dcn31_hpo_dp_stream_enc_map_stream_to_link, |
746 | .dp_audio_setup = dcn31_hpo_dp_stream_enc_audio_setup, |
747 | .dp_audio_enable = dcn31_hpo_dp_stream_enc_audio_enable, |
748 | .dp_audio_disable = dcn31_hpo_dp_stream_enc_audio_disable, |
749 | .read_state = dcn31_hpo_dp_stream_enc_read_state, |
750 | .set_hblank_min_symbol_width = dcn31_set_hblank_min_symbol_width, |
751 | }; |
752 | |
753 | void dcn31_hpo_dp_stream_encoder_construct( |
754 | struct dcn31_hpo_dp_stream_encoder *enc3, |
755 | struct dc_context *ctx, |
756 | struct dc_bios *bp, |
757 | uint32_t inst, |
758 | enum engine_id eng_id, |
759 | struct vpg *vpg, |
760 | struct apg *apg, |
761 | const struct dcn31_hpo_dp_stream_encoder_registers *regs, |
762 | const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift, |
763 | const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask) |
764 | { |
765 | enc3->base.funcs = &dcn30_str_enc_funcs; |
766 | enc3->base.ctx = ctx; |
767 | enc3->base.inst = inst; |
768 | enc3->base.id = eng_id; |
769 | enc3->base.bp = bp; |
770 | enc3->base.vpg = vpg; |
771 | enc3->base.apg = apg; |
772 | enc3->regs = regs; |
773 | enc3->hpo_se_shift = hpo_se_shift; |
774 | enc3->hpo_se_mask = hpo_se_mask; |
775 | } |
776 | |