xref: /linux/drivers/gpu/drm/meson/meson_venc.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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, &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(vmode->enci.sch_adjust,
1107 				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 				    total_pixels_venc);
1162 		de_h_end  = modulo(de_h_begin + active_pixels_venc,
1163 				   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(hs_begin + hsync_pixels_venc,
1197 				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(hs_begin
1268 						+ (total_pixels_venc >> 1),
1269 						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(hs_begin
1283 						+ (total_pixels_venc >> 1),
1284 						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 				    total_pixels_venc);
1409 		de_h_end = modulo(de_h_begin + active_pixels_venc,
1410 				  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((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(hs_begin + hsync_pixels_venc,
1460 				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(vs_bline_evn + vsync_lines,
1482 					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(hs_begin
1503 						+ (total_pixels_venc >> 1),
1504 						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, meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_R);
1622 	meson_encl_set_gamma_table(priv, meson_encl_gamma_table, L_GAMMA_ADDR_PORT_SEL_G);
1623 	meson_encl_set_gamma_table(priv, 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(mode->sch_adjust, 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(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(priv->hhi, HHI_GCLK_MPEG2, BIT(25), 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, VPU_COMPATIBLE_G12A)) {
1973 		regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
1974 		regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 8);
1975 	} else {
1976 		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
1977 		regmap_write(priv->hhi, HHI_VDAC_CNTL1, 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(priv->hhi, HHI_HDMI_PHY_CNTL0, 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