1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2016 BayLibre, SAS |
4 | * Author: Neil Armstrong <narmstrong@baylibre.com> |
5 | * Copyright (C) 2015 Amlogic, Inc. All rights reserved. |
6 | */ |
7 | |
8 | #include <linux/bitfield.h> |
9 | #include <linux/export.h> |
10 | #include <linux/iopoll.h> |
11 | |
12 | #include <drm/drm_modes.h> |
13 | |
14 | #include "meson_drv.h" |
15 | #include "meson_registers.h" |
16 | #include "meson_venc.h" |
17 | #include "meson_vpp.h" |
18 | |
19 | /** |
20 | * DOC: Video Encoder |
21 | * |
22 | * VENC Handle the pixels encoding to the output formats. |
23 | * We handle the following encodings : |
24 | * |
25 | * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter |
26 | * - TMDS/HDMI Encoding via ENCI_DIV and ENCP |
27 | * - Setup of more clock rates for HDMI modes |
28 | * |
29 | * What is missing : |
30 | * |
31 | * - LCD Panel encoding via ENCL |
32 | * - TV Panel encoding via ENCT |
33 | * |
34 | * VENC paths : |
35 | * |
36 | * .. code:: |
37 | * |
38 | * _____ _____ ____________________ |
39 | * vd1---| |-| | | VENC /---------|----VDAC |
40 | * vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|-| |
41 | * osd1--| |-| | | \ | X--HDMI-TX |
42 | * osd2--|_____|-|_____| | |\-ENCP--ENCP_DVI-|-| |
43 | * | | | |
44 | * | \--ENCL-----------|----LVDS |
45 | * |____________________| |
46 | * |
47 | * The ENCI is designed for PAl or NTSC encoding and can go through the VDAC |
48 | * directly for CVBS encoding or through the ENCI_DVI encoder for HDMI. |
49 | * The ENCP is designed for Progressive encoding but can also generate |
50 | * 1080i interlaced pixels, and was initially designed to encode pixels for |
51 | * VDAC to output RGB ou YUV analog outputs. |
52 | * It's output is only used through the ENCP_DVI encoder for HDMI. |
53 | * The ENCL LVDS encoder is not implemented. |
54 | * |
55 | * The ENCI and ENCP encoders needs specially defined parameters for each |
56 | * supported mode and thus cannot be determined from standard video timings. |
57 | * |
58 | * The ENCI end ENCP DVI encoders are more generic and can generate any timings |
59 | * from the pixel data generated by ENCI or ENCP, so can use the standard video |
60 | * timings are source for HW parameters. |
61 | */ |
62 | |
63 | /* HHI Registers */ |
64 | #define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */ |
65 | #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ |
66 | #define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbb offset in data sheet */ |
67 | #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ |
68 | #define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbc offset in data sheet */ |
69 | #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */ |
70 | |
71 | struct meson_cvbs_enci_mode meson_cvbs_enci_pal = { |
72 | .mode_tag = MESON_VENC_MODE_CVBS_PAL, |
73 | .hso_begin = 3, |
74 | .hso_end = 129, |
75 | .vso_even = 3, |
76 | .vso_odd = 260, |
77 | .macv_max_amp = 7, |
78 | .video_prog_mode = 0xff, |
79 | .video_mode = 0x13, |
80 | .sch_adjust = 0x28, |
81 | .yc_delay = 0x343, |
82 | .pixel_start = 251, |
83 | .pixel_end = 1691, |
84 | .top_field_line_start = 22, |
85 | .top_field_line_end = 310, |
86 | .bottom_field_line_start = 23, |
87 | .bottom_field_line_end = 311, |
88 | .video_saturation = 9, |
89 | .video_contrast = 0, |
90 | .video_brightness = 0, |
91 | .video_hue = 0, |
92 | .analog_sync_adj = 0x8080, |
93 | }; |
94 | |
95 | struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = { |
96 | .mode_tag = MESON_VENC_MODE_CVBS_NTSC, |
97 | .hso_begin = 5, |
98 | .hso_end = 129, |
99 | .vso_even = 3, |
100 | .vso_odd = 260, |
101 | .macv_max_amp = 0xb, |
102 | .video_prog_mode = 0xf0, |
103 | .video_mode = 0x8, |
104 | .sch_adjust = 0x20, |
105 | .yc_delay = 0x333, |
106 | .pixel_start = 227, |
107 | .pixel_end = 1667, |
108 | .top_field_line_start = 18, |
109 | .top_field_line_end = 258, |
110 | .bottom_field_line_start = 19, |
111 | .bottom_field_line_end = 259, |
112 | .video_saturation = 18, |
113 | .video_contrast = 3, |
114 | .video_brightness = 0, |
115 | .video_hue = 0, |
116 | .analog_sync_adj = 0x9c00, |
117 | }; |
118 | |
119 | union meson_hdmi_venc_mode { |
120 | struct { |
121 | unsigned int mode_tag; |
122 | unsigned int hso_begin; |
123 | unsigned int hso_end; |
124 | unsigned int vso_even; |
125 | unsigned int vso_odd; |
126 | unsigned int macv_max_amp; |
127 | unsigned int video_prog_mode; |
128 | unsigned int video_mode; |
129 | unsigned int sch_adjust; |
130 | unsigned int yc_delay; |
131 | unsigned int pixel_start; |
132 | unsigned int pixel_end; |
133 | unsigned int top_field_line_start; |
134 | unsigned int top_field_line_end; |
135 | unsigned int bottom_field_line_start; |
136 | unsigned int bottom_field_line_end; |
137 | } enci; |
138 | struct { |
139 | unsigned int dvi_settings; |
140 | unsigned int video_mode; |
141 | unsigned int video_mode_adv; |
142 | unsigned int video_prog_mode; |
143 | bool video_prog_mode_present; |
144 | unsigned int video_sync_mode; |
145 | bool video_sync_mode_present; |
146 | unsigned int video_yc_dly; |
147 | bool video_yc_dly_present; |
148 | unsigned int video_rgb_ctrl; |
149 | bool video_rgb_ctrl_present; |
150 | unsigned int video_filt_ctrl; |
151 | bool video_filt_ctrl_present; |
152 | unsigned int video_ofld_voav_ofst; |
153 | bool video_ofld_voav_ofst_present; |
154 | unsigned int yfp1_htime; |
155 | unsigned int yfp2_htime; |
156 | unsigned int max_pxcnt; |
157 | unsigned int hspuls_begin; |
158 | unsigned int hspuls_end; |
159 | unsigned int hspuls_switch; |
160 | unsigned int vspuls_begin; |
161 | unsigned int vspuls_end; |
162 | unsigned int vspuls_bline; |
163 | unsigned int vspuls_eline; |
164 | unsigned int eqpuls_begin; |
165 | bool eqpuls_begin_present; |
166 | unsigned int eqpuls_end; |
167 | bool eqpuls_end_present; |
168 | unsigned int eqpuls_bline; |
169 | bool eqpuls_bline_present; |
170 | unsigned int eqpuls_eline; |
171 | bool eqpuls_eline_present; |
172 | unsigned int havon_begin; |
173 | unsigned int havon_end; |
174 | unsigned int vavon_bline; |
175 | unsigned int vavon_eline; |
176 | unsigned int hso_begin; |
177 | unsigned int hso_end; |
178 | unsigned int vso_begin; |
179 | unsigned int vso_end; |
180 | unsigned int vso_bline; |
181 | unsigned int vso_eline; |
182 | bool vso_eline_present; |
183 | unsigned int sy_val; |
184 | bool sy_val_present; |
185 | unsigned int sy2_val; |
186 | bool sy2_val_present; |
187 | unsigned int max_lncnt; |
188 | } encp; |
189 | }; |
190 | |
191 | static union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = { |
192 | .enci = { |
193 | .hso_begin = 5, |
194 | .hso_end = 129, |
195 | .vso_even = 3, |
196 | .vso_odd = 260, |
197 | .macv_max_amp = 0xb, |
198 | .video_prog_mode = 0xf0, |
199 | .video_mode = 0x8, |
200 | .sch_adjust = 0x20, |
201 | .yc_delay = 0, |
202 | .pixel_start = 227, |
203 | .pixel_end = 1667, |
204 | .top_field_line_start = 18, |
205 | .top_field_line_end = 258, |
206 | .bottom_field_line_start = 19, |
207 | .bottom_field_line_end = 259, |
208 | }, |
209 | }; |
210 | |
211 | static union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = { |
212 | .enci = { |
213 | .hso_begin = 3, |
214 | .hso_end = 129, |
215 | .vso_even = 3, |
216 | .vso_odd = 260, |
217 | .macv_max_amp = 0x7, |
218 | .video_prog_mode = 0xff, |
219 | .video_mode = 0x13, |
220 | .sch_adjust = 0x28, |
221 | .yc_delay = 0x333, |
222 | .pixel_start = 251, |
223 | .pixel_end = 1691, |
224 | .top_field_line_start = 22, |
225 | .top_field_line_end = 310, |
226 | .bottom_field_line_start = 23, |
227 | .bottom_field_line_end = 311, |
228 | }, |
229 | }; |
230 | |
231 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = { |
232 | .encp = { |
233 | .dvi_settings = 0x21, |
234 | .video_mode = 0x4000, |
235 | .video_mode_adv = 0x9, |
236 | .video_prog_mode = 0, |
237 | .video_prog_mode_present = true, |
238 | .video_sync_mode = 7, |
239 | .video_sync_mode_present = true, |
240 | /* video_yc_dly */ |
241 | /* video_rgb_ctrl */ |
242 | .video_filt_ctrl = 0x2052, |
243 | .video_filt_ctrl_present = true, |
244 | /* video_ofld_voav_ofst */ |
245 | .yfp1_htime = 244, |
246 | .yfp2_htime = 1630, |
247 | .max_pxcnt = 1715, |
248 | .hspuls_begin = 0x22, |
249 | .hspuls_end = 0xa0, |
250 | .hspuls_switch = 88, |
251 | .vspuls_begin = 0, |
252 | .vspuls_end = 1589, |
253 | .vspuls_bline = 0, |
254 | .vspuls_eline = 5, |
255 | .havon_begin = 249, |
256 | .havon_end = 1689, |
257 | .vavon_bline = 42, |
258 | .vavon_eline = 521, |
259 | /* eqpuls_begin */ |
260 | /* eqpuls_end */ |
261 | /* eqpuls_bline */ |
262 | /* eqpuls_eline */ |
263 | .hso_begin = 3, |
264 | .hso_end = 5, |
265 | .vso_begin = 3, |
266 | .vso_end = 5, |
267 | .vso_bline = 0, |
268 | /* vso_eline */ |
269 | .sy_val = 8, |
270 | .sy_val_present = true, |
271 | .sy2_val = 0x1d8, |
272 | .sy2_val_present = true, |
273 | .max_lncnt = 524, |
274 | }, |
275 | }; |
276 | |
277 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = { |
278 | .encp = { |
279 | .dvi_settings = 0x21, |
280 | .video_mode = 0x4000, |
281 | .video_mode_adv = 0x9, |
282 | .video_prog_mode = 0, |
283 | .video_prog_mode_present = true, |
284 | .video_sync_mode = 7, |
285 | .video_sync_mode_present = true, |
286 | /* video_yc_dly */ |
287 | /* video_rgb_ctrl */ |
288 | .video_filt_ctrl = 0x52, |
289 | .video_filt_ctrl_present = true, |
290 | /* video_ofld_voav_ofst */ |
291 | .yfp1_htime = 235, |
292 | .yfp2_htime = 1674, |
293 | .max_pxcnt = 1727, |
294 | .hspuls_begin = 0, |
295 | .hspuls_end = 0x80, |
296 | .hspuls_switch = 88, |
297 | .vspuls_begin = 0, |
298 | .vspuls_end = 1599, |
299 | .vspuls_bline = 0, |
300 | .vspuls_eline = 4, |
301 | .havon_begin = 235, |
302 | .havon_end = 1674, |
303 | .vavon_bline = 44, |
304 | .vavon_eline = 619, |
305 | /* eqpuls_begin */ |
306 | /* eqpuls_end */ |
307 | /* eqpuls_bline */ |
308 | /* eqpuls_eline */ |
309 | .hso_begin = 0x80, |
310 | .hso_end = 0, |
311 | .vso_begin = 0, |
312 | .vso_end = 5, |
313 | .vso_bline = 0, |
314 | /* vso_eline */ |
315 | .sy_val = 8, |
316 | .sy_val_present = true, |
317 | .sy2_val = 0x1d8, |
318 | .sy2_val_present = true, |
319 | .max_lncnt = 624, |
320 | }, |
321 | }; |
322 | |
323 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = { |
324 | .encp = { |
325 | .dvi_settings = 0x2029, |
326 | .video_mode = 0x4040, |
327 | .video_mode_adv = 0x19, |
328 | /* video_prog_mode */ |
329 | /* video_sync_mode */ |
330 | /* video_yc_dly */ |
331 | /* video_rgb_ctrl */ |
332 | /* video_filt_ctrl */ |
333 | /* video_ofld_voav_ofst */ |
334 | .yfp1_htime = 648, |
335 | .yfp2_htime = 3207, |
336 | .max_pxcnt = 3299, |
337 | .hspuls_begin = 80, |
338 | .hspuls_end = 240, |
339 | .hspuls_switch = 80, |
340 | .vspuls_begin = 688, |
341 | .vspuls_end = 3248, |
342 | .vspuls_bline = 4, |
343 | .vspuls_eline = 8, |
344 | .havon_begin = 648, |
345 | .havon_end = 3207, |
346 | .vavon_bline = 29, |
347 | .vavon_eline = 748, |
348 | /* eqpuls_begin */ |
349 | /* eqpuls_end */ |
350 | /* eqpuls_bline */ |
351 | /* eqpuls_eline */ |
352 | .hso_begin = 256, |
353 | .hso_end = 168, |
354 | .vso_begin = 168, |
355 | .vso_end = 256, |
356 | .vso_bline = 0, |
357 | .vso_eline = 5, |
358 | .vso_eline_present = true, |
359 | /* sy_val */ |
360 | /* sy2_val */ |
361 | .max_lncnt = 749, |
362 | }, |
363 | }; |
364 | |
365 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = { |
366 | .encp = { |
367 | .dvi_settings = 0x202d, |
368 | .video_mode = 0x4040, |
369 | .video_mode_adv = 0x19, |
370 | .video_prog_mode = 0x100, |
371 | .video_prog_mode_present = true, |
372 | .video_sync_mode = 0x407, |
373 | .video_sync_mode_present = true, |
374 | .video_yc_dly = 0, |
375 | .video_yc_dly_present = true, |
376 | /* video_rgb_ctrl */ |
377 | /* video_filt_ctrl */ |
378 | /* video_ofld_voav_ofst */ |
379 | .yfp1_htime = 648, |
380 | .yfp2_htime = 3207, |
381 | .max_pxcnt = 3959, |
382 | .hspuls_begin = 80, |
383 | .hspuls_end = 240, |
384 | .hspuls_switch = 80, |
385 | .vspuls_begin = 688, |
386 | .vspuls_end = 3248, |
387 | .vspuls_bline = 4, |
388 | .vspuls_eline = 8, |
389 | .havon_begin = 648, |
390 | .havon_end = 3207, |
391 | .vavon_bline = 29, |
392 | .vavon_eline = 748, |
393 | /* eqpuls_begin */ |
394 | /* eqpuls_end */ |
395 | /* eqpuls_bline */ |
396 | /* eqpuls_eline */ |
397 | .hso_begin = 128, |
398 | .hso_end = 208, |
399 | .vso_begin = 128, |
400 | .vso_end = 128, |
401 | .vso_bline = 0, |
402 | .vso_eline = 5, |
403 | .vso_eline_present = true, |
404 | /* sy_val */ |
405 | /* sy2_val */ |
406 | .max_lncnt = 749, |
407 | }, |
408 | }; |
409 | |
410 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = { |
411 | .encp = { |
412 | .dvi_settings = 0x2029, |
413 | .video_mode = 0x5ffc, |
414 | .video_mode_adv = 0x19, |
415 | .video_prog_mode = 0x100, |
416 | .video_prog_mode_present = true, |
417 | .video_sync_mode = 0x207, |
418 | .video_sync_mode_present = true, |
419 | /* video_yc_dly */ |
420 | /* video_rgb_ctrl */ |
421 | /* video_filt_ctrl */ |
422 | .video_ofld_voav_ofst = 0x11, |
423 | .video_ofld_voav_ofst_present = true, |
424 | .yfp1_htime = 516, |
425 | .yfp2_htime = 4355, |
426 | .max_pxcnt = 4399, |
427 | .hspuls_begin = 88, |
428 | .hspuls_end = 264, |
429 | .hspuls_switch = 88, |
430 | .vspuls_begin = 440, |
431 | .vspuls_end = 2200, |
432 | .vspuls_bline = 0, |
433 | .vspuls_eline = 4, |
434 | .havon_begin = 516, |
435 | .havon_end = 4355, |
436 | .vavon_bline = 20, |
437 | .vavon_eline = 559, |
438 | .eqpuls_begin = 2288, |
439 | .eqpuls_begin_present = true, |
440 | .eqpuls_end = 2464, |
441 | .eqpuls_end_present = true, |
442 | .eqpuls_bline = 0, |
443 | .eqpuls_bline_present = true, |
444 | .eqpuls_eline = 4, |
445 | .eqpuls_eline_present = true, |
446 | .hso_begin = 264, |
447 | .hso_end = 176, |
448 | .vso_begin = 88, |
449 | .vso_end = 88, |
450 | .vso_bline = 0, |
451 | .vso_eline = 5, |
452 | .vso_eline_present = true, |
453 | /* sy_val */ |
454 | /* sy2_val */ |
455 | .max_lncnt = 1124, |
456 | }, |
457 | }; |
458 | |
459 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = { |
460 | .encp = { |
461 | .dvi_settings = 0x202d, |
462 | .video_mode = 0x5ffc, |
463 | .video_mode_adv = 0x19, |
464 | .video_prog_mode = 0x100, |
465 | .video_prog_mode_present = true, |
466 | .video_sync_mode = 0x7, |
467 | .video_sync_mode_present = true, |
468 | /* video_yc_dly */ |
469 | /* video_rgb_ctrl */ |
470 | /* video_filt_ctrl */ |
471 | .video_ofld_voav_ofst = 0x11, |
472 | .video_ofld_voav_ofst_present = true, |
473 | .yfp1_htime = 526, |
474 | .yfp2_htime = 4365, |
475 | .max_pxcnt = 5279, |
476 | .hspuls_begin = 88, |
477 | .hspuls_end = 264, |
478 | .hspuls_switch = 88, |
479 | .vspuls_begin = 440, |
480 | .vspuls_end = 2200, |
481 | .vspuls_bline = 0, |
482 | .vspuls_eline = 4, |
483 | .havon_begin = 526, |
484 | .havon_end = 4365, |
485 | .vavon_bline = 20, |
486 | .vavon_eline = 559, |
487 | .eqpuls_begin = 2288, |
488 | .eqpuls_begin_present = true, |
489 | .eqpuls_end = 2464, |
490 | .eqpuls_end_present = true, |
491 | .eqpuls_bline = 0, |
492 | .eqpuls_bline_present = true, |
493 | .eqpuls_eline = 4, |
494 | .eqpuls_eline_present = true, |
495 | .hso_begin = 142, |
496 | .hso_end = 230, |
497 | .vso_begin = 142, |
498 | .vso_end = 142, |
499 | .vso_bline = 0, |
500 | .vso_eline = 5, |
501 | .vso_eline_present = true, |
502 | /* sy_val */ |
503 | /* sy2_val */ |
504 | .max_lncnt = 1124, |
505 | }, |
506 | }; |
507 | |
508 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = { |
509 | .encp = { |
510 | .dvi_settings = 0xd, |
511 | .video_mode = 0x4040, |
512 | .video_mode_adv = 0x18, |
513 | .video_prog_mode = 0x100, |
514 | .video_prog_mode_present = true, |
515 | .video_sync_mode = 0x7, |
516 | .video_sync_mode_present = true, |
517 | .video_yc_dly = 0, |
518 | .video_yc_dly_present = true, |
519 | .video_rgb_ctrl = 2, |
520 | .video_rgb_ctrl_present = true, |
521 | .video_filt_ctrl = 0x1052, |
522 | .video_filt_ctrl_present = true, |
523 | /* video_ofld_voav_ofst */ |
524 | .yfp1_htime = 271, |
525 | .yfp2_htime = 2190, |
526 | .max_pxcnt = 2749, |
527 | .hspuls_begin = 44, |
528 | .hspuls_end = 132, |
529 | .hspuls_switch = 44, |
530 | .vspuls_begin = 220, |
531 | .vspuls_end = 2140, |
532 | .vspuls_bline = 0, |
533 | .vspuls_eline = 4, |
534 | .havon_begin = 271, |
535 | .havon_end = 2190, |
536 | .vavon_bline = 41, |
537 | .vavon_eline = 1120, |
538 | /* eqpuls_begin */ |
539 | /* eqpuls_end */ |
540 | .eqpuls_bline = 0, |
541 | .eqpuls_bline_present = true, |
542 | .eqpuls_eline = 4, |
543 | .eqpuls_eline_present = true, |
544 | .hso_begin = 79, |
545 | .hso_end = 123, |
546 | .vso_begin = 79, |
547 | .vso_end = 79, |
548 | .vso_bline = 0, |
549 | .vso_eline = 5, |
550 | .vso_eline_present = true, |
551 | /* sy_val */ |
552 | /* sy2_val */ |
553 | .max_lncnt = 1124, |
554 | }, |
555 | }; |
556 | |
557 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = { |
558 | .encp = { |
559 | .dvi_settings = 0x1, |
560 | .video_mode = 0x4040, |
561 | .video_mode_adv = 0x18, |
562 | .video_prog_mode = 0x100, |
563 | .video_prog_mode_present = true, |
564 | /* video_sync_mode */ |
565 | /* video_yc_dly */ |
566 | /* video_rgb_ctrl */ |
567 | .video_filt_ctrl = 0x1052, |
568 | .video_filt_ctrl_present = true, |
569 | /* video_ofld_voav_ofst */ |
570 | .yfp1_htime = 140, |
571 | .yfp2_htime = 2060, |
572 | .max_pxcnt = 2199, |
573 | .hspuls_begin = 2156, |
574 | .hspuls_end = 44, |
575 | .hspuls_switch = 44, |
576 | .vspuls_begin = 140, |
577 | .vspuls_end = 2059, |
578 | .vspuls_bline = 0, |
579 | .vspuls_eline = 4, |
580 | .havon_begin = 148, |
581 | .havon_end = 2067, |
582 | .vavon_bline = 41, |
583 | .vavon_eline = 1120, |
584 | /* eqpuls_begin */ |
585 | /* eqpuls_end */ |
586 | /* eqpuls_bline */ |
587 | /* eqpuls_eline */ |
588 | .hso_begin = 44, |
589 | .hso_end = 2156, |
590 | .vso_begin = 2100, |
591 | .vso_end = 2164, |
592 | .vso_bline = 0, |
593 | .vso_eline = 5, |
594 | .vso_eline_present = true, |
595 | /* sy_val */ |
596 | /* sy2_val */ |
597 | .max_lncnt = 1124, |
598 | }, |
599 | }; |
600 | |
601 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = { |
602 | .encp = { |
603 | .dvi_settings = 0xd, |
604 | .video_mode = 0x4040, |
605 | .video_mode_adv = 0x18, |
606 | .video_prog_mode = 0x100, |
607 | .video_prog_mode_present = true, |
608 | .video_sync_mode = 0x7, |
609 | .video_sync_mode_present = true, |
610 | .video_yc_dly = 0, |
611 | .video_yc_dly_present = true, |
612 | .video_rgb_ctrl = 2, |
613 | .video_rgb_ctrl_present = true, |
614 | /* video_filt_ctrl */ |
615 | /* video_ofld_voav_ofst */ |
616 | .yfp1_htime = 271, |
617 | .yfp2_htime = 2190, |
618 | .max_pxcnt = 2639, |
619 | .hspuls_begin = 44, |
620 | .hspuls_end = 132, |
621 | .hspuls_switch = 44, |
622 | .vspuls_begin = 220, |
623 | .vspuls_end = 2140, |
624 | .vspuls_bline = 0, |
625 | .vspuls_eline = 4, |
626 | .havon_begin = 271, |
627 | .havon_end = 2190, |
628 | .vavon_bline = 41, |
629 | .vavon_eline = 1120, |
630 | /* eqpuls_begin */ |
631 | /* eqpuls_end */ |
632 | .eqpuls_bline = 0, |
633 | .eqpuls_bline_present = true, |
634 | .eqpuls_eline = 4, |
635 | .eqpuls_eline_present = true, |
636 | .hso_begin = 79, |
637 | .hso_end = 123, |
638 | .vso_begin = 79, |
639 | .vso_end = 79, |
640 | .vso_bline = 0, |
641 | .vso_eline = 5, |
642 | .vso_eline_present = true, |
643 | /* sy_val */ |
644 | /* sy2_val */ |
645 | .max_lncnt = 1124, |
646 | }, |
647 | }; |
648 | |
649 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = { |
650 | .encp = { |
651 | .dvi_settings = 0x1, |
652 | .video_mode = 0x4040, |
653 | .video_mode_adv = 0x18, |
654 | .video_prog_mode = 0x100, |
655 | .video_prog_mode_present = true, |
656 | /* video_sync_mode */ |
657 | /* video_yc_dly */ |
658 | /* video_rgb_ctrl */ |
659 | .video_filt_ctrl = 0x1052, |
660 | .video_filt_ctrl_present = true, |
661 | /* video_ofld_voav_ofst */ |
662 | .yfp1_htime = 140, |
663 | .yfp2_htime = 2060, |
664 | .max_pxcnt = 2199, |
665 | .hspuls_begin = 2156, |
666 | .hspuls_end = 44, |
667 | .hspuls_switch = 44, |
668 | .vspuls_begin = 140, |
669 | .vspuls_end = 2059, |
670 | .vspuls_bline = 0, |
671 | .vspuls_eline = 4, |
672 | .havon_begin = 148, |
673 | .havon_end = 2067, |
674 | .vavon_bline = 41, |
675 | .vavon_eline = 1120, |
676 | /* eqpuls_begin */ |
677 | /* eqpuls_end */ |
678 | /* eqpuls_bline */ |
679 | /* eqpuls_eline */ |
680 | .hso_begin = 44, |
681 | .hso_end = 2156, |
682 | .vso_begin = 2100, |
683 | .vso_end = 2164, |
684 | .vso_bline = 0, |
685 | .vso_eline = 5, |
686 | .vso_eline_present = true, |
687 | /* sy_val */ |
688 | /* sy2_val */ |
689 | .max_lncnt = 1124, |
690 | }, |
691 | }; |
692 | |
693 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = { |
694 | .encp = { |
695 | .dvi_settings = 0x1, |
696 | .video_mode = 0x4040, |
697 | .video_mode_adv = 0x8, |
698 | /* video_sync_mode */ |
699 | /* video_yc_dly */ |
700 | /* video_rgb_ctrl */ |
701 | .video_filt_ctrl = 0x1000, |
702 | .video_filt_ctrl_present = true, |
703 | /* video_ofld_voav_ofst */ |
704 | .yfp1_htime = 140, |
705 | .yfp2_htime = 140+3840, |
706 | .max_pxcnt = 3840+1660-1, |
707 | .hspuls_begin = 2156+1920, |
708 | .hspuls_end = 44, |
709 | .hspuls_switch = 44, |
710 | .vspuls_begin = 140, |
711 | .vspuls_end = 2059+1920, |
712 | .vspuls_bline = 0, |
713 | .vspuls_eline = 4, |
714 | .havon_begin = 148, |
715 | .havon_end = 3987, |
716 | .vavon_bline = 89, |
717 | .vavon_eline = 2248, |
718 | /* eqpuls_begin */ |
719 | /* eqpuls_end */ |
720 | /* eqpuls_bline */ |
721 | /* eqpuls_eline */ |
722 | .hso_begin = 44, |
723 | .hso_end = 2156+1920, |
724 | .vso_begin = 2100+1920, |
725 | .vso_end = 2164+1920, |
726 | .vso_bline = 51, |
727 | .vso_eline = 53, |
728 | .vso_eline_present = true, |
729 | /* sy_val */ |
730 | /* sy2_val */ |
731 | .max_lncnt = 2249, |
732 | }, |
733 | }; |
734 | |
735 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = { |
736 | .encp = { |
737 | .dvi_settings = 0x1, |
738 | .video_mode = 0x4040, |
739 | .video_mode_adv = 0x8, |
740 | /* video_sync_mode */ |
741 | /* video_yc_dly */ |
742 | /* video_rgb_ctrl */ |
743 | .video_filt_ctrl = 0x1000, |
744 | .video_filt_ctrl_present = true, |
745 | /* video_ofld_voav_ofst */ |
746 | .yfp1_htime = 140, |
747 | .yfp2_htime = 140+3840, |
748 | .max_pxcnt = 3840+1440-1, |
749 | .hspuls_begin = 2156+1920, |
750 | .hspuls_end = 44, |
751 | .hspuls_switch = 44, |
752 | .vspuls_begin = 140, |
753 | .vspuls_end = 2059+1920, |
754 | .vspuls_bline = 0, |
755 | .vspuls_eline = 4, |
756 | .havon_begin = 148, |
757 | .havon_end = 3987, |
758 | .vavon_bline = 89, |
759 | .vavon_eline = 2248, |
760 | /* eqpuls_begin */ |
761 | /* eqpuls_end */ |
762 | /* eqpuls_bline */ |
763 | /* eqpuls_eline */ |
764 | .hso_begin = 44, |
765 | .hso_end = 2156+1920, |
766 | .vso_begin = 2100+1920, |
767 | .vso_end = 2164+1920, |
768 | .vso_bline = 51, |
769 | .vso_eline = 53, |
770 | .vso_eline_present = true, |
771 | /* sy_val */ |
772 | /* sy2_val */ |
773 | .max_lncnt = 2249, |
774 | }, |
775 | }; |
776 | |
777 | static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = { |
778 | .encp = { |
779 | .dvi_settings = 0x1, |
780 | .video_mode = 0x4040, |
781 | .video_mode_adv = 0x8, |
782 | /* video_sync_mode */ |
783 | /* video_yc_dly */ |
784 | /* video_rgb_ctrl */ |
785 | .video_filt_ctrl = 0x1000, |
786 | .video_filt_ctrl_present = true, |
787 | /* video_ofld_voav_ofst */ |
788 | .yfp1_htime = 140, |
789 | .yfp2_htime = 140+3840, |
790 | .max_pxcnt = 3840+560-1, |
791 | .hspuls_begin = 2156+1920, |
792 | .hspuls_end = 44, |
793 | .hspuls_switch = 44, |
794 | .vspuls_begin = 140, |
795 | .vspuls_end = 2059+1920, |
796 | .vspuls_bline = 0, |
797 | .vspuls_eline = 4, |
798 | .havon_begin = 148, |
799 | .havon_end = 3987, |
800 | .vavon_bline = 89, |
801 | .vavon_eline = 2248, |
802 | /* eqpuls_begin */ |
803 | /* eqpuls_end */ |
804 | /* eqpuls_bline */ |
805 | /* eqpuls_eline */ |
806 | .hso_begin = 44, |
807 | .hso_end = 2156+1920, |
808 | .vso_begin = 2100+1920, |
809 | .vso_end = 2164+1920, |
810 | .vso_bline = 51, |
811 | .vso_eline = 53, |
812 | .vso_eline_present = true, |
813 | /* sy_val */ |
814 | /* sy2_val */ |
815 | .max_lncnt = 2249, |
816 | }, |
817 | }; |
818 | |
819 | static struct meson_hdmi_venc_vic_mode { |
820 | unsigned int vic; |
821 | union meson_hdmi_venc_mode *mode; |
822 | } meson_hdmi_venc_vic_modes[] = { |
823 | { 6, &meson_hdmi_enci_mode_480i }, |
824 | { 7, &meson_hdmi_enci_mode_480i }, |
825 | { 21, &meson_hdmi_enci_mode_576i }, |
826 | { 22, &meson_hdmi_enci_mode_576i }, |
827 | { 2, &meson_hdmi_encp_mode_480p }, |
828 | { 3, &meson_hdmi_encp_mode_480p }, |
829 | { 17, &meson_hdmi_encp_mode_576p }, |
830 | { 18, &meson_hdmi_encp_mode_576p }, |
831 | { 4, &meson_hdmi_encp_mode_720p60 }, |
832 | { 19, &meson_hdmi_encp_mode_720p50 }, |
833 | { 5, &meson_hdmi_encp_mode_1080i60 }, |
834 | { 20, &meson_hdmi_encp_mode_1080i50 }, |
835 | { 32, &meson_hdmi_encp_mode_1080p24 }, |
836 | { 33, &meson_hdmi_encp_mode_1080p50 }, |
837 | { 34, &meson_hdmi_encp_mode_1080p30 }, |
838 | { 31, &meson_hdmi_encp_mode_1080p50 }, |
839 | { 16, &meson_hdmi_encp_mode_1080p60 }, |
840 | { 93, &meson_hdmi_encp_mode_2160p24 }, |
841 | { 94, &meson_hdmi_encp_mode_2160p25 }, |
842 | { 95, &meson_hdmi_encp_mode_2160p30 }, |
843 | { 96, &meson_hdmi_encp_mode_2160p25 }, |
844 | { 97, &meson_hdmi_encp_mode_2160p30 }, |
845 | { 0, NULL}, /* sentinel */ |
846 | }; |
847 | |
848 | static signed int to_signed(unsigned int a) |
849 | { |
850 | if (a <= 7) |
851 | return a; |
852 | else |
853 | return a - 16; |
854 | } |
855 | |
856 | static unsigned long modulo(unsigned long a, unsigned long b) |
857 | { |
858 | if (a >= b) |
859 | return a - b; |
860 | else |
861 | return a; |
862 | } |
863 | |
864 | enum drm_mode_status |
865 | meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode) |
866 | { |
867 | if (mode->flags & ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC | |
868 | DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC)) |
869 | return MODE_BAD; |
870 | |
871 | if (mode->hdisplay < 400 || mode->hdisplay > 1920) |
872 | return MODE_BAD_HVALUE; |
873 | |
874 | if (mode->vdisplay < 480 || mode->vdisplay > 1920) |
875 | return MODE_BAD_VVALUE; |
876 | |
877 | return MODE_OK; |
878 | } |
879 | EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode); |
880 | |
881 | bool meson_venc_hdmi_supported_vic(int vic) |
882 | { |
883 | struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes; |
884 | |
885 | while (vmode->vic && vmode->mode) { |
886 | if (vmode->vic == vic) |
887 | return true; |
888 | vmode++; |
889 | } |
890 | |
891 | return false; |
892 | } |
893 | EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic); |
894 | |
895 | static void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode, |
896 | union meson_hdmi_venc_mode *dmt_mode) |
897 | { |
898 | memset(dmt_mode, 0, sizeof(*dmt_mode)); |
899 | |
900 | dmt_mode->encp.dvi_settings = 0x21; |
901 | dmt_mode->encp.video_mode = 0x4040; |
902 | dmt_mode->encp.video_mode_adv = 0x18; |
903 | dmt_mode->encp.max_pxcnt = mode->htotal - 1; |
904 | dmt_mode->encp.havon_begin = mode->htotal - mode->hsync_start; |
905 | dmt_mode->encp.havon_end = dmt_mode->encp.havon_begin + |
906 | mode->hdisplay - 1; |
907 | dmt_mode->encp.vavon_bline = mode->vtotal - mode->vsync_start; |
908 | dmt_mode->encp.vavon_eline = dmt_mode->encp.vavon_bline + |
909 | mode->vdisplay - 1; |
910 | dmt_mode->encp.hso_begin = 0; |
911 | dmt_mode->encp.hso_end = mode->hsync_end - mode->hsync_start; |
912 | dmt_mode->encp.vso_begin = 30; |
913 | dmt_mode->encp.vso_end = 50; |
914 | dmt_mode->encp.vso_bline = 0; |
915 | dmt_mode->encp.vso_eline = mode->vsync_end - mode->vsync_start; |
916 | dmt_mode->encp.vso_eline_present = true; |
917 | dmt_mode->encp.max_lncnt = mode->vtotal - 1; |
918 | } |
919 | |
920 | static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic) |
921 | { |
922 | struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes; |
923 | |
924 | while (vmode->vic && vmode->mode) { |
925 | if (vmode->vic == vic) |
926 | return vmode->mode; |
927 | vmode++; |
928 | } |
929 | |
930 | return NULL; |
931 | } |
932 | |
933 | bool meson_venc_hdmi_venc_repeat(int vic) |
934 | { |
935 | /* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */ |
936 | if (vic == 6 || vic == 7 || /* 480i */ |
937 | vic == 21 || vic == 22 || /* 576i */ |
938 | vic == 17 || vic == 18 || /* 576p */ |
939 | vic == 2 || vic == 3 || /* 480p */ |
940 | vic == 4 || /* 720p60 */ |
941 | vic == 19 || /* 720p50 */ |
942 | vic == 5 || /* 1080i60 */ |
943 | vic == 20) /* 1080i50 */ |
944 | return true; |
945 | |
946 | return false; |
947 | } |
948 | EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat); |
949 | |
950 | void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, |
951 | unsigned int ycrcb_map, |
952 | bool yuv420_mode, |
953 | const struct drm_display_mode *mode) |
954 | { |
955 | union meson_hdmi_venc_mode *vmode = NULL; |
956 | union meson_hdmi_venc_mode vmode_dmt; |
957 | bool use_enci = false; |
958 | bool venc_repeat = false; |
959 | bool hdmi_repeat = false; |
960 | unsigned int venc_hdmi_latency = 2; |
961 | unsigned long total_pixels_venc = 0; |
962 | unsigned long active_pixels_venc = 0; |
963 | unsigned long front_porch_venc = 0; |
964 | unsigned long hsync_pixels_venc = 0; |
965 | unsigned long de_h_begin = 0; |
966 | unsigned long de_h_end = 0; |
967 | unsigned long de_v_begin_even = 0; |
968 | unsigned long de_v_end_even = 0; |
969 | unsigned long de_v_begin_odd = 0; |
970 | unsigned long de_v_end_odd = 0; |
971 | unsigned long hs_begin = 0; |
972 | unsigned long hs_end = 0; |
973 | unsigned long vs_adjust = 0; |
974 | unsigned long vs_bline_evn = 0; |
975 | unsigned long vs_eline_evn = 0; |
976 | unsigned long vs_bline_odd = 0; |
977 | unsigned long vs_eline_odd = 0; |
978 | unsigned long vso_begin_evn = 0; |
979 | unsigned long vso_begin_odd = 0; |
980 | unsigned int eof_lines; |
981 | unsigned int sof_lines; |
982 | unsigned int vsync_lines; |
983 | u32 reg; |
984 | |
985 | /* Use VENCI for 480i and 576i and double HDMI pixels */ |
986 | if (mode->flags & DRM_MODE_FLAG_DBLCLK) { |
987 | hdmi_repeat = true; |
988 | use_enci = true; |
989 | venc_hdmi_latency = 1; |
990 | } |
991 | |
992 | if (meson_venc_hdmi_supported_vic(vic)) { |
993 | vmode = meson_venc_hdmi_get_vic_vmode(vic); |
994 | if (!vmode) { |
995 | dev_err(priv->dev, "%s: Fatal Error, unsupported mode " |
996 | DRM_MODE_FMT "\n" , __func__, |
997 | DRM_MODE_ARG(mode)); |
998 | return; |
999 | } |
1000 | } else { |
1001 | meson_venc_hdmi_get_dmt_vmode(mode, dmt_mode: &vmode_dmt); |
1002 | vmode = &vmode_dmt; |
1003 | use_enci = false; |
1004 | } |
1005 | |
1006 | /* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */ |
1007 | if (meson_venc_hdmi_venc_repeat(vic)) |
1008 | venc_repeat = true; |
1009 | |
1010 | eof_lines = mode->vsync_start - mode->vdisplay; |
1011 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
1012 | eof_lines /= 2; |
1013 | sof_lines = mode->vtotal - mode->vsync_end; |
1014 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
1015 | sof_lines /= 2; |
1016 | vsync_lines = mode->vsync_end - mode->vsync_start; |
1017 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
1018 | vsync_lines /= 2; |
1019 | |
1020 | total_pixels_venc = mode->htotal; |
1021 | if (hdmi_repeat) |
1022 | total_pixels_venc /= 2; |
1023 | if (venc_repeat) |
1024 | total_pixels_venc *= 2; |
1025 | |
1026 | active_pixels_venc = mode->hdisplay; |
1027 | if (hdmi_repeat) |
1028 | active_pixels_venc /= 2; |
1029 | if (venc_repeat) |
1030 | active_pixels_venc *= 2; |
1031 | |
1032 | front_porch_venc = (mode->hsync_start - mode->hdisplay); |
1033 | if (hdmi_repeat) |
1034 | front_porch_venc /= 2; |
1035 | if (venc_repeat) |
1036 | front_porch_venc *= 2; |
1037 | |
1038 | hsync_pixels_venc = (mode->hsync_end - mode->hsync_start); |
1039 | if (hdmi_repeat) |
1040 | hsync_pixels_venc /= 2; |
1041 | if (venc_repeat) |
1042 | hsync_pixels_venc *= 2; |
1043 | |
1044 | /* Disable VDACs */ |
1045 | writel_bits_relaxed(0xff, 0xff, |
1046 | priv->io_base + _REG(VENC_VDAC_SETTING)); |
1047 | |
1048 | writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); |
1049 | writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); |
1050 | |
1051 | if (use_enci) { |
1052 | unsigned int lines_f0; |
1053 | unsigned int lines_f1; |
1054 | |
1055 | /* CVBS Filter settings */ |
1056 | writel_relaxed(ENCI_CFILT_CMPT_SEL_HIGH | 0x10, |
1057 | priv->io_base + _REG(ENCI_CFILT_CTRL)); |
1058 | writel_relaxed(ENCI_CFILT_CMPT_CR_DLY(2) | |
1059 | ENCI_CFILT_CMPT_CB_DLY(1), |
1060 | priv->io_base + _REG(ENCI_CFILT_CTRL2)); |
1061 | |
1062 | /* Digital Video Select : Interlace, clk27 clk, external */ |
1063 | writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING)); |
1064 | |
1065 | /* Reset Video Mode */ |
1066 | writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE)); |
1067 | writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); |
1068 | |
1069 | /* Horizontal sync signal output */ |
1070 | writel_relaxed(vmode->enci.hso_begin, |
1071 | priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN)); |
1072 | writel_relaxed(vmode->enci.hso_end, |
1073 | priv->io_base + _REG(ENCI_SYNC_HSO_END)); |
1074 | |
1075 | /* Vertical Sync lines */ |
1076 | writel_relaxed(vmode->enci.vso_even, |
1077 | priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN)); |
1078 | writel_relaxed(vmode->enci.vso_odd, |
1079 | priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN)); |
1080 | |
1081 | /* Macrovision max amplitude change */ |
1082 | writel_relaxed(ENCI_MACV_MAX_AMP_ENABLE_CHANGE | |
1083 | ENCI_MACV_MAX_AMP_VAL(vmode->enci.macv_max_amp), |
1084 | priv->io_base + _REG(ENCI_MACV_MAX_AMP)); |
1085 | |
1086 | /* Video mode */ |
1087 | writel_relaxed(vmode->enci.video_prog_mode, |
1088 | priv->io_base + _REG(VENC_VIDEO_PROG_MODE)); |
1089 | writel_relaxed(vmode->enci.video_mode, |
1090 | priv->io_base + _REG(ENCI_VIDEO_MODE)); |
1091 | |
1092 | /* |
1093 | * Advanced Video Mode : |
1094 | * Demux shifting 0x2 |
1095 | * Blank line end at line17/22 |
1096 | * High bandwidth Luma Filter |
1097 | * Low bandwidth Chroma Filter |
1098 | * Bypass luma low pass filter |
1099 | * No macrovision on CSYNC |
1100 | */ |
1101 | writel_relaxed(ENCI_VIDEO_MODE_ADV_DMXMD(2) | |
1102 | ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 | |
1103 | ENCI_VIDEO_MODE_ADV_YBW_HIGH, |
1104 | priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); |
1105 | |
1106 | writel(val: vmode->enci.sch_adjust, |
1107 | addr: priv->io_base + _REG(ENCI_VIDEO_SCH)); |
1108 | |
1109 | /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */ |
1110 | writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE)); |
1111 | |
1112 | if (vmode->enci.yc_delay) |
1113 | writel_relaxed(vmode->enci.yc_delay, |
1114 | priv->io_base + _REG(ENCI_YC_DELAY)); |
1115 | |
1116 | |
1117 | /* UNreset Interlaced TV Encoder */ |
1118 | writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST)); |
1119 | |
1120 | /* |
1121 | * Enable Vfifo2vd and set Y_Cb_Y_Cr: |
1122 | * Corresponding value: |
1123 | * Y => 00 or 10 |
1124 | * Cb => 01 |
1125 | * Cr => 11 |
1126 | * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y |
1127 | */ |
1128 | writel_relaxed(ENCI_VFIFO2VD_CTL_ENABLE | |
1129 | ENCI_VFIFO2VD_CTL_VD_SEL(0x4e), |
1130 | priv->io_base + _REG(ENCI_VFIFO2VD_CTL)); |
1131 | |
1132 | /* Timings */ |
1133 | writel_relaxed(vmode->enci.pixel_start, |
1134 | priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START)); |
1135 | writel_relaxed(vmode->enci.pixel_end, |
1136 | priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END)); |
1137 | |
1138 | writel_relaxed(vmode->enci.top_field_line_start, |
1139 | priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START)); |
1140 | writel_relaxed(vmode->enci.top_field_line_end, |
1141 | priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END)); |
1142 | |
1143 | writel_relaxed(vmode->enci.bottom_field_line_start, |
1144 | priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START)); |
1145 | writel_relaxed(vmode->enci.bottom_field_line_end, |
1146 | priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END)); |
1147 | |
1148 | /* Select ENCI for VIU */ |
1149 | meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI); |
1150 | |
1151 | /* Interlace video enable */ |
1152 | writel_relaxed(ENCI_VIDEO_EN_ENABLE, |
1153 | priv->io_base + _REG(ENCI_VIDEO_EN)); |
1154 | |
1155 | lines_f0 = mode->vtotal >> 1; |
1156 | lines_f1 = lines_f0 + 1; |
1157 | |
1158 | de_h_begin = modulo(readl_relaxed(priv->io_base + |
1159 | _REG(ENCI_VFIFO2VD_PIXEL_START)) |
1160 | + venc_hdmi_latency, |
1161 | b: total_pixels_venc); |
1162 | de_h_end = modulo(a: de_h_begin + active_pixels_venc, |
1163 | b: total_pixels_venc); |
1164 | |
1165 | writel_relaxed(de_h_begin, |
1166 | priv->io_base + _REG(ENCI_DE_H_BEGIN)); |
1167 | writel_relaxed(de_h_end, |
1168 | priv->io_base + _REG(ENCI_DE_H_END)); |
1169 | |
1170 | de_v_begin_even = readl_relaxed(priv->io_base + |
1171 | _REG(ENCI_VFIFO2VD_LINE_TOP_START)); |
1172 | de_v_end_even = de_v_begin_even + mode->vdisplay; |
1173 | de_v_begin_odd = readl_relaxed(priv->io_base + |
1174 | _REG(ENCI_VFIFO2VD_LINE_BOT_START)); |
1175 | de_v_end_odd = de_v_begin_odd + mode->vdisplay; |
1176 | |
1177 | writel_relaxed(de_v_begin_even, |
1178 | priv->io_base + _REG(ENCI_DE_V_BEGIN_EVEN)); |
1179 | writel_relaxed(de_v_end_even, |
1180 | priv->io_base + _REG(ENCI_DE_V_END_EVEN)); |
1181 | writel_relaxed(de_v_begin_odd, |
1182 | priv->io_base + _REG(ENCI_DE_V_BEGIN_ODD)); |
1183 | writel_relaxed(de_v_end_odd, |
1184 | priv->io_base + _REG(ENCI_DE_V_END_ODD)); |
1185 | |
1186 | /* Program Hsync timing */ |
1187 | hs_begin = de_h_end + front_porch_venc; |
1188 | if (de_h_end + front_porch_venc >= total_pixels_venc) { |
1189 | hs_begin -= total_pixels_venc; |
1190 | vs_adjust = 1; |
1191 | } else { |
1192 | hs_begin = de_h_end + front_porch_venc; |
1193 | vs_adjust = 0; |
1194 | } |
1195 | |
1196 | hs_end = modulo(a: hs_begin + hsync_pixels_venc, |
1197 | b: total_pixels_venc); |
1198 | writel_relaxed(hs_begin, |
1199 | priv->io_base + _REG(ENCI_DVI_HSO_BEGIN)); |
1200 | writel_relaxed(hs_end, |
1201 | priv->io_base + _REG(ENCI_DVI_HSO_END)); |
1202 | |
1203 | /* Program Vsync timing for even field */ |
1204 | if (((de_v_end_odd - 1) + eof_lines + vs_adjust) >= lines_f1) { |
1205 | vs_bline_evn = (de_v_end_odd - 1) |
1206 | + eof_lines |
1207 | + vs_adjust |
1208 | - lines_f1; |
1209 | vs_eline_evn = vs_bline_evn + vsync_lines; |
1210 | |
1211 | writel_relaxed(vs_bline_evn, |
1212 | priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN)); |
1213 | |
1214 | writel_relaxed(vs_eline_evn, |
1215 | priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN)); |
1216 | |
1217 | writel_relaxed(hs_begin, |
1218 | priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_EVN)); |
1219 | writel_relaxed(hs_begin, |
1220 | priv->io_base + _REG(ENCI_DVI_VSO_END_EVN)); |
1221 | } else { |
1222 | vs_bline_odd = (de_v_end_odd - 1) |
1223 | + eof_lines |
1224 | + vs_adjust; |
1225 | |
1226 | writel_relaxed(vs_bline_odd, |
1227 | priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD)); |
1228 | |
1229 | writel_relaxed(hs_begin, |
1230 | priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD)); |
1231 | |
1232 | if ((vs_bline_odd + vsync_lines) >= lines_f1) { |
1233 | vs_eline_evn = vs_bline_odd |
1234 | + vsync_lines |
1235 | - lines_f1; |
1236 | |
1237 | writel_relaxed(vs_eline_evn, priv->io_base |
1238 | + _REG(ENCI_DVI_VSO_ELINE_EVN)); |
1239 | |
1240 | writel_relaxed(hs_begin, priv->io_base |
1241 | + _REG(ENCI_DVI_VSO_END_EVN)); |
1242 | } else { |
1243 | vs_eline_odd = vs_bline_odd |
1244 | + vsync_lines; |
1245 | |
1246 | writel_relaxed(vs_eline_odd, priv->io_base |
1247 | + _REG(ENCI_DVI_VSO_ELINE_ODD)); |
1248 | |
1249 | writel_relaxed(hs_begin, priv->io_base |
1250 | + _REG(ENCI_DVI_VSO_END_ODD)); |
1251 | } |
1252 | } |
1253 | |
1254 | /* Program Vsync timing for odd field */ |
1255 | if (((de_v_end_even - 1) + (eof_lines + 1)) >= lines_f0) { |
1256 | vs_bline_odd = (de_v_end_even - 1) |
1257 | + (eof_lines + 1) |
1258 | - lines_f0; |
1259 | vs_eline_odd = vs_bline_odd + vsync_lines; |
1260 | |
1261 | writel_relaxed(vs_bline_odd, |
1262 | priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD)); |
1263 | |
1264 | writel_relaxed(vs_eline_odd, |
1265 | priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD)); |
1266 | |
1267 | vso_begin_odd = modulo(a: hs_begin |
1268 | + (total_pixels_venc >> 1), |
1269 | b: total_pixels_venc); |
1270 | |
1271 | writel_relaxed(vso_begin_odd, |
1272 | priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD)); |
1273 | writel_relaxed(vso_begin_odd, |
1274 | priv->io_base + _REG(ENCI_DVI_VSO_END_ODD)); |
1275 | } else { |
1276 | vs_bline_evn = (de_v_end_even - 1) |
1277 | + (eof_lines + 1); |
1278 | |
1279 | writel_relaxed(vs_bline_evn, |
1280 | priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN)); |
1281 | |
1282 | vso_begin_evn = modulo(a: hs_begin |
1283 | + (total_pixels_venc >> 1), |
1284 | b: total_pixels_venc); |
1285 | |
1286 | writel_relaxed(vso_begin_evn, priv->io_base |
1287 | + _REG(ENCI_DVI_VSO_BEGIN_EVN)); |
1288 | |
1289 | if (vs_bline_evn + vsync_lines >= lines_f0) { |
1290 | vs_eline_odd = vs_bline_evn |
1291 | + vsync_lines |
1292 | - lines_f0; |
1293 | |
1294 | writel_relaxed(vs_eline_odd, priv->io_base |
1295 | + _REG(ENCI_DVI_VSO_ELINE_ODD)); |
1296 | |
1297 | writel_relaxed(vso_begin_evn, priv->io_base |
1298 | + _REG(ENCI_DVI_VSO_END_ODD)); |
1299 | } else { |
1300 | vs_eline_evn = vs_bline_evn + vsync_lines; |
1301 | |
1302 | writel_relaxed(vs_eline_evn, priv->io_base |
1303 | + _REG(ENCI_DVI_VSO_ELINE_EVN)); |
1304 | |
1305 | writel_relaxed(vso_begin_evn, priv->io_base |
1306 | + _REG(ENCI_DVI_VSO_END_EVN)); |
1307 | } |
1308 | } |
1309 | } else { |
1310 | writel_relaxed(vmode->encp.dvi_settings, |
1311 | priv->io_base + _REG(VENC_DVI_SETTING)); |
1312 | writel_relaxed(vmode->encp.video_mode, |
1313 | priv->io_base + _REG(ENCP_VIDEO_MODE)); |
1314 | writel_relaxed(vmode->encp.video_mode_adv, |
1315 | priv->io_base + _REG(ENCP_VIDEO_MODE_ADV)); |
1316 | if (vmode->encp.video_prog_mode_present) |
1317 | writel_relaxed(vmode->encp.video_prog_mode, |
1318 | priv->io_base + _REG(VENC_VIDEO_PROG_MODE)); |
1319 | if (vmode->encp.video_sync_mode_present) |
1320 | writel_relaxed(vmode->encp.video_sync_mode, |
1321 | priv->io_base + _REG(ENCP_VIDEO_SYNC_MODE)); |
1322 | if (vmode->encp.video_yc_dly_present) |
1323 | writel_relaxed(vmode->encp.video_yc_dly, |
1324 | priv->io_base + _REG(ENCP_VIDEO_YC_DLY)); |
1325 | if (vmode->encp.video_rgb_ctrl_present) |
1326 | writel_relaxed(vmode->encp.video_rgb_ctrl, |
1327 | priv->io_base + _REG(ENCP_VIDEO_RGB_CTRL)); |
1328 | if (vmode->encp.video_filt_ctrl_present) |
1329 | writel_relaxed(vmode->encp.video_filt_ctrl, |
1330 | priv->io_base + _REG(ENCP_VIDEO_FILT_CTRL)); |
1331 | if (vmode->encp.video_ofld_voav_ofst_present) |
1332 | writel_relaxed(vmode->encp.video_ofld_voav_ofst, |
1333 | priv->io_base |
1334 | + _REG(ENCP_VIDEO_OFLD_VOAV_OFST)); |
1335 | writel_relaxed(vmode->encp.yfp1_htime, |
1336 | priv->io_base + _REG(ENCP_VIDEO_YFP1_HTIME)); |
1337 | writel_relaxed(vmode->encp.yfp2_htime, |
1338 | priv->io_base + _REG(ENCP_VIDEO_YFP2_HTIME)); |
1339 | writel_relaxed(vmode->encp.max_pxcnt, |
1340 | priv->io_base + _REG(ENCP_VIDEO_MAX_PXCNT)); |
1341 | writel_relaxed(vmode->encp.hspuls_begin, |
1342 | priv->io_base + _REG(ENCP_VIDEO_HSPULS_BEGIN)); |
1343 | writel_relaxed(vmode->encp.hspuls_end, |
1344 | priv->io_base + _REG(ENCP_VIDEO_HSPULS_END)); |
1345 | writel_relaxed(vmode->encp.hspuls_switch, |
1346 | priv->io_base + _REG(ENCP_VIDEO_HSPULS_SWITCH)); |
1347 | writel_relaxed(vmode->encp.vspuls_begin, |
1348 | priv->io_base + _REG(ENCP_VIDEO_VSPULS_BEGIN)); |
1349 | writel_relaxed(vmode->encp.vspuls_end, |
1350 | priv->io_base + _REG(ENCP_VIDEO_VSPULS_END)); |
1351 | writel_relaxed(vmode->encp.vspuls_bline, |
1352 | priv->io_base + _REG(ENCP_VIDEO_VSPULS_BLINE)); |
1353 | writel_relaxed(vmode->encp.vspuls_eline, |
1354 | priv->io_base + _REG(ENCP_VIDEO_VSPULS_ELINE)); |
1355 | if (vmode->encp.eqpuls_begin_present) |
1356 | writel_relaxed(vmode->encp.eqpuls_begin, |
1357 | priv->io_base + _REG(ENCP_VIDEO_EQPULS_BEGIN)); |
1358 | if (vmode->encp.eqpuls_end_present) |
1359 | writel_relaxed(vmode->encp.eqpuls_end, |
1360 | priv->io_base + _REG(ENCP_VIDEO_EQPULS_END)); |
1361 | if (vmode->encp.eqpuls_bline_present) |
1362 | writel_relaxed(vmode->encp.eqpuls_bline, |
1363 | priv->io_base + _REG(ENCP_VIDEO_EQPULS_BLINE)); |
1364 | if (vmode->encp.eqpuls_eline_present) |
1365 | writel_relaxed(vmode->encp.eqpuls_eline, |
1366 | priv->io_base + _REG(ENCP_VIDEO_EQPULS_ELINE)); |
1367 | writel_relaxed(vmode->encp.havon_begin, |
1368 | priv->io_base + _REG(ENCP_VIDEO_HAVON_BEGIN)); |
1369 | writel_relaxed(vmode->encp.havon_end, |
1370 | priv->io_base + _REG(ENCP_VIDEO_HAVON_END)); |
1371 | writel_relaxed(vmode->encp.vavon_bline, |
1372 | priv->io_base + _REG(ENCP_VIDEO_VAVON_BLINE)); |
1373 | writel_relaxed(vmode->encp.vavon_eline, |
1374 | priv->io_base + _REG(ENCP_VIDEO_VAVON_ELINE)); |
1375 | writel_relaxed(vmode->encp.hso_begin, |
1376 | priv->io_base + _REG(ENCP_VIDEO_HSO_BEGIN)); |
1377 | writel_relaxed(vmode->encp.hso_end, |
1378 | priv->io_base + _REG(ENCP_VIDEO_HSO_END)); |
1379 | writel_relaxed(vmode->encp.vso_begin, |
1380 | priv->io_base + _REG(ENCP_VIDEO_VSO_BEGIN)); |
1381 | writel_relaxed(vmode->encp.vso_end, |
1382 | priv->io_base + _REG(ENCP_VIDEO_VSO_END)); |
1383 | writel_relaxed(vmode->encp.vso_bline, |
1384 | priv->io_base + _REG(ENCP_VIDEO_VSO_BLINE)); |
1385 | if (vmode->encp.vso_eline_present) |
1386 | writel_relaxed(vmode->encp.vso_eline, |
1387 | priv->io_base + _REG(ENCP_VIDEO_VSO_ELINE)); |
1388 | if (vmode->encp.sy_val_present) |
1389 | writel_relaxed(vmode->encp.sy_val, |
1390 | priv->io_base + _REG(ENCP_VIDEO_SY_VAL)); |
1391 | if (vmode->encp.sy2_val_present) |
1392 | writel_relaxed(vmode->encp.sy2_val, |
1393 | priv->io_base + _REG(ENCP_VIDEO_SY2_VAL)); |
1394 | writel_relaxed(vmode->encp.max_lncnt, |
1395 | priv->io_base + _REG(ENCP_VIDEO_MAX_LNCNT)); |
1396 | |
1397 | writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); |
1398 | |
1399 | /* Set DE signal’s polarity is active high */ |
1400 | writel_bits_relaxed(ENCP_VIDEO_MODE_DE_V_HIGH, |
1401 | ENCP_VIDEO_MODE_DE_V_HIGH, |
1402 | priv->io_base + _REG(ENCP_VIDEO_MODE)); |
1403 | |
1404 | /* Program DE timing */ |
1405 | de_h_begin = modulo(readl_relaxed(priv->io_base + |
1406 | _REG(ENCP_VIDEO_HAVON_BEGIN)) |
1407 | + venc_hdmi_latency, |
1408 | b: total_pixels_venc); |
1409 | de_h_end = modulo(a: de_h_begin + active_pixels_venc, |
1410 | b: total_pixels_venc); |
1411 | |
1412 | writel_relaxed(de_h_begin, |
1413 | priv->io_base + _REG(ENCP_DE_H_BEGIN)); |
1414 | writel_relaxed(de_h_end, |
1415 | priv->io_base + _REG(ENCP_DE_H_END)); |
1416 | |
1417 | /* Program DE timing for even field */ |
1418 | de_v_begin_even = readl_relaxed(priv->io_base |
1419 | + _REG(ENCP_VIDEO_VAVON_BLINE)); |
1420 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
1421 | de_v_end_even = de_v_begin_even + |
1422 | (mode->vdisplay / 2); |
1423 | else |
1424 | de_v_end_even = de_v_begin_even + mode->vdisplay; |
1425 | |
1426 | writel_relaxed(de_v_begin_even, |
1427 | priv->io_base + _REG(ENCP_DE_V_BEGIN_EVEN)); |
1428 | writel_relaxed(de_v_end_even, |
1429 | priv->io_base + _REG(ENCP_DE_V_END_EVEN)); |
1430 | |
1431 | /* Program DE timing for odd field if needed */ |
1432 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
1433 | unsigned int ofld_voav_ofst = |
1434 | readl_relaxed(priv->io_base + |
1435 | _REG(ENCP_VIDEO_OFLD_VOAV_OFST)); |
1436 | de_v_begin_odd = to_signed(a: (ofld_voav_ofst & 0xf0) >> 4) |
1437 | + de_v_begin_even |
1438 | + ((mode->vtotal - 1) / 2); |
1439 | de_v_end_odd = de_v_begin_odd + (mode->vdisplay / 2); |
1440 | |
1441 | writel_relaxed(de_v_begin_odd, |
1442 | priv->io_base + _REG(ENCP_DE_V_BEGIN_ODD)); |
1443 | writel_relaxed(de_v_end_odd, |
1444 | priv->io_base + _REG(ENCP_DE_V_END_ODD)); |
1445 | } |
1446 | |
1447 | /* Program Hsync timing */ |
1448 | if ((de_h_end + front_porch_venc) >= total_pixels_venc) { |
1449 | hs_begin = de_h_end |
1450 | + front_porch_venc |
1451 | - total_pixels_venc; |
1452 | vs_adjust = 1; |
1453 | } else { |
1454 | hs_begin = de_h_end |
1455 | + front_porch_venc; |
1456 | vs_adjust = 0; |
1457 | } |
1458 | |
1459 | hs_end = modulo(a: hs_begin + hsync_pixels_venc, |
1460 | b: total_pixels_venc); |
1461 | |
1462 | writel_relaxed(hs_begin, |
1463 | priv->io_base + _REG(ENCP_DVI_HSO_BEGIN)); |
1464 | writel_relaxed(hs_end, |
1465 | priv->io_base + _REG(ENCP_DVI_HSO_END)); |
1466 | |
1467 | /* Program Vsync timing for even field */ |
1468 | if (de_v_begin_even >= |
1469 | (sof_lines + vsync_lines + (1 - vs_adjust))) |
1470 | vs_bline_evn = de_v_begin_even |
1471 | - sof_lines |
1472 | - vsync_lines |
1473 | - (1 - vs_adjust); |
1474 | else |
1475 | vs_bline_evn = mode->vtotal |
1476 | + de_v_begin_even |
1477 | - sof_lines |
1478 | - vsync_lines |
1479 | - (1 - vs_adjust); |
1480 | |
1481 | vs_eline_evn = modulo(a: vs_bline_evn + vsync_lines, |
1482 | b: mode->vtotal); |
1483 | |
1484 | writel_relaxed(vs_bline_evn, |
1485 | priv->io_base + _REG(ENCP_DVI_VSO_BLINE_EVN)); |
1486 | writel_relaxed(vs_eline_evn, |
1487 | priv->io_base + _REG(ENCP_DVI_VSO_ELINE_EVN)); |
1488 | |
1489 | vso_begin_evn = hs_begin; |
1490 | writel_relaxed(vso_begin_evn, |
1491 | priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_EVN)); |
1492 | writel_relaxed(vso_begin_evn, |
1493 | priv->io_base + _REG(ENCP_DVI_VSO_END_EVN)); |
1494 | |
1495 | /* Program Vsync timing for odd field if needed */ |
1496 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) { |
1497 | vs_bline_odd = (de_v_begin_odd - 1) |
1498 | - sof_lines |
1499 | - vsync_lines; |
1500 | vs_eline_odd = (de_v_begin_odd - 1) |
1501 | - vsync_lines; |
1502 | vso_begin_odd = modulo(a: hs_begin |
1503 | + (total_pixels_venc >> 1), |
1504 | b: total_pixels_venc); |
1505 | |
1506 | writel_relaxed(vs_bline_odd, |
1507 | priv->io_base + _REG(ENCP_DVI_VSO_BLINE_ODD)); |
1508 | writel_relaxed(vs_eline_odd, |
1509 | priv->io_base + _REG(ENCP_DVI_VSO_ELINE_ODD)); |
1510 | writel_relaxed(vso_begin_odd, |
1511 | priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_ODD)); |
1512 | writel_relaxed(vso_begin_odd, |
1513 | priv->io_base + _REG(ENCP_DVI_VSO_END_ODD)); |
1514 | } |
1515 | |
1516 | /* Select ENCP for VIU */ |
1517 | meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP); |
1518 | } |
1519 | |
1520 | /* Set VPU HDMI setting */ |
1521 | /* Select ENCP or ENCI data to HDMI */ |
1522 | if (use_enci) |
1523 | reg = VPU_HDMI_ENCI_DATA_TO_HDMI; |
1524 | else |
1525 | reg = VPU_HDMI_ENCP_DATA_TO_HDMI; |
1526 | |
1527 | /* Invert polarity of HSYNC from VENC */ |
1528 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) |
1529 | reg |= VPU_HDMI_INV_HSYNC; |
1530 | |
1531 | /* Invert polarity of VSYNC from VENC */ |
1532 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) |
1533 | reg |= VPU_HDMI_INV_VSYNC; |
1534 | |
1535 | /* Output data format */ |
1536 | reg |= ycrcb_map; |
1537 | |
1538 | /* |
1539 | * Write rate to the async FIFO between VENC and HDMI. |
1540 | * One write every 2 wr_clk. |
1541 | */ |
1542 | if (venc_repeat || yuv420_mode) |
1543 | reg |= VPU_HDMI_WR_RATE(2); |
1544 | |
1545 | /* |
1546 | * Read rate to the async FIFO between VENC and HDMI. |
1547 | * One read every 2 wr_clk. |
1548 | */ |
1549 | if (hdmi_repeat) |
1550 | reg |= VPU_HDMI_RD_RATE(2); |
1551 | |
1552 | writel_relaxed(reg, priv->io_base + _REG(VPU_HDMI_SETTING)); |
1553 | |
1554 | priv->venc.hdmi_repeat = hdmi_repeat; |
1555 | priv->venc.venc_repeat = venc_repeat; |
1556 | priv->venc.hdmi_use_enci = use_enci; |
1557 | |
1558 | priv->venc.current_mode = MESON_VENC_MODE_HDMI; |
1559 | } |
1560 | EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set); |
1561 | |
1562 | static unsigned short meson_encl_gamma_table[256] = { |
1563 | 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, |
1564 | 64, 68, 72, 76, 80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, |
1565 | 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 180, 184, 188, |
1566 | 192, 196, 200, 204, 208, 212, 216, 220, 224, 228, 232, 236, 240, 244, 248, 252, |
1567 | 256, 260, 264, 268, 272, 276, 280, 284, 288, 292, 296, 300, 304, 308, 312, 316, |
1568 | 320, 324, 328, 332, 336, 340, 344, 348, 352, 356, 360, 364, 368, 372, 376, 380, |
1569 | 384, 388, 392, 396, 400, 404, 408, 412, 416, 420, 424, 428, 432, 436, 440, 444, |
1570 | 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, 488, 492, 496, 500, 504, 508, |
1571 | 512, 516, 520, 524, 528, 532, 536, 540, 544, 548, 552, 556, 560, 564, 568, 572, |
1572 | 576, 580, 584, 588, 592, 596, 600, 604, 608, 612, 616, 620, 624, 628, 632, 636, |
1573 | 640, 644, 648, 652, 656, 660, 664, 668, 672, 676, 680, 684, 688, 692, 696, 700, |
1574 | 704, 708, 712, 716, 720, 724, 728, 732, 736, 740, 744, 748, 752, 756, 760, 764, |
1575 | 768, 772, 776, 780, 784, 788, 792, 796, 800, 804, 808, 812, 816, 820, 824, 828, |
1576 | 832, 836, 840, 844, 848, 852, 856, 860, 864, 868, 872, 876, 880, 884, 888, 892, |
1577 | 896, 900, 904, 908, 912, 916, 920, 924, 928, 932, 936, 940, 944, 948, 952, 956, |
1578 | 960, 964, 968, 972, 976, 980, 984, 988, 992, 996, 1000, 1004, 1008, 1012, 1016, 1020, |
1579 | }; |
1580 | |
1581 | static void meson_encl_set_gamma_table(struct meson_drm *priv, u16 *data, |
1582 | u32 rgb_mask) |
1583 | { |
1584 | int i, ret; |
1585 | u32 reg; |
1586 | |
1587 | writel_bits_relaxed(L_GAMMA_CNTL_PORT_EN, 0, |
1588 | priv->io_base + _REG(L_GAMMA_CNTL_PORT)); |
1589 | |
1590 | ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT), |
1591 | reg, reg & L_GAMMA_CNTL_PORT_ADR_RDY, 10, 10000); |
1592 | if (ret) |
1593 | pr_warn("%s: GAMMA ADR_RDY timeout\n" , __func__); |
1594 | |
1595 | writel_relaxed(L_GAMMA_ADDR_PORT_AUTO_INC | rgb_mask | |
1596 | FIELD_PREP(L_GAMMA_ADDR_PORT_ADDR, 0), |
1597 | priv->io_base + _REG(L_GAMMA_ADDR_PORT)); |
1598 | |
1599 | for (i = 0; i < 256; i++) { |
1600 | ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT), |
1601 | reg, reg & L_GAMMA_CNTL_PORT_WR_RDY, |
1602 | 10, 10000); |
1603 | if (ret) |
1604 | pr_warn_once("%s: GAMMA WR_RDY timeout\n" , __func__); |
1605 | |
1606 | writel_relaxed(data[i], priv->io_base + _REG(L_GAMMA_DATA_PORT)); |
1607 | } |
1608 | |
1609 | ret = readl_relaxed_poll_timeout(priv->io_base + _REG(L_GAMMA_CNTL_PORT), |
1610 | reg, reg & L_GAMMA_CNTL_PORT_ADR_RDY, 10, 10000); |
1611 | if (ret) |
1612 | pr_warn("%s: GAMMA ADR_RDY timeout\n" , __func__); |
1613 | |
1614 | writel_relaxed(L_GAMMA_ADDR_PORT_AUTO_INC | rgb_mask | |
1615 | FIELD_PREP(L_GAMMA_ADDR_PORT_ADDR, 0x23), |
1616 | priv->io_base + _REG(L_GAMMA_ADDR_PORT)); |
1617 | } |
1618 | |
1619 | void meson_encl_load_gamma(struct meson_drm *priv) |
1620 | { |
1621 | meson_encl_set_gamma_table(priv, data: meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_R); |
1622 | meson_encl_set_gamma_table(priv, data: meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_G); |
1623 | meson_encl_set_gamma_table(priv, data: meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_B); |
1624 | |
1625 | writel_bits_relaxed(L_GAMMA_CNTL_PORT_EN, L_GAMMA_CNTL_PORT_EN, |
1626 | priv->io_base + _REG(L_GAMMA_CNTL_PORT)); |
1627 | } |
1628 | |
1629 | void meson_venc_mipi_dsi_mode_set(struct meson_drm *priv, |
1630 | const struct drm_display_mode *mode) |
1631 | { |
1632 | unsigned int max_pxcnt; |
1633 | unsigned int max_lncnt; |
1634 | unsigned int havon_begin; |
1635 | unsigned int havon_end; |
1636 | unsigned int vavon_bline; |
1637 | unsigned int vavon_eline; |
1638 | unsigned int hso_begin; |
1639 | unsigned int hso_end; |
1640 | unsigned int vso_begin; |
1641 | unsigned int vso_end; |
1642 | unsigned int vso_bline; |
1643 | unsigned int vso_eline; |
1644 | |
1645 | max_pxcnt = mode->htotal - 1; |
1646 | max_lncnt = mode->vtotal - 1; |
1647 | havon_begin = mode->htotal - mode->hsync_start; |
1648 | havon_end = havon_begin + mode->hdisplay - 1; |
1649 | vavon_bline = mode->vtotal - mode->vsync_start; |
1650 | vavon_eline = vavon_bline + mode->vdisplay - 1; |
1651 | hso_begin = 0; |
1652 | hso_end = mode->hsync_end - mode->hsync_start; |
1653 | vso_begin = 0; |
1654 | vso_end = 0; |
1655 | vso_bline = 0; |
1656 | vso_eline = mode->vsync_end - mode->vsync_start; |
1657 | |
1658 | meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCL); |
1659 | |
1660 | writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN)); |
1661 | |
1662 | writel_relaxed(ENCL_PX_LN_CNT_SHADOW_EN, priv->io_base + _REG(ENCL_VIDEO_MODE)); |
1663 | writel_relaxed(ENCL_VIDEO_MODE_ADV_VFIFO_EN | |
1664 | ENCL_VIDEO_MODE_ADV_GAIN_HDTV | |
1665 | ENCL_SEL_GAMMA_RGB_IN, priv->io_base + _REG(ENCL_VIDEO_MODE_ADV)); |
1666 | |
1667 | writel_relaxed(ENCL_VIDEO_FILT_CTRL_BYPASS_FILTER, |
1668 | priv->io_base + _REG(ENCL_VIDEO_FILT_CTRL)); |
1669 | writel_relaxed(max_pxcnt, priv->io_base + _REG(ENCL_VIDEO_MAX_PXCNT)); |
1670 | writel_relaxed(max_lncnt, priv->io_base + _REG(ENCL_VIDEO_MAX_LNCNT)); |
1671 | writel_relaxed(havon_begin, priv->io_base + _REG(ENCL_VIDEO_HAVON_BEGIN)); |
1672 | writel_relaxed(havon_end, priv->io_base + _REG(ENCL_VIDEO_HAVON_END)); |
1673 | writel_relaxed(vavon_bline, priv->io_base + _REG(ENCL_VIDEO_VAVON_BLINE)); |
1674 | writel_relaxed(vavon_eline, priv->io_base + _REG(ENCL_VIDEO_VAVON_ELINE)); |
1675 | |
1676 | writel_relaxed(hso_begin, priv->io_base + _REG(ENCL_VIDEO_HSO_BEGIN)); |
1677 | writel_relaxed(hso_end, priv->io_base + _REG(ENCL_VIDEO_HSO_END)); |
1678 | writel_relaxed(vso_begin, priv->io_base + _REG(ENCL_VIDEO_VSO_BEGIN)); |
1679 | writel_relaxed(vso_end, priv->io_base + _REG(ENCL_VIDEO_VSO_END)); |
1680 | writel_relaxed(vso_bline, priv->io_base + _REG(ENCL_VIDEO_VSO_BLINE)); |
1681 | writel_relaxed(vso_eline, priv->io_base + _REG(ENCL_VIDEO_VSO_ELINE)); |
1682 | writel_relaxed(ENCL_VIDEO_RGBIN_RGB | ENCL_VIDEO_RGBIN_ZBLK, |
1683 | priv->io_base + _REG(ENCL_VIDEO_RGBIN_CTRL)); |
1684 | |
1685 | /* default black pattern */ |
1686 | writel_relaxed(0, priv->io_base + _REG(ENCL_TST_MDSEL)); |
1687 | writel_relaxed(0, priv->io_base + _REG(ENCL_TST_Y)); |
1688 | writel_relaxed(0, priv->io_base + _REG(ENCL_TST_CB)); |
1689 | writel_relaxed(0, priv->io_base + _REG(ENCL_TST_CR)); |
1690 | writel_relaxed(1, priv->io_base + _REG(ENCL_TST_EN)); |
1691 | writel_bits_relaxed(ENCL_VIDEO_MODE_ADV_VFIFO_EN, 0, |
1692 | priv->io_base + _REG(ENCL_VIDEO_MODE_ADV)); |
1693 | |
1694 | writel_relaxed(1, priv->io_base + _REG(ENCL_VIDEO_EN)); |
1695 | |
1696 | writel_relaxed(0, priv->io_base + _REG(L_RGB_BASE_ADDR)); |
1697 | writel_relaxed(0x400, priv->io_base + _REG(L_RGB_COEFF_ADDR)); /* Magic value */ |
1698 | |
1699 | writel_relaxed(L_DITH_CNTL_DITH10_EN, priv->io_base + _REG(L_DITH_CNTL_ADDR)); |
1700 | |
1701 | /* DE signal for TTL */ |
1702 | writel_relaxed(havon_begin, priv->io_base + _REG(L_OEH_HS_ADDR)); |
1703 | writel_relaxed(havon_end + 1, priv->io_base + _REG(L_OEH_HE_ADDR)); |
1704 | writel_relaxed(vavon_bline, priv->io_base + _REG(L_OEH_VS_ADDR)); |
1705 | writel_relaxed(vavon_eline, priv->io_base + _REG(L_OEH_VE_ADDR)); |
1706 | |
1707 | /* DE signal for TTL */ |
1708 | writel_relaxed(havon_begin, priv->io_base + _REG(L_OEV1_HS_ADDR)); |
1709 | writel_relaxed(havon_end + 1, priv->io_base + _REG(L_OEV1_HE_ADDR)); |
1710 | writel_relaxed(vavon_bline, priv->io_base + _REG(L_OEV1_VS_ADDR)); |
1711 | writel_relaxed(vavon_eline, priv->io_base + _REG(L_OEV1_VE_ADDR)); |
1712 | |
1713 | /* Hsync signal for TTL */ |
1714 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) { |
1715 | writel_relaxed(hso_begin, priv->io_base + _REG(L_STH1_HS_ADDR)); |
1716 | writel_relaxed(hso_end, priv->io_base + _REG(L_STH1_HE_ADDR)); |
1717 | } else { |
1718 | writel_relaxed(hso_end, priv->io_base + _REG(L_STH1_HS_ADDR)); |
1719 | writel_relaxed(hso_begin, priv->io_base + _REG(L_STH1_HE_ADDR)); |
1720 | } |
1721 | writel_relaxed(0, priv->io_base + _REG(L_STH1_VS_ADDR)); |
1722 | writel_relaxed(max_lncnt, priv->io_base + _REG(L_STH1_VE_ADDR)); |
1723 | |
1724 | /* Vsync signal for TTL */ |
1725 | writel_relaxed(vso_begin, priv->io_base + _REG(L_STV1_HS_ADDR)); |
1726 | writel_relaxed(vso_end, priv->io_base + _REG(L_STV1_HE_ADDR)); |
1727 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) { |
1728 | writel_relaxed(vso_bline, priv->io_base + _REG(L_STV1_VS_ADDR)); |
1729 | writel_relaxed(vso_eline, priv->io_base + _REG(L_STV1_VE_ADDR)); |
1730 | } else { |
1731 | writel_relaxed(vso_eline, priv->io_base + _REG(L_STV1_VS_ADDR)); |
1732 | writel_relaxed(vso_bline, priv->io_base + _REG(L_STV1_VE_ADDR)); |
1733 | } |
1734 | |
1735 | /* DE signal */ |
1736 | writel_relaxed(havon_begin, priv->io_base + _REG(L_DE_HS_ADDR)); |
1737 | writel_relaxed(havon_end + 1, priv->io_base + _REG(L_DE_HE_ADDR)); |
1738 | writel_relaxed(vavon_bline, priv->io_base + _REG(L_DE_VS_ADDR)); |
1739 | writel_relaxed(vavon_eline, priv->io_base + _REG(L_DE_VE_ADDR)); |
1740 | |
1741 | /* Hsync signal */ |
1742 | writel_relaxed(hso_begin, priv->io_base + _REG(L_HSYNC_HS_ADDR)); |
1743 | writel_relaxed(hso_end, priv->io_base + _REG(L_HSYNC_HE_ADDR)); |
1744 | writel_relaxed(0, priv->io_base + _REG(L_HSYNC_VS_ADDR)); |
1745 | writel_relaxed(max_lncnt, priv->io_base + _REG(L_HSYNC_VE_ADDR)); |
1746 | |
1747 | /* Vsync signal */ |
1748 | writel_relaxed(vso_begin, priv->io_base + _REG(L_VSYNC_HS_ADDR)); |
1749 | writel_relaxed(vso_end, priv->io_base + _REG(L_VSYNC_HE_ADDR)); |
1750 | writel_relaxed(vso_bline, priv->io_base + _REG(L_VSYNC_VS_ADDR)); |
1751 | writel_relaxed(vso_eline, priv->io_base + _REG(L_VSYNC_VE_ADDR)); |
1752 | |
1753 | writel_relaxed(0, priv->io_base + _REG(L_INV_CNT_ADDR)); |
1754 | writel_relaxed(L_TCON_MISC_SEL_STV1 | L_TCON_MISC_SEL_STV2, |
1755 | priv->io_base + _REG(L_TCON_MISC_SEL_ADDR)); |
1756 | |
1757 | priv->venc.current_mode = MESON_VENC_MODE_MIPI_DSI; |
1758 | } |
1759 | EXPORT_SYMBOL_GPL(meson_venc_mipi_dsi_mode_set); |
1760 | |
1761 | void meson_venci_cvbs_mode_set(struct meson_drm *priv, |
1762 | struct meson_cvbs_enci_mode *mode) |
1763 | { |
1764 | u32 reg; |
1765 | |
1766 | if (mode->mode_tag == priv->venc.current_mode) |
1767 | return; |
1768 | |
1769 | /* CVBS Filter settings */ |
1770 | writel_relaxed(ENCI_CFILT_CMPT_SEL_HIGH | 0x10, |
1771 | priv->io_base + _REG(ENCI_CFILT_CTRL)); |
1772 | writel_relaxed(ENCI_CFILT_CMPT_CR_DLY(2) | |
1773 | ENCI_CFILT_CMPT_CB_DLY(1), |
1774 | priv->io_base + _REG(ENCI_CFILT_CTRL2)); |
1775 | |
1776 | /* Digital Video Select : Interlace, clk27 clk, external */ |
1777 | writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING)); |
1778 | |
1779 | /* Reset Video Mode */ |
1780 | writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE)); |
1781 | writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); |
1782 | |
1783 | /* Horizontal sync signal output */ |
1784 | writel_relaxed(mode->hso_begin, |
1785 | priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN)); |
1786 | writel_relaxed(mode->hso_end, |
1787 | priv->io_base + _REG(ENCI_SYNC_HSO_END)); |
1788 | |
1789 | /* Vertical Sync lines */ |
1790 | writel_relaxed(mode->vso_even, |
1791 | priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN)); |
1792 | writel_relaxed(mode->vso_odd, |
1793 | priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN)); |
1794 | |
1795 | /* Macrovision max amplitude change */ |
1796 | writel_relaxed(ENCI_MACV_MAX_AMP_ENABLE_CHANGE | |
1797 | ENCI_MACV_MAX_AMP_VAL(mode->macv_max_amp), |
1798 | priv->io_base + _REG(ENCI_MACV_MAX_AMP)); |
1799 | |
1800 | /* Video mode */ |
1801 | writel_relaxed(mode->video_prog_mode, |
1802 | priv->io_base + _REG(VENC_VIDEO_PROG_MODE)); |
1803 | writel_relaxed(mode->video_mode, |
1804 | priv->io_base + _REG(ENCI_VIDEO_MODE)); |
1805 | |
1806 | /* |
1807 | * Advanced Video Mode : |
1808 | * Demux shifting 0x2 |
1809 | * Blank line end at line17/22 |
1810 | * High bandwidth Luma Filter |
1811 | * Low bandwidth Chroma Filter |
1812 | * Bypass luma low pass filter |
1813 | * No macrovision on CSYNC |
1814 | */ |
1815 | writel_relaxed(ENCI_VIDEO_MODE_ADV_DMXMD(2) | |
1816 | ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 | |
1817 | ENCI_VIDEO_MODE_ADV_YBW_HIGH, |
1818 | priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); |
1819 | |
1820 | writel(val: mode->sch_adjust, addr: priv->io_base + _REG(ENCI_VIDEO_SCH)); |
1821 | |
1822 | /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */ |
1823 | writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE)); |
1824 | |
1825 | /* 0x3 Y, C, and Component Y delay */ |
1826 | writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY)); |
1827 | |
1828 | /* Timings */ |
1829 | writel_relaxed(mode->pixel_start, |
1830 | priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START)); |
1831 | writel_relaxed(mode->pixel_end, |
1832 | priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END)); |
1833 | |
1834 | writel_relaxed(mode->top_field_line_start, |
1835 | priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START)); |
1836 | writel_relaxed(mode->top_field_line_end, |
1837 | priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END)); |
1838 | |
1839 | writel_relaxed(mode->bottom_field_line_start, |
1840 | priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START)); |
1841 | writel_relaxed(mode->bottom_field_line_end, |
1842 | priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END)); |
1843 | |
1844 | /* Internal Venc, Internal VIU Sync, Internal Vencoder */ |
1845 | writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE)); |
1846 | |
1847 | /* UNreset Interlaced TV Encoder */ |
1848 | writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST)); |
1849 | |
1850 | /* |
1851 | * Enable Vfifo2vd and set Y_Cb_Y_Cr: |
1852 | * Corresponding value: |
1853 | * Y => 00 or 10 |
1854 | * Cb => 01 |
1855 | * Cr => 11 |
1856 | * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y |
1857 | */ |
1858 | writel_relaxed(ENCI_VFIFO2VD_CTL_ENABLE | |
1859 | ENCI_VFIFO2VD_CTL_VD_SEL(0x4e), |
1860 | priv->io_base + _REG(ENCI_VFIFO2VD_CTL)); |
1861 | |
1862 | /* Power UP Dacs */ |
1863 | writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING)); |
1864 | |
1865 | /* Video Upsampling */ |
1866 | /* |
1867 | * CTRL0, CTRL1 and CTRL2: |
1868 | * Filter0: input data sample every 2 cloks |
1869 | * Filter1: filtering and upsample enable |
1870 | */ |
1871 | reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN | |
1872 | VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN; |
1873 | |
1874 | /* |
1875 | * Upsample CTRL0: |
1876 | * Interlace High Bandwidth Luma |
1877 | */ |
1878 | writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg, |
1879 | priv->io_base + _REG(VENC_UPSAMPLE_CTRL0)); |
1880 | |
1881 | /* |
1882 | * Upsample CTRL1: |
1883 | * Interlace Pb |
1884 | */ |
1885 | writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg, |
1886 | priv->io_base + _REG(VENC_UPSAMPLE_CTRL1)); |
1887 | |
1888 | /* |
1889 | * Upsample CTRL2: |
1890 | * Interlace R |
1891 | */ |
1892 | writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg, |
1893 | priv->io_base + _REG(VENC_UPSAMPLE_CTRL2)); |
1894 | |
1895 | /* Select Interlace Y DACs */ |
1896 | writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0)); |
1897 | writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL1)); |
1898 | writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL2)); |
1899 | writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL3)); |
1900 | writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL4)); |
1901 | writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL5)); |
1902 | |
1903 | /* Select ENCI for VIU */ |
1904 | meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI); |
1905 | |
1906 | /* Enable ENCI FIFO */ |
1907 | writel_relaxed(VENC_VDAC_FIFO_EN_ENCI_ENABLE, |
1908 | priv->io_base + _REG(VENC_VDAC_FIFO_CTRL)); |
1909 | |
1910 | /* Select ENCI DACs 0, 1, 4, and 5 */ |
1911 | writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0)); |
1912 | writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1)); |
1913 | |
1914 | /* Interlace video enable */ |
1915 | writel_relaxed(ENCI_VIDEO_EN_ENABLE, |
1916 | priv->io_base + _REG(ENCI_VIDEO_EN)); |
1917 | |
1918 | /* Configure Video Saturation / Contrast / Brightness / Hue */ |
1919 | writel_relaxed(mode->video_saturation, |
1920 | priv->io_base + _REG(ENCI_VIDEO_SAT)); |
1921 | writel_relaxed(mode->video_contrast, |
1922 | priv->io_base + _REG(ENCI_VIDEO_CONT)); |
1923 | writel_relaxed(mode->video_brightness, |
1924 | priv->io_base + _REG(ENCI_VIDEO_BRIGHT)); |
1925 | writel_relaxed(mode->video_hue, |
1926 | priv->io_base + _REG(ENCI_VIDEO_HUE)); |
1927 | |
1928 | /* Enable DAC0 Filter */ |
1929 | writel_relaxed(VENC_VDAC_DAC0_FILT_CTRL0_EN, |
1930 | priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0)); |
1931 | writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1)); |
1932 | |
1933 | /* 0 in Macrovision register 0 */ |
1934 | writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0)); |
1935 | |
1936 | /* Analog Synchronization and color burst value adjust */ |
1937 | writel_relaxed(mode->analog_sync_adj, |
1938 | priv->io_base + _REG(ENCI_SYNC_ADJ)); |
1939 | |
1940 | priv->venc.current_mode = mode->mode_tag; |
1941 | } |
1942 | |
1943 | /* Returns the current ENCI field polarity */ |
1944 | unsigned int meson_venci_get_field(struct meson_drm *priv) |
1945 | { |
1946 | return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29); |
1947 | } |
1948 | |
1949 | void meson_venc_enable_vsync(struct meson_drm *priv) |
1950 | { |
1951 | switch (priv->venc.current_mode) { |
1952 | case MESON_VENC_MODE_MIPI_DSI: |
1953 | writel_relaxed(VENC_INTCTRL_ENCP_LNRST_INT_EN, |
1954 | priv->io_base + _REG(VENC_INTCTRL)); |
1955 | break; |
1956 | default: |
1957 | writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN, |
1958 | priv->io_base + _REG(VENC_INTCTRL)); |
1959 | } |
1960 | regmap_update_bits(map: priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25)); |
1961 | } |
1962 | |
1963 | void meson_venc_disable_vsync(struct meson_drm *priv) |
1964 | { |
1965 | regmap_update_bits(map: priv->hhi, HHI_GCLK_MPEG2, BIT(25), val: 0); |
1966 | writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL)); |
1967 | } |
1968 | |
1969 | void meson_venc_init(struct meson_drm *priv) |
1970 | { |
1971 | /* Disable CVBS VDAC */ |
1972 | if (meson_vpu_is_compatible(priv, family: VPU_COMPATIBLE_G12A)) { |
1973 | regmap_write(map: priv->hhi, HHI_VDAC_CNTL0_G12A, val: 0); |
1974 | regmap_write(map: priv->hhi, HHI_VDAC_CNTL1_G12A, val: 8); |
1975 | } else { |
1976 | regmap_write(map: priv->hhi, HHI_VDAC_CNTL0, val: 0); |
1977 | regmap_write(map: priv->hhi, HHI_VDAC_CNTL1, val: 8); |
1978 | } |
1979 | |
1980 | /* Power Down Dacs */ |
1981 | writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING)); |
1982 | |
1983 | /* Disable HDMI PHY */ |
1984 | regmap_write(map: priv->hhi, HHI_HDMI_PHY_CNTL0, val: 0); |
1985 | |
1986 | /* Disable HDMI */ |
1987 | writel_bits_relaxed(VPU_HDMI_ENCI_DATA_TO_HDMI | |
1988 | VPU_HDMI_ENCP_DATA_TO_HDMI, 0, |
1989 | priv->io_base + _REG(VPU_HDMI_SETTING)); |
1990 | |
1991 | /* Disable all encoders */ |
1992 | writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); |
1993 | writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); |
1994 | writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN)); |
1995 | |
1996 | /* Disable VSync IRQ */ |
1997 | meson_venc_disable_vsync(priv); |
1998 | |
1999 | priv->venc.current_mode = MESON_VENC_MODE_NONE; |
2000 | } |
2001 | |