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