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