1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Amlogic Meson Video Processing Unit driver
4  *
5  * Copyright (c) 2018 BayLibre, SAS.
6  * Author: Neil Armstrong <narmstrong@baylibre.com>
7  */
8 
9 #include <edid.h>
10 #include "meson_vpu.h"
11 
12 enum {
13 	MESON_VENC_MODE_NONE = 0,
14 	MESON_VENC_MODE_CVBS_PAL,
15 	MESON_VENC_MODE_CVBS_NTSC,
16 	MESON_VENC_MODE_HDMI,
17 };
18 
19 enum meson_venc_source {
20 	MESON_VENC_SOURCE_NONE = 0,
21 	MESON_VENC_SOURCE_ENCI = 1,
22 	MESON_VENC_SOURCE_ENCP = 2,
23 };
24 
25 #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
26 #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
27 
28 struct meson_cvbs_enci_mode {
29 	unsigned int mode_tag;
30 	unsigned int hso_begin; /* HSO begin position */
31 	unsigned int hso_end; /* HSO end position */
32 	unsigned int vso_even; /* VSO even line */
33 	unsigned int vso_odd; /* VSO odd line */
34 	unsigned int macv_max_amp; /* Macrovision max amplitude */
35 	unsigned int video_prog_mode;
36 	unsigned int video_mode;
37 	unsigned int sch_adjust;
38 	unsigned int yc_delay;
39 	unsigned int pixel_start;
40 	unsigned int pixel_end;
41 	unsigned int top_field_line_start;
42 	unsigned int top_field_line_end;
43 	unsigned int bottom_field_line_start;
44 	unsigned int bottom_field_line_end;
45 	unsigned int video_saturation;
46 	unsigned int video_contrast;
47 	unsigned int video_brightness;
48 	unsigned int video_hue;
49 	unsigned int analog_sync_adj;
50 };
51 
52 struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
53 	.mode_tag = MESON_VENC_MODE_CVBS_PAL,
54 	.hso_begin = 3,
55 	.hso_end = 129,
56 	.vso_even = 3,
57 	.vso_odd = 260,
58 	.macv_max_amp = 7,
59 	.video_prog_mode = 0xff,
60 	.video_mode = 0x13,
61 	.sch_adjust = 0x28,
62 	.yc_delay = 0x343,
63 	.pixel_start = 251,
64 	.pixel_end = 1691,
65 	.top_field_line_start = 22,
66 	.top_field_line_end = 310,
67 	.bottom_field_line_start = 23,
68 	.bottom_field_line_end = 311,
69 	.video_saturation = 9,
70 	.video_contrast = 0,
71 	.video_brightness = 0,
72 	.video_hue = 0,
73 	.analog_sync_adj = 0x8080,
74 };
75 
76 struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
77 	.mode_tag = MESON_VENC_MODE_CVBS_NTSC,
78 	.hso_begin = 5,
79 	.hso_end = 129,
80 	.vso_even = 3,
81 	.vso_odd = 260,
82 	.macv_max_amp = 0xb,
83 	.video_prog_mode = 0xf0,
84 	.video_mode = 0x8,
85 	.sch_adjust = 0x20,
86 	.yc_delay = 0x333,
87 	.pixel_start = 227,
88 	.pixel_end = 1667,
89 	.top_field_line_start = 18,
90 	.top_field_line_end = 258,
91 	.bottom_field_line_start = 19,
92 	.bottom_field_line_end = 259,
93 	.video_saturation = 18,
94 	.video_contrast = 3,
95 	.video_brightness = 0,
96 	.video_hue = 0,
97 	.analog_sync_adj = 0x9c00,
98 };
99 
100 union meson_hdmi_venc_mode {
101 	struct {
102 		unsigned int mode_tag;
103 		unsigned int hso_begin;
104 		unsigned int hso_end;
105 		unsigned int vso_even;
106 		unsigned int vso_odd;
107 		unsigned int macv_max_amp;
108 		unsigned int video_prog_mode;
109 		unsigned int video_mode;
110 		unsigned int sch_adjust;
111 		unsigned int yc_delay;
112 		unsigned int pixel_start;
113 		unsigned int pixel_end;
114 		unsigned int top_field_line_start;
115 		unsigned int top_field_line_end;
116 		unsigned int bottom_field_line_start;
117 		unsigned int bottom_field_line_end;
118 	} enci;
119 	struct {
120 		unsigned int dvi_settings;
121 		unsigned int video_mode;
122 		unsigned int video_mode_adv;
123 		unsigned int video_prog_mode;
124 		bool video_prog_mode_present;
125 		unsigned int video_sync_mode;
126 		bool video_sync_mode_present;
127 		unsigned int video_yc_dly;
128 		bool video_yc_dly_present;
129 		unsigned int video_rgb_ctrl;
130 		bool video_rgb_ctrl_present;
131 		unsigned int video_filt_ctrl;
132 		bool video_filt_ctrl_present;
133 		unsigned int video_ofld_voav_ofst;
134 		bool video_ofld_voav_ofst_present;
135 		unsigned int yfp1_htime;
136 		unsigned int yfp2_htime;
137 		unsigned int max_pxcnt;
138 		unsigned int hspuls_begin;
139 		unsigned int hspuls_end;
140 		unsigned int hspuls_switch;
141 		unsigned int vspuls_begin;
142 		unsigned int vspuls_end;
143 		unsigned int vspuls_bline;
144 		unsigned int vspuls_eline;
145 		unsigned int eqpuls_begin;
146 		bool eqpuls_begin_present;
147 		unsigned int eqpuls_end;
148 		bool eqpuls_end_present;
149 		unsigned int eqpuls_bline;
150 		bool eqpuls_bline_present;
151 		unsigned int eqpuls_eline;
152 		bool eqpuls_eline_present;
153 		unsigned int havon_begin;
154 		unsigned int havon_end;
155 		unsigned int vavon_bline;
156 		unsigned int vavon_eline;
157 		unsigned int hso_begin;
158 		unsigned int hso_end;
159 		unsigned int vso_begin;
160 		unsigned int vso_end;
161 		unsigned int vso_bline;
162 		unsigned int vso_eline;
163 		bool vso_eline_present;
164 		unsigned int sy_val;
165 		bool sy_val_present;
166 		unsigned int sy2_val;
167 		bool sy2_val_present;
168 		unsigned int max_lncnt;
169 	} encp;
170 };
171 
172 union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
173 	.enci = {
174 		.hso_begin = 5,
175 		.hso_end = 129,
176 		.vso_even = 3,
177 		.vso_odd = 260,
178 		.macv_max_amp = 0x810b,
179 		.video_prog_mode = 0xf0,
180 		.video_mode = 0x8,
181 		.sch_adjust = 0x20,
182 		.yc_delay = 0,
183 		.pixel_start = 227,
184 		.pixel_end = 1667,
185 		.top_field_line_start = 18,
186 		.top_field_line_end = 258,
187 		.bottom_field_line_start = 19,
188 		.bottom_field_line_end = 259,
189 	},
190 };
191 
192 union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
193 	.enci = {
194 		.hso_begin = 3,
195 		.hso_end = 129,
196 		.vso_even = 3,
197 		.vso_odd = 260,
198 		.macv_max_amp = 8107,
199 		.video_prog_mode = 0xff,
200 		.video_mode = 0x13,
201 		.sch_adjust = 0x28,
202 		.yc_delay = 0x333,
203 		.pixel_start = 251,
204 		.pixel_end = 1691,
205 		.top_field_line_start = 22,
206 		.top_field_line_end = 310,
207 		.bottom_field_line_start = 23,
208 		.bottom_field_line_end = 311,
209 	},
210 };
211 
212 union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
213 	.encp = {
214 		.dvi_settings = 0x21,
215 		.video_mode = 0x4000,
216 		.video_mode_adv = 0x9,
217 		.video_prog_mode = 0,
218 		.video_prog_mode_present = true,
219 		.video_sync_mode = 7,
220 		.video_sync_mode_present = true,
221 		/* video_yc_dly */
222 		/* video_rgb_ctrl */
223 		.video_filt_ctrl = 0x2052,
224 		.video_filt_ctrl_present = true,
225 		/* video_ofld_voav_ofst */
226 		.yfp1_htime = 244,
227 		.yfp2_htime = 1630,
228 		.max_pxcnt = 1715,
229 		.hspuls_begin = 0x22,
230 		.hspuls_end = 0xa0,
231 		.hspuls_switch = 88,
232 		.vspuls_begin = 0,
233 		.vspuls_end = 1589,
234 		.vspuls_bline = 0,
235 		.vspuls_eline = 5,
236 		.havon_begin = 249,
237 		.havon_end = 1689,
238 		.vavon_bline = 42,
239 		.vavon_eline = 521,
240 		/* eqpuls_begin */
241 		/* eqpuls_end */
242 		/* eqpuls_bline */
243 		/* eqpuls_eline */
244 		.hso_begin = 3,
245 		.hso_end = 5,
246 		.vso_begin = 3,
247 		.vso_end = 5,
248 		.vso_bline = 0,
249 		/* vso_eline */
250 		.sy_val	= 8,
251 		.sy_val_present = true,
252 		.sy2_val = 0x1d8,
253 		.sy2_val_present = true,
254 		.max_lncnt = 524,
255 	},
256 };
257 
258 union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
259 	.encp = {
260 		.dvi_settings = 0x21,
261 		.video_mode = 0x4000,
262 		.video_mode_adv = 0x9,
263 		.video_prog_mode = 0,
264 		.video_prog_mode_present = true,
265 		.video_sync_mode = 7,
266 		.video_sync_mode_present = true,
267 		/* video_yc_dly */
268 		/* video_rgb_ctrl */
269 		.video_filt_ctrl = 0x52,
270 		.video_filt_ctrl_present = true,
271 		/* video_ofld_voav_ofst */
272 		.yfp1_htime = 235,
273 		.yfp2_htime = 1674,
274 		.max_pxcnt = 1727,
275 		.hspuls_begin = 0,
276 		.hspuls_end = 0x80,
277 		.hspuls_switch = 88,
278 		.vspuls_begin = 0,
279 		.vspuls_end = 1599,
280 		.vspuls_bline = 0,
281 		.vspuls_eline = 4,
282 		.havon_begin = 235,
283 		.havon_end = 1674,
284 		.vavon_bline = 44,
285 		.vavon_eline = 619,
286 		/* eqpuls_begin */
287 		/* eqpuls_end */
288 		/* eqpuls_bline */
289 		/* eqpuls_eline */
290 		.hso_begin = 0x80,
291 		.hso_end = 0,
292 		.vso_begin = 0,
293 		.vso_end = 5,
294 		.vso_bline = 0,
295 		/* vso_eline */
296 		.sy_val	= 8,
297 		.sy_val_present = true,
298 		.sy2_val = 0x1d8,
299 		.sy2_val_present = true,
300 		.max_lncnt = 624,
301 	},
302 };
303 
304 union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
305 	.encp = {
306 		.dvi_settings = 0x2029,
307 		.video_mode = 0x4040,
308 		.video_mode_adv = 0x19,
309 		/* video_prog_mode */
310 		/* video_sync_mode */
311 		/* video_yc_dly */
312 		/* video_rgb_ctrl */
313 		/* video_filt_ctrl */
314 		/* video_ofld_voav_ofst */
315 		.yfp1_htime = 648,
316 		.yfp2_htime = 3207,
317 		.max_pxcnt = 3299,
318 		.hspuls_begin = 80,
319 		.hspuls_end = 240,
320 		.hspuls_switch = 80,
321 		.vspuls_begin = 688,
322 		.vspuls_end = 3248,
323 		.vspuls_bline = 4,
324 		.vspuls_eline = 8,
325 		.havon_begin = 648,
326 		.havon_end = 3207,
327 		.vavon_bline = 29,
328 		.vavon_eline = 748,
329 		/* eqpuls_begin */
330 		/* eqpuls_end */
331 		/* eqpuls_bline */
332 		/* eqpuls_eline */
333 		.hso_begin = 256,
334 		.hso_end = 168,
335 		.vso_begin = 168,
336 		.vso_end = 256,
337 		.vso_bline = 0,
338 		.vso_eline = 5,
339 		.vso_eline_present = true,
340 		/* sy_val */
341 		/* sy2_val */
342 		.max_lncnt = 749,
343 	},
344 };
345 
346 union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
347 	.encp = {
348 		.dvi_settings = 0x202d,
349 		.video_mode = 0x4040,
350 		.video_mode_adv = 0x19,
351 		.video_prog_mode = 0x100,
352 		.video_prog_mode_present = true,
353 		.video_sync_mode = 0x407,
354 		.video_sync_mode_present = true,
355 		.video_yc_dly = 0,
356 		.video_yc_dly_present = true,
357 		/* video_rgb_ctrl */
358 		/* video_filt_ctrl */
359 		/* video_ofld_voav_ofst */
360 		.yfp1_htime = 648,
361 		.yfp2_htime = 3207,
362 		.max_pxcnt = 3959,
363 		.hspuls_begin = 80,
364 		.hspuls_end = 240,
365 		.hspuls_switch = 80,
366 		.vspuls_begin = 688,
367 		.vspuls_end = 3248,
368 		.vspuls_bline = 4,
369 		.vspuls_eline = 8,
370 		.havon_begin = 648,
371 		.havon_end = 3207,
372 		.vavon_bline = 29,
373 		.vavon_eline = 748,
374 		/* eqpuls_begin */
375 		/* eqpuls_end */
376 		/* eqpuls_bline */
377 		/* eqpuls_eline */
378 		.hso_begin = 128,
379 		.hso_end = 208,
380 		.vso_begin = 128,
381 		.vso_end = 128,
382 		.vso_bline = 0,
383 		.vso_eline = 5,
384 		.vso_eline_present = true,
385 		/* sy_val */
386 		/* sy2_val */
387 		.max_lncnt = 749,
388 	},
389 };
390 
391 union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
392 	.encp = {
393 		.dvi_settings = 0x2029,
394 		.video_mode = 0x5ffc,
395 		.video_mode_adv = 0x19,
396 		.video_prog_mode = 0x100,
397 		.video_prog_mode_present = true,
398 		.video_sync_mode = 0x207,
399 		.video_sync_mode_present = true,
400 		/* video_yc_dly */
401 		/* video_rgb_ctrl */
402 		/* video_filt_ctrl */
403 		.video_ofld_voav_ofst = 0x11,
404 		.video_ofld_voav_ofst_present = true,
405 		.yfp1_htime = 516,
406 		.yfp2_htime = 4355,
407 		.max_pxcnt = 4399,
408 		.hspuls_begin = 88,
409 		.hspuls_end = 264,
410 		.hspuls_switch = 88,
411 		.vspuls_begin = 440,
412 		.vspuls_end = 2200,
413 		.vspuls_bline = 0,
414 		.vspuls_eline = 4,
415 		.havon_begin = 516,
416 		.havon_end = 4355,
417 		.vavon_bline = 20,
418 		.vavon_eline = 559,
419 		.eqpuls_begin = 2288,
420 		.eqpuls_begin_present = true,
421 		.eqpuls_end = 2464,
422 		.eqpuls_end_present = true,
423 		.eqpuls_bline = 0,
424 		.eqpuls_bline_present = true,
425 		.eqpuls_eline = 4,
426 		.eqpuls_eline_present = true,
427 		.hso_begin = 264,
428 		.hso_end = 176,
429 		.vso_begin = 88,
430 		.vso_end = 88,
431 		.vso_bline = 0,
432 		.vso_eline = 5,
433 		.vso_eline_present = true,
434 		/* sy_val */
435 		/* sy2_val */
436 		.max_lncnt = 1124,
437 	},
438 };
439 
440 union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
441 	.encp = {
442 		.dvi_settings = 0x202d,
443 		.video_mode = 0x5ffc,
444 		.video_mode_adv = 0x19,
445 		.video_prog_mode = 0x100,
446 		.video_prog_mode_present = true,
447 		.video_sync_mode = 0x7,
448 		.video_sync_mode_present = true,
449 		/* video_yc_dly */
450 		/* video_rgb_ctrl */
451 		/* video_filt_ctrl */
452 		.video_ofld_voav_ofst = 0x11,
453 		.video_ofld_voav_ofst_present = true,
454 		.yfp1_htime = 526,
455 		.yfp2_htime = 4365,
456 		.max_pxcnt = 5279,
457 		.hspuls_begin = 88,
458 		.hspuls_end = 264,
459 		.hspuls_switch = 88,
460 		.vspuls_begin = 440,
461 		.vspuls_end = 2200,
462 		.vspuls_bline = 0,
463 		.vspuls_eline = 4,
464 		.havon_begin = 526,
465 		.havon_end = 4365,
466 		.vavon_bline = 20,
467 		.vavon_eline = 559,
468 		.eqpuls_begin = 2288,
469 		.eqpuls_begin_present = true,
470 		.eqpuls_end = 2464,
471 		.eqpuls_end_present = true,
472 		.eqpuls_bline = 0,
473 		.eqpuls_bline_present = true,
474 		.eqpuls_eline = 4,
475 		.eqpuls_eline_present = true,
476 		.hso_begin = 142,
477 		.hso_end = 230,
478 		.vso_begin = 142,
479 		.vso_end = 142,
480 		.vso_bline = 0,
481 		.vso_eline = 5,
482 		.vso_eline_present = true,
483 		/* sy_val */
484 		/* sy2_val */
485 		.max_lncnt = 1124,
486 	},
487 };
488 
489 union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
490 	.encp = {
491 		.dvi_settings = 0xd,
492 		.video_mode = 0x4040,
493 		.video_mode_adv = 0x18,
494 		.video_prog_mode = 0x100,
495 		.video_prog_mode_present = true,
496 		.video_sync_mode = 0x7,
497 		.video_sync_mode_present = true,
498 		.video_yc_dly = 0,
499 		.video_yc_dly_present = true,
500 		.video_rgb_ctrl = 2,
501 		.video_rgb_ctrl_present = true,
502 		.video_filt_ctrl = 0x1052,
503 		.video_filt_ctrl_present = true,
504 		/* video_ofld_voav_ofst */
505 		.yfp1_htime = 271,
506 		.yfp2_htime = 2190,
507 		.max_pxcnt = 2749,
508 		.hspuls_begin = 44,
509 		.hspuls_end = 132,
510 		.hspuls_switch = 44,
511 		.vspuls_begin = 220,
512 		.vspuls_end = 2140,
513 		.vspuls_bline = 0,
514 		.vspuls_eline = 4,
515 		.havon_begin = 271,
516 		.havon_end = 2190,
517 		.vavon_bline = 41,
518 		.vavon_eline = 1120,
519 		/* eqpuls_begin */
520 		/* eqpuls_end */
521 		.eqpuls_bline = 0,
522 		.eqpuls_bline_present = true,
523 		.eqpuls_eline = 4,
524 		.eqpuls_eline_present = true,
525 		.hso_begin = 79,
526 		.hso_end = 123,
527 		.vso_begin = 79,
528 		.vso_end = 79,
529 		.vso_bline = 0,
530 		.vso_eline = 5,
531 		.vso_eline_present = true,
532 		/* sy_val */
533 		/* sy2_val */
534 		.max_lncnt = 1124,
535 	},
536 };
537 
538 union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
539 	.encp = {
540 		.dvi_settings = 0x1,
541 		.video_mode = 0x4040,
542 		.video_mode_adv = 0x18,
543 		.video_prog_mode = 0x100,
544 		.video_prog_mode_present = true,
545 		/* video_sync_mode */
546 		/* video_yc_dly */
547 		/* video_rgb_ctrl */
548 		.video_filt_ctrl = 0x1052,
549 		.video_filt_ctrl_present = true,
550 		/* video_ofld_voav_ofst */
551 		.yfp1_htime = 140,
552 		.yfp2_htime = 2060,
553 		.max_pxcnt = 2199,
554 		.hspuls_begin = 2156,
555 		.hspuls_end = 44,
556 		.hspuls_switch = 44,
557 		.vspuls_begin = 140,
558 		.vspuls_end = 2059,
559 		.vspuls_bline = 0,
560 		.vspuls_eline = 4,
561 		.havon_begin = 148,
562 		.havon_end = 2067,
563 		.vavon_bline = 41,
564 		.vavon_eline = 1120,
565 		/* eqpuls_begin */
566 		/* eqpuls_end */
567 		/* eqpuls_bline */
568 		/* eqpuls_eline */
569 		.hso_begin = 44,
570 		.hso_end = 2156,
571 		.vso_begin = 2100,
572 		.vso_end = 2164,
573 		.vso_bline = 0,
574 		.vso_eline = 5,
575 		.vso_eline_present = true,
576 		/* sy_val */
577 		/* sy2_val */
578 		.max_lncnt = 1124,
579 	},
580 };
581 
582 union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
583 	.encp = {
584 		.dvi_settings = 0xd,
585 		.video_mode = 0x4040,
586 		.video_mode_adv = 0x18,
587 		.video_prog_mode = 0x100,
588 		.video_prog_mode_present = true,
589 		.video_sync_mode = 0x7,
590 		.video_sync_mode_present = true,
591 		.video_yc_dly = 0,
592 		.video_yc_dly_present = true,
593 		.video_rgb_ctrl = 2,
594 		.video_rgb_ctrl_present = true,
595 		/* video_filt_ctrl */
596 		/* video_ofld_voav_ofst */
597 		.yfp1_htime = 271,
598 		.yfp2_htime = 2190,
599 		.max_pxcnt = 2639,
600 		.hspuls_begin = 44,
601 		.hspuls_end = 132,
602 		.hspuls_switch = 44,
603 		.vspuls_begin = 220,
604 		.vspuls_end = 2140,
605 		.vspuls_bline = 0,
606 		.vspuls_eline = 4,
607 		.havon_begin = 271,
608 		.havon_end = 2190,
609 		.vavon_bline = 41,
610 		.vavon_eline = 1120,
611 		/* eqpuls_begin */
612 		/* eqpuls_end */
613 		.eqpuls_bline = 0,
614 		.eqpuls_bline_present = true,
615 		.eqpuls_eline = 4,
616 		.eqpuls_eline_present = true,
617 		.hso_begin = 79,
618 		.hso_end = 123,
619 		.vso_begin = 79,
620 		.vso_end = 79,
621 		.vso_bline = 0,
622 		.vso_eline = 5,
623 		.vso_eline_present = true,
624 		/* sy_val */
625 		/* sy2_val */
626 		.max_lncnt = 1124,
627 	},
628 };
629 
630 union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
631 	.encp = {
632 		.dvi_settings = 0x1,
633 		.video_mode = 0x4040,
634 		.video_mode_adv = 0x18,
635 		.video_prog_mode = 0x100,
636 		.video_prog_mode_present = true,
637 		/* video_sync_mode */
638 		/* video_yc_dly */
639 		/* video_rgb_ctrl */
640 		.video_filt_ctrl = 0x1052,
641 		.video_filt_ctrl_present = true,
642 		/* video_ofld_voav_ofst */
643 		.yfp1_htime = 140,
644 		.yfp2_htime = 2060,
645 		.max_pxcnt = 2199,
646 		.hspuls_begin = 2156,
647 		.hspuls_end = 44,
648 		.hspuls_switch = 44,
649 		.vspuls_begin = 140,
650 		.vspuls_end = 2059,
651 		.vspuls_bline = 0,
652 		.vspuls_eline = 4,
653 		.havon_begin = 148,
654 		.havon_end = 2067,
655 		.vavon_bline = 41,
656 		.vavon_eline = 1120,
657 		/* eqpuls_begin */
658 		/* eqpuls_end */
659 		/* eqpuls_bline */
660 		/* eqpuls_eline */
661 		.hso_begin = 44,
662 		.hso_end = 2156,
663 		.vso_begin = 2100,
664 		.vso_end = 2164,
665 		.vso_bline = 0,
666 		.vso_eline = 5,
667 		.vso_eline_present = true,
668 		/* sy_val */
669 		/* sy2_val */
670 		.max_lncnt = 1124,
671 	},
672 };
673 
674 static signed int to_signed(unsigned int a)
675 {
676 	if (a <= 7)
677 		return a;
678 	else
679 		return a - 16;
680 }
681 
682 static unsigned long modulo(unsigned long a, unsigned long b)
683 {
684 	if (a >= b)
685 		return a - b;
686 	else
687 		return a;
688 }
689 
690 bool meson_venc_hdmi_supported_mode(const struct display_timing *mode)
691 {
692 	if (mode->flags & ~(DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_HSYNC_HIGH |
693 			    DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH))
694 		return false;
695 
696 	if (mode->hactive.typ < 640 || mode->hactive.typ > 1920)
697 		return false;
698 
699 	if (mode->vactive.typ < 480 || mode->vactive.typ > 1200)
700 		return false;
701 
702 	return true;
703 }
704 
705 static void meson_venc_hdmi_get_dmt_vmode(const struct display_timing *mode,
706 					  union meson_hdmi_venc_mode *dmt_mode)
707 {
708 	memset(dmt_mode, 0, sizeof(*dmt_mode));
709 
710 	dmt_mode->encp.dvi_settings = 0x21;
711 	dmt_mode->encp.video_mode = 0x4040;
712 	dmt_mode->encp.video_mode_adv = 0x18;
713 
714 	dmt_mode->encp.max_pxcnt = mode->hactive.typ +
715 				   mode->hfront_porch.typ +
716 				   mode->hback_porch.typ +
717 				   mode->hsync_len.typ - 1;
718 
719 	dmt_mode->encp.havon_begin = mode->hback_porch.typ +
720 				     mode->hsync_len.typ;
721 
722 	dmt_mode->encp.havon_end = dmt_mode->encp.havon_begin +
723 				   mode->hactive.typ - 1;
724 
725 	dmt_mode->encp.vavon_bline = mode->vback_porch.typ +
726 				     mode->vsync_len.typ;
727 	dmt_mode->encp.vavon_eline = dmt_mode->encp.vavon_bline +
728 				     mode->vactive.typ - 1;
729 
730 	/* to investigate */
731 	dmt_mode->encp.hso_begin = 0;
732 	dmt_mode->encp.hso_end = mode->hsync_len.typ;
733 	dmt_mode->encp.vso_begin = 30;
734 	dmt_mode->encp.vso_end = 50;
735 
736 	dmt_mode->encp.vso_bline = 0;
737 	dmt_mode->encp.vso_eline = mode->vsync_len.typ;
738 	dmt_mode->encp.vso_eline_present = true;
739 
740 	dmt_mode->encp.max_lncnt = mode->vactive.typ +
741 			    mode->vfront_porch.typ +
742 			    mode->vback_porch.typ +
743 			    mode->vsync_len.typ - 1;
744 }
745 
746 static void meson_venc_hdmi_mode_set(struct meson_vpu_priv *priv,
747 				     const struct display_timing *mode)
748 {
749 	union meson_hdmi_venc_mode *vmode = NULL;
750 	union meson_hdmi_venc_mode vmode_dmt;
751 	bool use_enci = false;
752 	bool venc_repeat = false;
753 	bool hdmi_repeat = false;
754 	unsigned int venc_hdmi_latency = 2;
755 	unsigned long total_pixels_venc = 0;
756 	unsigned long active_pixels_venc = 0;
757 	unsigned long front_porch_venc = 0;
758 	unsigned long hsync_pixels_venc = 0;
759 	unsigned long de_h_begin = 0;
760 	unsigned long de_h_end = 0;
761 	unsigned long de_v_begin_even = 0;
762 	unsigned long de_v_end_even = 0;
763 	unsigned long de_v_begin_odd = 0;
764 	unsigned long de_v_end_odd = 0;
765 	unsigned long hs_begin = 0;
766 	unsigned long hs_end = 0;
767 	unsigned long vs_adjust = 0;
768 	unsigned long vs_bline_evn = 0;
769 	unsigned long vs_eline_evn = 0;
770 	unsigned long vs_bline_odd = 0;
771 	unsigned long vs_eline_odd = 0;
772 	unsigned long vso_begin_evn = 0;
773 	unsigned long vso_begin_odd = 0;
774 	unsigned int eof_lines;
775 	unsigned int sof_lines;
776 	unsigned int vsync_lines;
777 
778 	/* Use VENCI for 480i and 576i and double HDMI pixels */
779 	if (mode->flags & DISPLAY_FLAGS_DOUBLECLK) {
780 		venc_hdmi_latency = 1;
781 		hdmi_repeat = true;
782 		use_enci = true;
783 	}
784 
785 	meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
786 	vmode = &vmode_dmt;
787 	use_enci = false;
788 
789 	debug(" max_pxcnt   %04d, max_lncnt   %04d\n"
790 	      " havon_begin %04d, havon_end   %04d\n"
791 	      " vavon_bline %04d, vavon_eline %04d\n"
792 	      " hso_begin   %04d, hso_end     %04d\n"
793 	      " vso_begin   %04d, vso_end     %04d\n"
794 	      " vso_bline   %04d, vso_eline   %04d\n",
795 		vmode->encp.max_pxcnt,   vmode->encp.max_lncnt,
796 		vmode->encp.havon_begin, vmode->encp.havon_end,
797 		vmode->encp.vavon_bline, vmode->encp.vavon_eline,
798 		vmode->encp.hso_begin,   vmode->encp.hso_end,
799 		vmode->encp.vso_begin,   vmode->encp.vso_end,
800 		vmode->encp.vso_bline,   vmode->encp.vso_eline);
801 
802 	eof_lines = mode->vfront_porch.typ;
803 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
804 		eof_lines /= 2;
805 
806 	sof_lines = mode->vback_porch.typ;
807 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
808 		sof_lines /= 2;
809 
810 	vsync_lines = mode->vsync_len.typ;
811 	if (mode->flags & DISPLAY_FLAGS_INTERLACED)
812 		vsync_lines /= 2;
813 
814 	total_pixels_venc = mode->hback_porch.typ + mode->hactive.typ +
815 			mode->hfront_porch.typ + mode->hsync_len.typ;
816 	if (hdmi_repeat)
817 		total_pixels_venc /= 2;
818 	if (venc_repeat)
819 		total_pixels_venc *= 2;
820 
821 	active_pixels_venc = mode->hactive.typ;
822 	if (hdmi_repeat)
823 		active_pixels_venc /= 2;
824 	if (venc_repeat)
825 		active_pixels_venc *= 2;
826 
827 	front_porch_venc = mode->hfront_porch.typ;
828 	if (hdmi_repeat)
829 		front_porch_venc /= 2;
830 	if (venc_repeat)
831 		front_porch_venc *= 2;
832 
833 	hsync_pixels_venc = mode->hsync_len.typ;
834 	if (hdmi_repeat)
835 		hsync_pixels_venc /= 2;
836 	if (venc_repeat)
837 		hsync_pixels_venc *= 2;
838 
839 	/* Disable VDACs */
840 	writel_bits(0xff, 0xff,
841 		    priv->io_base + _REG(VENC_VDAC_SETTING));
842 
843 	writel(0, priv->io_base + _REG(ENCI_VIDEO_EN));
844 	writel(0, priv->io_base + _REG(ENCP_VIDEO_EN));
845 
846 	debug("use_enci: %d, hdmi_repeat: %d\n", use_enci, hdmi_repeat);
847 
848 	if (use_enci) {
849 		unsigned int lines_f0;
850 		unsigned int lines_f1;
851 
852 		/* CVBS Filter settings */
853 		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
854 		writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
855 
856 		/* Digital Video Select : Interlace, clk27 clk, external */
857 		writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
858 
859 		/* Reset Video Mode */
860 		writel(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
861 		writel(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
862 
863 		/* Horizontal sync signal output */
864 		writel(vmode->enci.hso_begin,
865 		       priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
866 		writel(vmode->enci.hso_end,
867 		       priv->io_base + _REG(ENCI_SYNC_HSO_END));
868 
869 		/* Vertical Sync lines */
870 		writel(vmode->enci.vso_even,
871 		       priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
872 		writel(vmode->enci.vso_odd,
873 		       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
874 
875 		/* Macrovision max amplitude change */
876 		writel(vmode->enci.macv_max_amp,
877 		       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
878 
879 		/* Video mode */
880 		writel(vmode->enci.video_prog_mode,
881 		       priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
882 		writel(vmode->enci.video_mode,
883 		       priv->io_base + _REG(ENCI_VIDEO_MODE));
884 
885 		/* Advanced Video Mode :
886 		 * Demux shifting 0x2
887 		 * Blank line end at line17/22
888 		 * High bandwidth Luma Filter
889 		 * Low bandwidth Chroma Filter
890 		 * Bypass luma low pass filter
891 		 * No macrovision on CSYNC
892 		 */
893 		writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
894 
895 		writel(vmode->enci.sch_adjust,
896 		       priv->io_base + _REG(ENCI_VIDEO_SCH));
897 
898 		/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
899 		writel(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
900 
901 		if (vmode->enci.yc_delay)
902 			writel(vmode->enci.yc_delay,
903 			       priv->io_base + _REG(ENCI_YC_DELAY));
904 
905 		/* UNreset Interlaced TV Encoder */
906 		writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
907 
908 		/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
909 		writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
910 
911 		/* Timings */
912 		writel(vmode->enci.pixel_start,
913 		       priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
914 		writel(vmode->enci.pixel_end,
915 		       priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
916 
917 		writel(vmode->enci.top_field_line_start,
918 		       priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
919 		writel(vmode->enci.top_field_line_end,
920 		       priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
921 
922 		writel(vmode->enci.bottom_field_line_start,
923 		       priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
924 		writel(vmode->enci.bottom_field_line_end,
925 		       priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
926 
927 		/* Select ENCI for VIU */
928 		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
929 
930 		/* Interlace video enable */
931 		writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
932 
933 		lines_f0 = mode->vback_porch.typ + mode->vactive.typ +
934 			   mode->vback_porch.typ + mode->vsync_len.typ;
935 		lines_f0 = lines_f0 >> 1;
936 		lines_f1 = lines_f0 + 1;
937 
938 		de_h_begin = modulo(readl(priv->io_base +
939 					_REG(ENCI_VFIFO2VD_PIXEL_START))
940 					+ venc_hdmi_latency,
941 				    total_pixels_venc);
942 		de_h_end  = modulo(de_h_begin + active_pixels_venc,
943 				   total_pixels_venc);
944 
945 		writel(de_h_begin,
946 		       priv->io_base + _REG(ENCI_DE_H_BEGIN));
947 		writel(de_h_end,
948 		       priv->io_base + _REG(ENCI_DE_H_END));
949 
950 		de_v_begin_even = readl(priv->io_base +
951 					_REG(ENCI_VFIFO2VD_LINE_TOP_START));
952 		de_v_end_even  = de_v_begin_even + mode->vactive.typ;
953 		de_v_begin_odd = readl(priv->io_base +
954 					_REG(ENCI_VFIFO2VD_LINE_BOT_START));
955 		de_v_end_odd = de_v_begin_odd + mode->vactive.typ;
956 
957 		writel(de_v_begin_even,
958 		       priv->io_base + _REG(ENCI_DE_V_BEGIN_EVEN));
959 		writel(de_v_end_even,
960 		       priv->io_base + _REG(ENCI_DE_V_END_EVEN));
961 		writel(de_v_begin_odd,
962 		       priv->io_base + _REG(ENCI_DE_V_BEGIN_ODD));
963 		writel(de_v_end_odd,
964 		       priv->io_base + _REG(ENCI_DE_V_END_ODD));
965 
966 		/* Program Hsync timing */
967 		hs_begin = de_h_end + front_porch_venc;
968 		if (de_h_end + front_porch_venc >= total_pixels_venc) {
969 			hs_begin -= total_pixels_venc;
970 			vs_adjust  = 1;
971 		} else {
972 			hs_begin = de_h_end + front_porch_venc;
973 			vs_adjust  = 0;
974 		}
975 
976 		hs_end = modulo(hs_begin + hsync_pixels_venc,
977 				total_pixels_venc);
978 		writel(hs_begin,
979 		       priv->io_base + _REG(ENCI_DVI_HSO_BEGIN));
980 		writel(hs_end,
981 		       priv->io_base + _REG(ENCI_DVI_HSO_END));
982 
983 		/* Program Vsync timing for even field */
984 		if (((de_v_end_odd - 1) + eof_lines + vs_adjust) >= lines_f1) {
985 			vs_bline_evn = (de_v_end_odd - 1)
986 					+ eof_lines
987 					+ vs_adjust
988 					- lines_f1;
989 			vs_eline_evn = vs_bline_evn + vsync_lines;
990 
991 			writel(vs_bline_evn,
992 			       priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
993 
994 			writel(vs_eline_evn,
995 			       priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN));
996 
997 			writel(hs_begin,
998 			       priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_EVN));
999 			writel(hs_begin,
1000 			       priv->io_base + _REG(ENCI_DVI_VSO_END_EVN));
1001 		} else {
1002 			vs_bline_odd = (de_v_end_odd - 1)
1003 					+ eof_lines
1004 					+ vs_adjust;
1005 
1006 			writel(vs_bline_odd,
1007 			       priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
1008 
1009 			writel(hs_begin,
1010 			       priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
1011 
1012 			if ((vs_bline_odd + vsync_lines) >= lines_f1) {
1013 				vs_eline_evn = vs_bline_odd
1014 						+ vsync_lines
1015 						- lines_f1;
1016 
1017 				writel(vs_eline_evn, priv->io_base
1018 				       + _REG(ENCI_DVI_VSO_ELINE_EVN));
1019 
1020 				writel(hs_begin, priv->io_base
1021 				       + _REG(ENCI_DVI_VSO_END_EVN));
1022 			} else {
1023 				vs_eline_odd = vs_bline_odd
1024 						+ vsync_lines;
1025 
1026 				writel(vs_eline_odd, priv->io_base
1027 				       + _REG(ENCI_DVI_VSO_ELINE_ODD));
1028 
1029 				writel(hs_begin, priv->io_base
1030 				       + _REG(ENCI_DVI_VSO_END_ODD));
1031 			}
1032 		}
1033 
1034 		/* Program Vsync timing for odd field */
1035 		if (((de_v_end_even - 1) + (eof_lines + 1)) >= lines_f0) {
1036 			vs_bline_odd = (de_v_end_even - 1)
1037 					+ (eof_lines + 1)
1038 					- lines_f0;
1039 			vs_eline_odd = vs_bline_odd + vsync_lines;
1040 
1041 			writel(vs_bline_odd,
1042 			       priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
1043 
1044 			writel(vs_eline_odd,
1045 			       priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD));
1046 
1047 			vso_begin_odd  = modulo(hs_begin
1048 						+ (total_pixels_venc >> 1),
1049 						total_pixels_venc);
1050 
1051 			writel(vso_begin_odd,
1052 			       priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
1053 			writel(vso_begin_odd,
1054 			       priv->io_base + _REG(ENCI_DVI_VSO_END_ODD));
1055 		} else {
1056 			vs_bline_evn = (de_v_end_even - 1)
1057 					+ (eof_lines + 1);
1058 
1059 			writel(vs_bline_evn,
1060 			       priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
1061 
1062 			vso_begin_evn  = modulo(hs_begin
1063 						+ (total_pixels_venc >> 1),
1064 						total_pixels_venc);
1065 
1066 			writel(vso_begin_evn, priv->io_base
1067 					+ _REG(ENCI_DVI_VSO_BEGIN_EVN));
1068 
1069 			if (vs_bline_evn + vsync_lines >= lines_f0) {
1070 				vs_eline_odd = vs_bline_evn
1071 						+ vsync_lines
1072 						- lines_f0;
1073 
1074 				writel(vs_eline_odd, priv->io_base
1075 						+ _REG(ENCI_DVI_VSO_ELINE_ODD));
1076 
1077 				writel(vso_begin_evn, priv->io_base
1078 						+ _REG(ENCI_DVI_VSO_END_ODD));
1079 			} else {
1080 				vs_eline_evn = vs_bline_evn + vsync_lines;
1081 
1082 				writel(vs_eline_evn, priv->io_base
1083 						+ _REG(ENCI_DVI_VSO_ELINE_EVN));
1084 
1085 				writel(vso_begin_evn, priv->io_base
1086 						+ _REG(ENCI_DVI_VSO_END_EVN));
1087 			}
1088 		}
1089 	} else {
1090 		writel(vmode->encp.dvi_settings,
1091 		       priv->io_base + _REG(VENC_DVI_SETTING));
1092 		writel(vmode->encp.video_mode,
1093 		       priv->io_base + _REG(ENCP_VIDEO_MODE));
1094 		writel(vmode->encp.video_mode_adv,
1095 		       priv->io_base + _REG(ENCP_VIDEO_MODE_ADV));
1096 		if (vmode->encp.video_prog_mode_present)
1097 			writel(vmode->encp.video_prog_mode,
1098 			       priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
1099 		if (vmode->encp.video_sync_mode_present)
1100 			writel(vmode->encp.video_sync_mode,
1101 			       priv->io_base + _REG(ENCP_VIDEO_SYNC_MODE));
1102 		if (vmode->encp.video_yc_dly_present)
1103 			writel(vmode->encp.video_yc_dly,
1104 			       priv->io_base + _REG(ENCP_VIDEO_YC_DLY));
1105 		if (vmode->encp.video_rgb_ctrl_present)
1106 			writel(vmode->encp.video_rgb_ctrl,
1107 			       priv->io_base + _REG(ENCP_VIDEO_RGB_CTRL));
1108 		if (vmode->encp.video_filt_ctrl_present)
1109 			writel(vmode->encp.video_filt_ctrl,
1110 			       priv->io_base + _REG(ENCP_VIDEO_FILT_CTRL));
1111 		if (vmode->encp.video_ofld_voav_ofst_present)
1112 			writel(vmode->encp.video_ofld_voav_ofst,
1113 			       priv->io_base
1114 			       + _REG(ENCP_VIDEO_OFLD_VOAV_OFST));
1115 		writel(vmode->encp.yfp1_htime,
1116 		       priv->io_base + _REG(ENCP_VIDEO_YFP1_HTIME));
1117 		writel(vmode->encp.yfp2_htime,
1118 		       priv->io_base + _REG(ENCP_VIDEO_YFP2_HTIME));
1119 		writel(vmode->encp.max_pxcnt,
1120 		       priv->io_base + _REG(ENCP_VIDEO_MAX_PXCNT));
1121 		writel(vmode->encp.hspuls_begin,
1122 		       priv->io_base + _REG(ENCP_VIDEO_HSPULS_BEGIN));
1123 		writel(vmode->encp.hspuls_end,
1124 		       priv->io_base + _REG(ENCP_VIDEO_HSPULS_END));
1125 		writel(vmode->encp.hspuls_switch,
1126 		       priv->io_base + _REG(ENCP_VIDEO_HSPULS_SWITCH));
1127 		writel(vmode->encp.vspuls_begin,
1128 		       priv->io_base + _REG(ENCP_VIDEO_VSPULS_BEGIN));
1129 		writel(vmode->encp.vspuls_end,
1130 		       priv->io_base + _REG(ENCP_VIDEO_VSPULS_END));
1131 		writel(vmode->encp.vspuls_bline,
1132 		       priv->io_base + _REG(ENCP_VIDEO_VSPULS_BLINE));
1133 		writel(vmode->encp.vspuls_eline,
1134 		       priv->io_base + _REG(ENCP_VIDEO_VSPULS_ELINE));
1135 		if (vmode->encp.eqpuls_begin_present)
1136 			writel(vmode->encp.eqpuls_begin,
1137 			       priv->io_base + _REG(ENCP_VIDEO_EQPULS_BEGIN));
1138 		if (vmode->encp.eqpuls_end_present)
1139 			writel(vmode->encp.eqpuls_end,
1140 			       priv->io_base + _REG(ENCP_VIDEO_EQPULS_END));
1141 		if (vmode->encp.eqpuls_bline_present)
1142 			writel(vmode->encp.eqpuls_bline,
1143 			       priv->io_base + _REG(ENCP_VIDEO_EQPULS_BLINE));
1144 		if (vmode->encp.eqpuls_eline_present)
1145 			writel(vmode->encp.eqpuls_eline,
1146 			       priv->io_base + _REG(ENCP_VIDEO_EQPULS_ELINE));
1147 		writel(vmode->encp.havon_begin,
1148 		       priv->io_base + _REG(ENCP_VIDEO_HAVON_BEGIN));
1149 		writel(vmode->encp.havon_end,
1150 		       priv->io_base + _REG(ENCP_VIDEO_HAVON_END));
1151 		writel(vmode->encp.vavon_bline,
1152 		       priv->io_base + _REG(ENCP_VIDEO_VAVON_BLINE));
1153 		writel(vmode->encp.vavon_eline,
1154 		       priv->io_base + _REG(ENCP_VIDEO_VAVON_ELINE));
1155 		writel(vmode->encp.hso_begin,
1156 		       priv->io_base + _REG(ENCP_VIDEO_HSO_BEGIN));
1157 		writel(vmode->encp.hso_end,
1158 		       priv->io_base + _REG(ENCP_VIDEO_HSO_END));
1159 		writel(vmode->encp.vso_begin,
1160 		       priv->io_base + _REG(ENCP_VIDEO_VSO_BEGIN));
1161 		writel(vmode->encp.vso_end,
1162 		       priv->io_base + _REG(ENCP_VIDEO_VSO_END));
1163 		writel(vmode->encp.vso_bline,
1164 		       priv->io_base + _REG(ENCP_VIDEO_VSO_BLINE));
1165 		if (vmode->encp.vso_eline_present)
1166 			writel(vmode->encp.vso_eline,
1167 			       priv->io_base + _REG(ENCP_VIDEO_VSO_ELINE));
1168 		if (vmode->encp.sy_val_present)
1169 			writel(vmode->encp.sy_val,
1170 			       priv->io_base + _REG(ENCP_VIDEO_SY_VAL));
1171 		if (vmode->encp.sy2_val_present)
1172 			writel(vmode->encp.sy2_val,
1173 			       priv->io_base + _REG(ENCP_VIDEO_SY2_VAL));
1174 		writel(vmode->encp.max_lncnt,
1175 		       priv->io_base + _REG(ENCP_VIDEO_MAX_LNCNT));
1176 
1177 		writel(1, priv->io_base + _REG(ENCP_VIDEO_EN));
1178 
1179 		/* Set DE signal's polarity is active high */
1180 		writel_bits(BIT(14), BIT(14),
1181 			    priv->io_base + _REG(ENCP_VIDEO_MODE));
1182 
1183 		/* Program DE timing */
1184 		de_h_begin = modulo(readl(priv->io_base +
1185 					_REG(ENCP_VIDEO_HAVON_BEGIN))
1186 					+ venc_hdmi_latency,
1187 				    total_pixels_venc);
1188 		de_h_end = modulo(de_h_begin + active_pixels_venc,
1189 				  total_pixels_venc);
1190 
1191 		writel(de_h_begin,
1192 		       priv->io_base + _REG(ENCP_DE_H_BEGIN));
1193 		writel(de_h_end,
1194 		       priv->io_base + _REG(ENCP_DE_H_END));
1195 
1196 		/* Program DE timing for even field */
1197 		de_v_begin_even = readl(priv->io_base
1198 						+ _REG(ENCP_VIDEO_VAVON_BLINE));
1199 		if (mode->flags & DISPLAY_FLAGS_INTERLACED)
1200 			de_v_end_even = de_v_begin_even +
1201 					(mode->vactive.typ / 2);
1202 		else
1203 			de_v_end_even = de_v_begin_even + mode->vactive.typ;
1204 
1205 		writel(de_v_begin_even,
1206 		       priv->io_base + _REG(ENCP_DE_V_BEGIN_EVEN));
1207 		writel(de_v_end_even,
1208 		       priv->io_base + _REG(ENCP_DE_V_END_EVEN));
1209 
1210 		/* Program DE timing for odd field if needed */
1211 		if (mode->flags & DISPLAY_FLAGS_INTERLACED) {
1212 			unsigned int ofld_voav_ofst =
1213 				readl(priv->io_base +
1214 					_REG(ENCP_VIDEO_OFLD_VOAV_OFST));
1215 			de_v_begin_odd = to_signed((ofld_voav_ofst & 0xf0) >> 4)
1216 					+ de_v_begin_even
1217 					+ ((mode->vfront_porch.typ +
1218 					    mode->vactive.typ +
1219 					    mode->vsync_len.typ - 1) / 2);
1220 			de_v_end_odd = de_v_begin_odd + (mode->vactive.typ / 2);
1221 
1222 			writel(de_v_begin_odd,
1223 			       priv->io_base + _REG(ENCP_DE_V_BEGIN_ODD));
1224 			writel(de_v_end_odd,
1225 			       priv->io_base + _REG(ENCP_DE_V_END_ODD));
1226 		}
1227 
1228 		/* Program Hsync timing */
1229 		if ((de_h_end + front_porch_venc) >= total_pixels_venc) {
1230 			hs_begin = de_h_end
1231 				   + front_porch_venc
1232 				   - total_pixels_venc;
1233 			vs_adjust  = 1;
1234 		} else {
1235 			hs_begin = de_h_end
1236 				   + front_porch_venc;
1237 			vs_adjust  = 0;
1238 		}
1239 
1240 		hs_end = modulo(hs_begin + hsync_pixels_venc,
1241 				total_pixels_venc);
1242 
1243 		writel(hs_begin,
1244 		       priv->io_base + _REG(ENCP_DVI_HSO_BEGIN));
1245 		writel(hs_end,
1246 		       priv->io_base + _REG(ENCP_DVI_HSO_END));
1247 
1248 		/* Program Vsync timing for even field */
1249 		if (de_v_begin_even >=
1250 				(sof_lines + vsync_lines + (1 - vs_adjust)))
1251 			vs_bline_evn = de_v_begin_even
1252 					- sof_lines
1253 					- vsync_lines
1254 					- (1 - vs_adjust);
1255 		else
1256 			vs_bline_evn = (mode->vfront_porch.typ +
1257 					mode->vactive.typ +
1258 					mode->vsync_len.typ) +
1259 					+ de_v_begin_even
1260 					- sof_lines
1261 					- vsync_lines
1262 					- (1 - vs_adjust);
1263 
1264 		vs_eline_evn = modulo(vs_bline_evn + vsync_lines,
1265 				      mode->hfront_porch.typ +
1266 				      mode->hactive.typ +
1267 				      mode->hsync_len.typ);
1268 
1269 		writel(vs_bline_evn,
1270 		       priv->io_base + _REG(ENCP_DVI_VSO_BLINE_EVN));
1271 		writel(vs_eline_evn,
1272 		       priv->io_base + _REG(ENCP_DVI_VSO_ELINE_EVN));
1273 
1274 		vso_begin_evn = hs_begin;
1275 		writel(vso_begin_evn,
1276 		       priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_EVN));
1277 		writel(vso_begin_evn,
1278 		       priv->io_base + _REG(ENCP_DVI_VSO_END_EVN));
1279 
1280 		/* Program Vsync timing for odd field if needed */
1281 		if (mode->flags & DISPLAY_FLAGS_INTERLACED) {
1282 			vs_bline_odd = (de_v_begin_odd - 1)
1283 					- sof_lines
1284 					- vsync_lines;
1285 			vs_eline_odd = (de_v_begin_odd - 1)
1286 					- vsync_lines;
1287 			vso_begin_odd  = modulo(hs_begin
1288 						+ (total_pixels_venc >> 1),
1289 						total_pixels_venc);
1290 
1291 			writel(vs_bline_odd,
1292 			       priv->io_base + _REG(ENCP_DVI_VSO_BLINE_ODD));
1293 			writel(vs_eline_odd,
1294 			       priv->io_base + _REG(ENCP_DVI_VSO_ELINE_ODD));
1295 			writel(vso_begin_odd,
1296 			       priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_ODD));
1297 			writel(vso_begin_odd,
1298 			       priv->io_base + _REG(ENCP_DVI_VSO_END_ODD));
1299 		}
1300 
1301 		/* Select ENCP for VIU */
1302 		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
1303 	}
1304 
1305 	writel((use_enci ? 1 : 2) |
1306 		       (mode->flags & DISPLAY_FLAGS_HSYNC_HIGH ? 1 << 2 : 0) |
1307 		       (mode->flags & DISPLAY_FLAGS_VSYNC_HIGH ? 1 << 3 : 0) |
1308 		       4 << 5 |
1309 		       (venc_repeat ? 1 << 8 : 0) |
1310 		       (hdmi_repeat ? 1 << 12 : 0),
1311 		       priv->io_base + _REG(VPU_HDMI_SETTING));
1312 }
1313 
1314 static void meson_venci_cvbs_mode_set(struct meson_vpu_priv *priv,
1315 				      struct meson_cvbs_enci_mode *mode)
1316 {
1317 	/* CVBS Filter settings */
1318 	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
1319 	writel(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2));
1320 
1321 	/* Digital Video Select : Interlace, clk27 clk, external */
1322 	writel(0, priv->io_base + _REG(VENC_DVI_SETTING));
1323 
1324 	/* Reset Video Mode */
1325 	writel(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
1326 	writel(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
1327 
1328 	/* Horizontal sync signal output */
1329 	writel(mode->hso_begin,
1330 	       priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
1331 	writel(mode->hso_end,
1332 	       priv->io_base + _REG(ENCI_SYNC_HSO_END));
1333 
1334 	/* Vertical Sync lines */
1335 	writel(mode->vso_even,
1336 	       priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
1337 	writel(mode->vso_odd,
1338 	       priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));
1339 
1340 	/* Macrovision max amplitude change */
1341 	writel(0x8100 + mode->macv_max_amp,
1342 	       priv->io_base + _REG(ENCI_MACV_MAX_AMP));
1343 
1344 	/* Video mode */
1345 	writel(mode->video_prog_mode,
1346 	       priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
1347 	writel(mode->video_mode,
1348 	       priv->io_base + _REG(ENCI_VIDEO_MODE));
1349 
1350 	/* Advanced Video Mode :
1351 	 * Demux shifting 0x2
1352 	 * Blank line end at line17/22
1353 	 * High bandwidth Luma Filter
1354 	 * Low bandwidth Chroma Filter
1355 	 * Bypass luma low pass filter
1356 	 * No macrovision on CSYNC
1357 	 */
1358 	writel(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));
1359 
1360 	writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
1361 
1362 	/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
1363 	writel(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
1364 
1365 	/* 0x3 Y, C, and Component Y delay */
1366 	writel(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));
1367 
1368 	/* Timings */
1369 	writel(mode->pixel_start,
1370 	       priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
1371 	writel(mode->pixel_end,
1372 	       priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));
1373 
1374 	writel(mode->top_field_line_start,
1375 	       priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
1376 	writel(mode->top_field_line_end,
1377 	       priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));
1378 
1379 	writel(mode->bottom_field_line_start,
1380 	       priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
1381 	writel(mode->bottom_field_line_end,
1382 	       priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));
1383 
1384 	/* Internal Venc, Internal VIU Sync, Internal Vencoder */
1385 	writel(0, priv->io_base + _REG(VENC_SYNC_ROUTE));
1386 
1387 	/* UNreset Interlaced TV Encoder */
1388 	writel(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
1389 
1390 	/* Enable Vfifo2vd, Y_Cb_Y_Cr select */
1391 	writel(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
1392 
1393 	/* Power UP Dacs */
1394 	writel(0, priv->io_base + _REG(VENC_VDAC_SETTING));
1395 
1396 	/* Video Upsampling */
1397 	writel(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
1398 	writel(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
1399 	writel(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
1400 
1401 	/* Select Interlace Y DACs */
1402 	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
1403 	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL1));
1404 	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL2));
1405 	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL3));
1406 	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL4));
1407 	writel(0, priv->io_base + _REG(VENC_VDAC_DACSEL5));
1408 
1409 	/* Select ENCI for VIU */
1410 	meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
1411 
1412 	/* Enable ENCI FIFO */
1413 	writel(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
1414 
1415 	/* Select ENCI DACs 0, 1, 4, and 5 */
1416 	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
1417 	writel(0x11, priv->io_base + _REG(ENCI_DACSEL_1));
1418 
1419 	/* Interlace video enable */
1420 	writel(1, priv->io_base + _REG(ENCI_VIDEO_EN));
1421 
1422 	/* Configure Video Saturation / Contrast / Brightness / Hue */
1423 	writel(mode->video_saturation,
1424 	       priv->io_base + _REG(ENCI_VIDEO_SAT));
1425 	writel(mode->video_contrast,
1426 	       priv->io_base + _REG(ENCI_VIDEO_CONT));
1427 	writel(mode->video_brightness,
1428 	       priv->io_base + _REG(ENCI_VIDEO_BRIGHT));
1429 	writel(mode->video_hue,
1430 	       priv->io_base + _REG(ENCI_VIDEO_HUE));
1431 
1432 	/* Enable DAC0 Filter */
1433 	writel(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
1434 	writel(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));
1435 
1436 	/* 0 in Macrovision register 0 */
1437 	writel(0, priv->io_base + _REG(ENCI_MACV_N0));
1438 
1439 	/* Analog Synchronization and color burst value adjust */
1440 	writel(mode->analog_sync_adj,
1441 	       priv->io_base + _REG(ENCI_SYNC_ADJ));
1442 
1443 	/* enable VDAC */
1444 	writel_bits(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
1445 
1446 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
1447 		hhi_write(HHI_VDAC_CNTL0, 1);
1448 	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
1449 		 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM))
1450 		hhi_write(HHI_VDAC_CNTL0, 0xf0001);
1451 
1452 	hhi_write(HHI_VDAC_CNTL1, 0);
1453 }
1454 
1455 void meson_vpu_setup_venc(struct udevice *dev,
1456 			  const struct display_timing *mode, bool is_cvbs)
1457 {
1458 	struct meson_vpu_priv *priv = dev_get_priv(dev);
1459 
1460 	if (is_cvbs)
1461 		return meson_venci_cvbs_mode_set(priv, &meson_cvbs_enci_pal);
1462 
1463 	meson_venc_hdmi_mode_set(priv, mode);
1464 }
1465