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
71struct 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
95struct 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
119union 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
191static 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
211static 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
231static 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
277static 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
323static 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
365static 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
410static 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
459static 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
508static 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
557static 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
601static 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
649static 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
693static 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
735static 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
777static 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
819static 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
848static signed int to_signed(unsigned int a)
849{
850	if (a <= 7)
851		return a;
852	else
853		return a - 16;
854}
855
856static 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
864enum drm_mode_status
865meson_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}
879EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode);
880
881bool 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}
893EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
894
895static 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
920static 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
933bool 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}
948EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);
949
950void 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}
1560EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);
1561
1562static 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
1581static 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
1619void 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
1629void 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}
1759EXPORT_SYMBOL_GPL(meson_venc_mipi_dsi_mode_set);
1760
1761void 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 */
1944unsigned 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
1949void 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
1963void 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
1969void 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