summaryrefslogblamecommitdiff
path: root/drivers/gpu/drm/meson/meson_venc.c
blob: f93c725b6f02d1abafa29db0c81d266126bd01bd (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
                                            



                                                        

   



                          
                      
                            

                       
 


                     

                                                         
  
                                                                            

                                             

                    
  

                                

               










                                                            














                                                                               

   
                   
                                                                     
                                                                     
                                                                     
                                                                     
                                                                     

                                                                     















































                                                    













































































                                                        
                                    


















                                                        
                                    


























































































































































































































































































































































































































































































                                                           





























































































































                                                           
















                                              
                                              


                                              


                                              

                                              


















                                                             

                                                                   
 


                                                                         
 

                                                          
 



                                                          


                                                  













                                                                           

                                                                        
 



















                                                                       

 






























                                                                           

                                                     
                                                                  

                                                 
                                             

























                                             
                
 






                                                                
                                                 
                                                           








                                                                               
                                 








































                                                                         
                                       









                                                                 




                                                                       




















                                                                             


                                                                               






                                                                            

                                        






                                              



                                                                          














                                                                                










                                                                        




















                                                                            

                                                                    





















































































































































































































































                                                                                

                                                              





















































































































                                                                                














                                                 

                                




                                                              
                                       









                                                                    








                                                       


                                                                 

                



                                                      




                                                               




















                                                                     


                                                                 






                                                                    

                                






                                      



                                                                  






























                                                                            










                                                                




                                                                   



























                                                                            












                                                                   

                                                                  





                                                                  

                                                            











                                                                      

                                                                        








                                                                                










                                                                             

                                                           
                                                                        



                                                     
                                                                  




                                                              
                               
                                                                 





                                                                







                                                                      

                                                          

                                                                    









                                                               
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2016 BayLibre, SAS
 * Author: Neil Armstrong <narmstrong@baylibre.com>
 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
 */

#include <linux/export.h>

#include <drm/drm_modes.h>

#include "meson_drv.h"
#include "meson_registers.h"
#include "meson_venc.h"
#include "meson_vpp.h"

/**
 * DOC: Video Encoder
 *
 * VENC Handle the pixels encoding to the output formats.
 * We handle the following encodings :
 *
 * - CVBS Encoding via the ENCI encoder and VDAC digital to analog converter
 * - TMDS/HDMI Encoding via ENCI_DIV and ENCP
 * - Setup of more clock rates for HDMI modes
 *
 * What is missing :
 *
 * - LCD Panel encoding via ENCL
 * - TV Panel encoding via ENCT
 *
 * VENC paths :
 *
 * .. code::
 *
 *          _____   _____   ____________________
 *   vd1---|     |-|     | | VENC     /---------|----VDAC
 *   vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|-|
 *   osd1--|     |-|     | | \                  | X--HDMI-TX
 *   osd2--|_____|-|_____| |  |\-ENCP--ENCP_DVI-|-|
 *                         |  |                 |
 *                         |  \--ENCL-----------|----LVDS
 *                         |____________________|
 *
 * The ENCI is designed for PAl or NTSC encoding and can go through the VDAC
 * directly for CVBS encoding or through the ENCI_DVI encoder for HDMI.
 * The ENCP is designed for Progressive encoding but can also generate
 * 1080i interlaced pixels, and was initialy desined to encode pixels for
 * VDAC to output RGB ou YUV analog outputs.
 * It's output is only used through the ENCP_DVI encoder for HDMI.
 * The ENCL LVDS encoder is not implemented.
 *
 * The ENCI and ENCP encoders needs specially defined parameters for each
 * supported mode and thus cannot be determined from standard video timings.
 *
 * The ENCI end ENCP DVI encoders are more generic and can generate any timings
 * from the pixel data generated by ENCI or ENCP, so can use the standard video
 * timings are source for HW parameters.
 */

/* HHI Registers */
#define HHI_GCLK_MPEG2		0x148 /* 0x52 offset in data sheet */
#define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */
#define HHI_VDAC_CNTL0_G12A	0x2EC /* 0xbb offset in data sheet */
#define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */
#define HHI_VDAC_CNTL1_G12A	0x2F0 /* 0xbc offset in data sheet */
#define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 offset in data sheet */

struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
	.mode_tag = MESON_VENC_MODE_CVBS_PAL,
	.hso_begin = 3,
	.hso_end = 129,
	.vso_even = 3,
	.vso_odd = 260,
	.macv_max_amp = 7,
	.video_prog_mode = 0xff,
	.video_mode = 0x13,
	.sch_adjust = 0x28,
	.yc_delay = 0x343,
	.pixel_start = 251,
	.pixel_end = 1691,
	.top_field_line_start = 22,
	.top_field_line_end = 310,
	.bottom_field_line_start = 23,
	.bottom_field_line_end = 311,
	.video_saturation = 9,
	.video_contrast = 0,
	.video_brightness = 0,
	.video_hue = 0,
	.analog_sync_adj = 0x8080,
};

struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
	.mode_tag = MESON_VENC_MODE_CVBS_NTSC,
	.hso_begin = 5,
	.hso_end = 129,
	.vso_even = 3,
	.vso_odd = 260,
	.macv_max_amp = 0xb,
	.video_prog_mode = 0xf0,
	.video_mode = 0x8,
	.sch_adjust = 0x20,
	.yc_delay = 0x333,
	.pixel_start = 227,
	.pixel_end = 1667,
	.top_field_line_start = 18,
	.top_field_line_end = 258,
	.bottom_field_line_start = 19,
	.bottom_field_line_end = 259,
	.video_saturation = 18,
	.video_contrast = 3,
	.video_brightness = 0,
	.video_hue = 0,
	.analog_sync_adj = 0x9c00,
};

union meson_hdmi_venc_mode {
	struct {
		unsigned int mode_tag;
		unsigned int hso_begin;
		unsigned int hso_end;
		unsigned int vso_even;
		unsigned int vso_odd;
		unsigned int macv_max_amp;
		unsigned int video_prog_mode;
		unsigned int video_mode;
		unsigned int sch_adjust;
		unsigned int yc_delay;
		unsigned int pixel_start;
		unsigned int pixel_end;
		unsigned int top_field_line_start;
		unsigned int top_field_line_end;
		unsigned int bottom_field_line_start;
		unsigned int bottom_field_line_end;
	} enci;
	struct {
		unsigned int dvi_settings;
		unsigned int video_mode;
		unsigned int video_mode_adv;
		unsigned int video_prog_mode;
		bool video_prog_mode_present;
		unsigned int video_sync_mode;
		bool video_sync_mode_present;
		unsigned int video_yc_dly;
		bool video_yc_dly_present;
		unsigned int video_rgb_ctrl;
		bool video_rgb_ctrl_present;
		unsigned int video_filt_ctrl;
		bool video_filt_ctrl_present;
		unsigned int video_ofld_voav_ofst;
		bool video_ofld_voav_ofst_present;
		unsigned int yfp1_htime;
		unsigned int yfp2_htime;
		unsigned int max_pxcnt;
		unsigned int hspuls_begin;
		unsigned int hspuls_end;
		unsigned int hspuls_switch;
		unsigned int vspuls_begin;
		unsigned int vspuls_end;
		unsigned int vspuls_bline;
		unsigned int vspuls_eline;
		unsigned int eqpuls_begin;
		bool eqpuls_begin_present;
		unsigned int eqpuls_end;
		bool eqpuls_end_present;
		unsigned int eqpuls_bline;
		bool eqpuls_bline_present;
		unsigned int eqpuls_eline;
		bool eqpuls_eline_present;
		unsigned int havon_begin;
		unsigned int havon_end;
		unsigned int vavon_bline;
		unsigned int vavon_eline;
		unsigned int hso_begin;
		unsigned int hso_end;
		unsigned int vso_begin;
		unsigned int vso_end;
		unsigned int vso_bline;
		unsigned int vso_eline;
		bool vso_eline_present;
		unsigned int sy_val;
		bool sy_val_present;
		unsigned int sy2_val;
		bool sy2_val_present;
		unsigned int max_lncnt;
	} encp;
};

union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
	.enci = {
		.hso_begin = 5,
		.hso_end = 129,
		.vso_even = 3,
		.vso_odd = 260,
		.macv_max_amp = 0xb,
		.video_prog_mode = 0xf0,
		.video_mode = 0x8,
		.sch_adjust = 0x20,
		.yc_delay = 0,
		.pixel_start = 227,
		.pixel_end = 1667,
		.top_field_line_start = 18,
		.top_field_line_end = 258,
		.bottom_field_line_start = 19,
		.bottom_field_line_end = 259,
	},
};

union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
	.enci = {
		.hso_begin = 3,
		.hso_end = 129,
		.vso_even = 3,
		.vso_odd = 260,
		.macv_max_amp = 0x7,
		.video_prog_mode = 0xff,
		.video_mode = 0x13,
		.sch_adjust = 0x28,
		.yc_delay = 0x333,
		.pixel_start = 251,
		.pixel_end = 1691,
		.top_field_line_start = 22,
		.top_field_line_end = 310,
		.bottom_field_line_start = 23,
		.bottom_field_line_end = 311,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
	.encp = {
		.dvi_settings = 0x21,
		.video_mode = 0x4000,
		.video_mode_adv = 0x9,
		.video_prog_mode = 0,
		.video_prog_mode_present = true,
		.video_sync_mode = 7,
		.video_sync_mode_present = true,
		/* video_yc_dly */
		/* video_rgb_ctrl */
		.video_filt_ctrl = 0x2052,
		.video_filt_ctrl_present = true,
		/* video_ofld_voav_ofst */
		.yfp1_htime = 244,
		.yfp2_htime = 1630,
		.max_pxcnt = 1715,
		.hspuls_begin = 0x22,
		.hspuls_end = 0xa0,
		.hspuls_switch = 88,
		.vspuls_begin = 0,
		.vspuls_end = 1589,
		.vspuls_bline = 0,
		.vspuls_eline = 5,
		.havon_begin = 249,
		.havon_end = 1689,
		.vavon_bline = 42,
		.vavon_eline = 521,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 3,
		.hso_end = 5,
		.vso_begin = 3,
		.vso_end = 5,
		.vso_bline = 0,
		/* vso_eline */
		.sy_val	= 8,
		.sy_val_present = true,
		.sy2_val = 0x1d8,
		.sy2_val_present = true,
		.max_lncnt = 524,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
	.encp = {
		.dvi_settings = 0x21,
		.video_mode = 0x4000,
		.video_mode_adv = 0x9,
		.video_prog_mode = 0,
		.video_prog_mode_present = true,
		.video_sync_mode = 7,
		.video_sync_mode_present = true,
		/* video_yc_dly */
		/* video_rgb_ctrl */
		.video_filt_ctrl = 0x52,
		.video_filt_ctrl_present = true,
		/* video_ofld_voav_ofst */
		.yfp1_htime = 235,
		.yfp2_htime = 1674,
		.max_pxcnt = 1727,
		.hspuls_begin = 0,
		.hspuls_end = 0x80,
		.hspuls_switch = 88,
		.vspuls_begin = 0,
		.vspuls_end = 1599,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 235,
		.havon_end = 1674,
		.vavon_bline = 44,
		.vavon_eline = 619,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 0x80,
		.hso_end = 0,
		.vso_begin = 0,
		.vso_end = 5,
		.vso_bline = 0,
		/* vso_eline */
		.sy_val	= 8,
		.sy_val_present = true,
		.sy2_val = 0x1d8,
		.sy2_val_present = true,
		.max_lncnt = 624,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
	.encp = {
		.dvi_settings = 0x2029,
		.video_mode = 0x4040,
		.video_mode_adv = 0x19,
		/* video_prog_mode */
		/* video_sync_mode */
		/* video_yc_dly */
		/* video_rgb_ctrl */
		/* video_filt_ctrl */
		/* video_ofld_voav_ofst */
		.yfp1_htime = 648,
		.yfp2_htime = 3207,
		.max_pxcnt = 3299,
		.hspuls_begin = 80,
		.hspuls_end = 240,
		.hspuls_switch = 80,
		.vspuls_begin = 688,
		.vspuls_end = 3248,
		.vspuls_bline = 4,
		.vspuls_eline = 8,
		.havon_begin = 648,
		.havon_end = 3207,
		.vavon_bline = 29,
		.vavon_eline = 748,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 256,
		.hso_end = 168,
		.vso_begin = 168,
		.vso_end = 256,
		.vso_bline = 0,
		.vso_eline = 5,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 749,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
	.encp = {
		.dvi_settings = 0x202d,
		.video_mode = 0x4040,
		.video_mode_adv = 0x19,
		.video_prog_mode = 0x100,
		.video_prog_mode_present = true,
		.video_sync_mode = 0x407,
		.video_sync_mode_present = true,
		.video_yc_dly = 0,
		.video_yc_dly_present = true,
		/* video_rgb_ctrl */
		/* video_filt_ctrl */
		/* video_ofld_voav_ofst */
		.yfp1_htime = 648,
		.yfp2_htime = 3207,
		.max_pxcnt = 3959,
		.hspuls_begin = 80,
		.hspuls_end = 240,
		.hspuls_switch = 80,
		.vspuls_begin = 688,
		.vspuls_end = 3248,
		.vspuls_bline = 4,
		.vspuls_eline = 8,
		.havon_begin = 648,
		.havon_end = 3207,
		.vavon_bline = 29,
		.vavon_eline = 748,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 128,
		.hso_end = 208,
		.vso_begin = 128,
		.vso_end = 128,
		.vso_bline = 0,
		.vso_eline = 5,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 749,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
	.encp = {
		.dvi_settings = 0x2029,
		.video_mode = 0x5ffc,
		.video_mode_adv = 0x19,
		.video_prog_mode = 0x100,
		.video_prog_mode_present = true,
		.video_sync_mode = 0x207,
		.video_sync_mode_present = true,
		/* video_yc_dly */
		/* video_rgb_ctrl */
		/* video_filt_ctrl */
		.video_ofld_voav_ofst = 0x11,
		.video_ofld_voav_ofst_present = true,
		.yfp1_htime = 516,
		.yfp2_htime = 4355,
		.max_pxcnt = 4399,
		.hspuls_begin = 88,
		.hspuls_end = 264,
		.hspuls_switch = 88,
		.vspuls_begin = 440,
		.vspuls_end = 2200,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 516,
		.havon_end = 4355,
		.vavon_bline = 20,
		.vavon_eline = 559,
		.eqpuls_begin = 2288,
		.eqpuls_begin_present = true,
		.eqpuls_end = 2464,
		.eqpuls_end_present = true,
		.eqpuls_bline = 0,
		.eqpuls_bline_present = true,
		.eqpuls_eline = 4,
		.eqpuls_eline_present = true,
		.hso_begin = 264,
		.hso_end = 176,
		.vso_begin = 88,
		.vso_end = 88,
		.vso_bline = 0,
		.vso_eline = 5,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 1124,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
	.encp = {
		.dvi_settings = 0x202d,
		.video_mode = 0x5ffc,
		.video_mode_adv = 0x19,
		.video_prog_mode = 0x100,
		.video_prog_mode_present = true,
		.video_sync_mode = 0x7,
		.video_sync_mode_present = true,
		/* video_yc_dly */
		/* video_rgb_ctrl */
		/* video_filt_ctrl */
		.video_ofld_voav_ofst = 0x11,
		.video_ofld_voav_ofst_present = true,
		.yfp1_htime = 526,
		.yfp2_htime = 4365,
		.max_pxcnt = 5279,
		.hspuls_begin = 88,
		.hspuls_end = 264,
		.hspuls_switch = 88,
		.vspuls_begin = 440,
		.vspuls_end = 2200,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 526,
		.havon_end = 4365,
		.vavon_bline = 20,
		.vavon_eline = 559,
		.eqpuls_begin = 2288,
		.eqpuls_begin_present = true,
		.eqpuls_end = 2464,
		.eqpuls_end_present = true,
		.eqpuls_bline = 0,
		.eqpuls_bline_present = true,
		.eqpuls_eline = 4,
		.eqpuls_eline_present = true,
		.hso_begin = 142,
		.hso_end = 230,
		.vso_begin = 142,
		.vso_end = 142,
		.vso_bline = 0,
		.vso_eline = 5,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 1124,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
	.encp = {
		.dvi_settings = 0xd,
		.video_mode = 0x4040,
		.video_mode_adv = 0x18,
		.video_prog_mode = 0x100,
		.video_prog_mode_present = true,
		.video_sync_mode = 0x7,
		.video_sync_mode_present = true,
		.video_yc_dly = 0,
		.video_yc_dly_present = true,
		.video_rgb_ctrl = 2,
		.video_rgb_ctrl_present = true,
		.video_filt_ctrl = 0x1052,
		.video_filt_ctrl_present = true,
		/* video_ofld_voav_ofst */
		.yfp1_htime = 271,
		.yfp2_htime = 2190,
		.max_pxcnt = 2749,
		.hspuls_begin = 44,
		.hspuls_end = 132,
		.hspuls_switch = 44,
		.vspuls_begin = 220,
		.vspuls_end = 2140,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 271,
		.havon_end = 2190,
		.vavon_bline = 41,
		.vavon_eline = 1120,
		/* eqpuls_begin */
		/* eqpuls_end */
		.eqpuls_bline = 0,
		.eqpuls_bline_present = true,
		.eqpuls_eline = 4,
		.eqpuls_eline_present = true,
		.hso_begin = 79,
		.hso_end = 123,
		.vso_begin = 79,
		.vso_end = 79,
		.vso_bline = 0,
		.vso_eline = 5,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 1124,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
	.encp = {
		.dvi_settings = 0x1,
		.video_mode = 0x4040,
		.video_mode_adv = 0x18,
		.video_prog_mode = 0x100,
		.video_prog_mode_present = true,
		/* video_sync_mode */
		/* video_yc_dly */
		/* video_rgb_ctrl */
		.video_filt_ctrl = 0x1052,
		.video_filt_ctrl_present = true,
		/* video_ofld_voav_ofst */
		.yfp1_htime = 140,
		.yfp2_htime = 2060,
		.max_pxcnt = 2199,
		.hspuls_begin = 2156,
		.hspuls_end = 44,
		.hspuls_switch = 44,
		.vspuls_begin = 140,
		.vspuls_end = 2059,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 148,
		.havon_end = 2067,
		.vavon_bline = 41,
		.vavon_eline = 1120,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 44,
		.hso_end = 2156,
		.vso_begin = 2100,
		.vso_end = 2164,
		.vso_bline = 0,
		.vso_eline = 5,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 1124,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
	.encp = {
		.dvi_settings = 0xd,
		.video_mode = 0x4040,
		.video_mode_adv = 0x18,
		.video_prog_mode = 0x100,
		.video_prog_mode_present = true,
		.video_sync_mode = 0x7,
		.video_sync_mode_present = true,
		.video_yc_dly = 0,
		.video_yc_dly_present = true,
		.video_rgb_ctrl = 2,
		.video_rgb_ctrl_present = true,
		/* video_filt_ctrl */
		/* video_ofld_voav_ofst */
		.yfp1_htime = 271,
		.yfp2_htime = 2190,
		.max_pxcnt = 2639,
		.hspuls_begin = 44,
		.hspuls_end = 132,
		.hspuls_switch = 44,
		.vspuls_begin = 220,
		.vspuls_end = 2140,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 271,
		.havon_end = 2190,
		.vavon_bline = 41,
		.vavon_eline = 1120,
		/* eqpuls_begin */
		/* eqpuls_end */
		.eqpuls_bline = 0,
		.eqpuls_bline_present = true,
		.eqpuls_eline = 4,
		.eqpuls_eline_present = true,
		.hso_begin = 79,
		.hso_end = 123,
		.vso_begin = 79,
		.vso_end = 79,
		.vso_bline = 0,
		.vso_eline = 5,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 1124,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
	.encp = {
		.dvi_settings = 0x1,
		.video_mode = 0x4040,
		.video_mode_adv = 0x18,
		.video_prog_mode = 0x100,
		.video_prog_mode_present = true,
		/* video_sync_mode */
		/* video_yc_dly */
		/* video_rgb_ctrl */
		.video_filt_ctrl = 0x1052,
		.video_filt_ctrl_present = true,
		/* video_ofld_voav_ofst */
		.yfp1_htime = 140,
		.yfp2_htime = 2060,
		.max_pxcnt = 2199,
		.hspuls_begin = 2156,
		.hspuls_end = 44,
		.hspuls_switch = 44,
		.vspuls_begin = 140,
		.vspuls_end = 2059,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 148,
		.havon_end = 2067,
		.vavon_bline = 41,
		.vavon_eline = 1120,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 44,
		.hso_end = 2156,
		.vso_begin = 2100,
		.vso_end = 2164,
		.vso_bline = 0,
		.vso_eline = 5,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 1124,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = {
	.encp = {
		.dvi_settings = 0x1,
		.video_mode = 0x4040,
		.video_mode_adv = 0x8,
		/* video_sync_mode */
		/* video_yc_dly */
		/* video_rgb_ctrl */
		.video_filt_ctrl = 0x1000,
		.video_filt_ctrl_present = true,
		/* video_ofld_voav_ofst */
		.yfp1_htime = 140,
		.yfp2_htime = 140+3840,
		.max_pxcnt = 3840+1660-1,
		.hspuls_begin = 2156+1920,
		.hspuls_end = 44,
		.hspuls_switch = 44,
		.vspuls_begin = 140,
		.vspuls_end = 2059+1920,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 148,
		.havon_end = 3987,
		.vavon_bline = 89,
		.vavon_eline = 2248,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 44,
		.hso_end = 2156+1920,
		.vso_begin = 2100+1920,
		.vso_end = 2164+1920,
		.vso_bline = 51,
		.vso_eline = 53,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 2249,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = {
	.encp = {
		.dvi_settings = 0x1,
		.video_mode = 0x4040,
		.video_mode_adv = 0x8,
		/* video_sync_mode */
		/* video_yc_dly */
		/* video_rgb_ctrl */
		.video_filt_ctrl = 0x1000,
		.video_filt_ctrl_present = true,
		/* video_ofld_voav_ofst */
		.yfp1_htime = 140,
		.yfp2_htime = 140+3840,
		.max_pxcnt = 3840+1440-1,
		.hspuls_begin = 2156+1920,
		.hspuls_end = 44,
		.hspuls_switch = 44,
		.vspuls_begin = 140,
		.vspuls_end = 2059+1920,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 148,
		.havon_end = 3987,
		.vavon_bline = 89,
		.vavon_eline = 2248,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 44,
		.hso_end = 2156+1920,
		.vso_begin = 2100+1920,
		.vso_end = 2164+1920,
		.vso_bline = 51,
		.vso_eline = 53,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 2249,
	},
};

union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = {
	.encp = {
		.dvi_settings = 0x1,
		.video_mode = 0x4040,
		.video_mode_adv = 0x8,
		/* video_sync_mode */
		/* video_yc_dly */
		/* video_rgb_ctrl */
		.video_filt_ctrl = 0x1000,
		.video_filt_ctrl_present = true,
		/* video_ofld_voav_ofst */
		.yfp1_htime = 140,
		.yfp2_htime = 140+3840,
		.max_pxcnt = 3840+560-1,
		.hspuls_begin = 2156+1920,
		.hspuls_end = 44,
		.hspuls_switch = 44,
		.vspuls_begin = 140,
		.vspuls_end = 2059+1920,
		.vspuls_bline = 0,
		.vspuls_eline = 4,
		.havon_begin = 148,
		.havon_end = 3987,
		.vavon_bline = 89,
		.vavon_eline = 2248,
		/* eqpuls_begin */
		/* eqpuls_end */
		/* eqpuls_bline */
		/* eqpuls_eline */
		.hso_begin = 44,
		.hso_end = 2156+1920,
		.vso_begin = 2100+1920,
		.vso_end = 2164+1920,
		.vso_bline = 51,
		.vso_eline = 53,
		.vso_eline_present = true,
		/* sy_val */
		/* sy2_val */
		.max_lncnt = 2249,
	},
};

struct meson_hdmi_venc_vic_mode {
	unsigned int vic;
	union meson_hdmi_venc_mode *mode;
} meson_hdmi_venc_vic_modes[] = {
	{ 6, &meson_hdmi_enci_mode_480i },
	{ 7, &meson_hdmi_enci_mode_480i },
	{ 21, &meson_hdmi_enci_mode_576i },
	{ 22, &meson_hdmi_enci_mode_576i },
	{ 2, &meson_hdmi_encp_mode_480p },
	{ 3, &meson_hdmi_encp_mode_480p },
	{ 17, &meson_hdmi_encp_mode_576p },
	{ 18, &meson_hdmi_encp_mode_576p },
	{ 4, &meson_hdmi_encp_mode_720p60 },
	{ 19, &meson_hdmi_encp_mode_720p50 },
	{ 5, &meson_hdmi_encp_mode_1080i60 },
	{ 20, &meson_hdmi_encp_mode_1080i50 },
	{ 32, &meson_hdmi_encp_mode_1080p24 },
	{ 33, &meson_hdmi_encp_mode_1080p50 },
	{ 34, &meson_hdmi_encp_mode_1080p30 },
	{ 31, &meson_hdmi_encp_mode_1080p50 },
	{ 16, &meson_hdmi_encp_mode_1080p60 },
	{ 93, &meson_hdmi_encp_mode_2160p24 },
	{ 94, &meson_hdmi_encp_mode_2160p25 },
	{ 95, &meson_hdmi_encp_mode_2160p30 },
	{ 96, &meson_hdmi_encp_mode_2160p25 },
	{ 97, &meson_hdmi_encp_mode_2160p30 },
	{ 0, NULL}, /* sentinel */
};

static signed int to_signed(unsigned int a)
{
	if (a <= 7)
		return a;
	else
		return a - 16;
}

static unsigned long modulo(unsigned long a, unsigned long b)
{
	if (a >= b)
		return a - b;
	else
		return a;
}

enum drm_mode_status
meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
{
	if (mode->flags & ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC |
			    DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))
		return MODE_BAD;

	if (mode->hdisplay < 640 || mode->hdisplay > 1920)
		return MODE_BAD_HVALUE;

	if (mode->vdisplay < 480 || mode->vdisplay > 1200)
		return MODE_BAD_VVALUE;

	return MODE_OK;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode);

bool meson_venc_hdmi_supported_vic(int vic)
{
	struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;

	while (vmode->vic && vmode->mode) {
		if (vmode->vic == vic)
			return true;
		vmode++;
	}

	return false;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);

void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
				   union meson_hdmi_venc_mode *dmt_mode)
{
	memset(dmt_mode, 0, sizeof(*dmt_mode));

	dmt_mode->encp.dvi_settings = 0x21;
	dmt_mode->encp.video_mode = 0x4040;
	dmt_mode->encp.video_mode_adv = 0x18;
	dmt_mode->encp.max_pxcnt = mode->htotal - 1;
	dmt_mode->encp.havon_begin = mode->htotal - mode->hsync_start;
	dmt_mode->encp.havon_end = dmt_mode->encp.havon_begin +
				   mode->hdisplay - 1;
	dmt_mode->encp.vavon_bline = mode->vtotal - mode->vsync_start;
	dmt_mode->encp.vavon_eline = dmt_mode->encp.vavon_bline +
				     mode->vdisplay - 1;
	dmt_mode->encp.hso_begin = 0;
	dmt_mode->encp.hso_end = mode->hsync_end - mode->hsync_start;
	dmt_mode->encp.vso_begin = 30;
	dmt_mode->encp.vso_end = 50;
	dmt_mode->encp.vso_bline = 0;
	dmt_mode->encp.vso_eline = mode->vsync_end - mode->vsync_start;
	dmt_mode->encp.vso_eline_present = true;
	dmt_mode->encp.max_lncnt = mode->vtotal - 1;
}

static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic)
{
	struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;

	while (vmode->vic && vmode->mode) {
		if (vmode->vic == vic)
			return vmode->mode;
		vmode++;
	}

	return NULL;
}

bool meson_venc_hdmi_venc_repeat(int vic)
{
	/* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
	if (vic == 6 || vic == 7 || /* 480i */
	    vic == 21 || vic == 22 || /* 576i */
	    vic == 17 || vic == 18 || /* 576p */
	    vic == 2 || vic == 3 || /* 480p */
	    vic == 4 || /* 720p60 */
	    vic == 19 || /* 720p50 */
	    vic == 5 || /* 1080i60 */
	    vic == 20)	/* 1080i50 */
		return true;

	return false;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);

void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
			      unsigned int ycrcb_map,
			      bool yuv420_mode,
			      const struct drm_display_mode *mode)
{
	union meson_hdmi_venc_mode *vmode = NULL;
	union meson_hdmi_venc_mode vmode_dmt;
	bool use_enci = false;
	bool venc_repeat = false;
	bool hdmi_repeat = false;
	unsigned int venc_hdmi_latency = 2;
	unsigned long total_pixels_venc = 0;
	unsigned long active_pixels_venc = 0;
	unsigned long front_porch_venc = 0;
	unsigned long hsync_pixels_venc = 0;
	unsigned long de_h_begin = 0;
	unsigned long de_h_end = 0;
	unsigned long de_v_begin_even = 0;
	unsigned long de_v_end_even = 0;
	unsigned long de_v_begin_odd = 0;
	unsigned long de_v_end_odd = 0;
	unsigned long hs_begin = 0;
	unsigned long hs_end = 0;
	unsigned long vs_adjust = 0;
	unsigned long vs_bline_evn = 0;
	unsigned long vs_eline_evn = 0;
	unsigned long vs_bline_odd = 0;
	unsigned long vs_eline_odd = 0;
	unsigned long vso_begin_evn = 0;
	unsigned long vso_begin_odd = 0;
	unsigned int eof_lines;
	unsigned int sof_lines;
	unsigned int vsync_lines;
	u32 reg;

	/* Use VENCI for 480i and 576i and double HDMI pixels */
	if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
		hdmi_repeat = true;
		use_enci = true;
		venc_hdmi_latency = 1;
	}

	if (meson_venc_hdmi_supported_vic(vic)) {
		vmode = meson_venc_hdmi_get_vic_vmode(vic);
		if (!vmode) {
			dev_err(priv->dev, "%s: Fatal Error, unsupported mode "
				DRM_MODE_FMT "\n", __func__,
				DRM_MODE_ARG(mode));
			return;
		}
	} else {
		meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
		vmode = &vmode_dmt;
		use_enci = false;
	}

	/* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
	if (meson_venc_hdmi_venc_repeat(vic))
		venc_repeat = true;

	eof_lines = mode->vsync_start - mode->vdisplay;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		eof_lines /= 2;
	sof_lines = mode->vtotal - mode->vsync_end;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		sof_lines /= 2;
	vsync_lines = mode->vsync_end - mode->vsync_start;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		vsync_lines /= 2;

	total_pixels_venc = mode->htotal;
	if (hdmi_repeat)
		total_pixels_venc /= 2;
	if (venc_repeat)
		total_pixels_venc *= 2;

	active_pixels_venc = mode->hdisplay;
	if (hdmi_repeat)
		active_pixels_venc /= 2;
	if (venc_repeat)
		active_pixels_venc *= 2;

	front_porch_venc = (mode->hsync_start - mode->hdisplay);
	if (hdmi_repeat)
		front_porch_venc /= 2;
	if (venc_repeat)
		front_porch_venc *= 2;

	hsync_pixels_venc = (mode->hsync_end - mode->hsync_start);
	if (hdmi_repeat)
		hsync_pixels_venc /= 2;
	if (venc_repeat)
		hsync_pixels_venc *= 2;

	/* Disable VDACs */
	writel_bits_relaxed(0xff, 0xff,
			priv->io_base + _REG(VENC_VDAC_SETTING));

	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));

	if (use_enci) {
		unsigned int lines_f0;
		unsigned int lines_f1;

		/* CVBS Filter settings */
		writel_relaxed(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
			       priv->io_base + _REG(ENCI_CFILT_CTRL));
		writel_relaxed(ENCI_CFILT_CMPT_CR_DLY(2) |
			       ENCI_CFILT_CMPT_CB_DLY(1),
			       priv->io_base + _REG(ENCI_CFILT_CTRL2));

		/* Digital Video Select : Interlace, clk27 clk, external */
		writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));

		/* Reset Video Mode */
		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));

		/* Horizontal sync signal output */
		writel_relaxed(vmode->enci.hso_begin,
				priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
		writel_relaxed(vmode->enci.hso_end,
				priv->io_base + _REG(ENCI_SYNC_HSO_END));

		/* Vertical Sync lines */
		writel_relaxed(vmode->enci.vso_even,
				priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
		writel_relaxed(vmode->enci.vso_odd,
				priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));

		/* Macrovision max amplitude change */
		writel_relaxed(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
			       ENCI_MACV_MAX_AMP_VAL(vmode->enci.macv_max_amp),
			       priv->io_base + _REG(ENCI_MACV_MAX_AMP));

		/* Video mode */
		writel_relaxed(vmode->enci.video_prog_mode,
				priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
		writel_relaxed(vmode->enci.video_mode,
				priv->io_base + _REG(ENCI_VIDEO_MODE));

		/*
		 * Advanced Video Mode :
		 * Demux shifting 0x2
		 * Blank line end at line17/22
		 * High bandwidth Luma Filter
		 * Low bandwidth Chroma Filter
		 * Bypass luma low pass filter
		 * No macrovision on CSYNC
		 */
		writel_relaxed(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
			       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
			       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
			       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));

		writel(vmode->enci.sch_adjust,
				priv->io_base + _REG(ENCI_VIDEO_SCH));

		/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
		writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));

		if (vmode->enci.yc_delay)
			writel_relaxed(vmode->enci.yc_delay,
					priv->io_base + _REG(ENCI_YC_DELAY));


		/* UNreset Interlaced TV Encoder */
		writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));

		/*
		 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
		 * Corresponding value:
		 * Y  => 00 or 10
		 * Cb => 01
		 * Cr => 11
		 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
		 */
		writel_relaxed(ENCI_VFIFO2VD_CTL_ENABLE |
			       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
			       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));

		/* Timings */
		writel_relaxed(vmode->enci.pixel_start,
			priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
		writel_relaxed(vmode->enci.pixel_end,
			priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));

		writel_relaxed(vmode->enci.top_field_line_start,
			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
		writel_relaxed(vmode->enci.top_field_line_end,
			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));

		writel_relaxed(vmode->enci.bottom_field_line_start,
			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
		writel_relaxed(vmode->enci.bottom_field_line_end,
			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));

		/* Select ENCI for VIU */
		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);

		/* Interlace video enable */
		writel_relaxed(ENCI_VIDEO_EN_ENABLE,
			       priv->io_base + _REG(ENCI_VIDEO_EN));

		lines_f0 = mode->vtotal >> 1;
		lines_f1 = lines_f0 + 1;

		de_h_begin = modulo(readl_relaxed(priv->io_base +
					_REG(ENCI_VFIFO2VD_PIXEL_START))
					+ venc_hdmi_latency,
				    total_pixels_venc);
		de_h_end  = modulo(de_h_begin + active_pixels_venc,
				   total_pixels_venc);

		writel_relaxed(de_h_begin,
				priv->io_base + _REG(ENCI_DE_H_BEGIN));
		writel_relaxed(de_h_end,
				priv->io_base + _REG(ENCI_DE_H_END));

		de_v_begin_even = readl_relaxed(priv->io_base +
					_REG(ENCI_VFIFO2VD_LINE_TOP_START));
		de_v_end_even  = de_v_begin_even + mode->vdisplay;
		de_v_begin_odd = readl_relaxed(priv->io_base +
					_REG(ENCI_VFIFO2VD_LINE_BOT_START));
		de_v_end_odd = de_v_begin_odd + mode->vdisplay;

		writel_relaxed(de_v_begin_even,
				priv->io_base + _REG(ENCI_DE_V_BEGIN_EVEN));
		writel_relaxed(de_v_end_even,
				priv->io_base + _REG(ENCI_DE_V_END_EVEN));
		writel_relaxed(de_v_begin_odd,
				priv->io_base + _REG(ENCI_DE_V_BEGIN_ODD));
		writel_relaxed(de_v_end_odd,
				priv->io_base + _REG(ENCI_DE_V_END_ODD));

		/* Program Hsync timing */
		hs_begin = de_h_end + front_porch_venc;
		if (de_h_end + front_porch_venc >= total_pixels_venc) {
			hs_begin -= total_pixels_venc;
			vs_adjust  = 1;
		} else {
			hs_begin = de_h_end + front_porch_venc;
			vs_adjust  = 0;
		}

		hs_end = modulo(hs_begin + hsync_pixels_venc,
				total_pixels_venc);
		writel_relaxed(hs_begin,
				priv->io_base + _REG(ENCI_DVI_HSO_BEGIN));
		writel_relaxed(hs_end,
				priv->io_base + _REG(ENCI_DVI_HSO_END));

		/* Program Vsync timing for even field */
		if (((de_v_end_odd - 1) + eof_lines + vs_adjust) >= lines_f1) {
			vs_bline_evn = (de_v_end_odd - 1)
					+ eof_lines
					+ vs_adjust
					- lines_f1;
			vs_eline_evn = vs_bline_evn + vsync_lines;

			writel_relaxed(vs_bline_evn,
				priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));

			writel_relaxed(vs_eline_evn,
				priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN));

			writel_relaxed(hs_begin,
				priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_EVN));
			writel_relaxed(hs_begin,
				priv->io_base + _REG(ENCI_DVI_VSO_END_EVN));
		} else {
			vs_bline_odd = (de_v_end_odd - 1)
					+ eof_lines
					+ vs_adjust;

			writel_relaxed(vs_bline_odd,
				priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));

			writel_relaxed(hs_begin,
				priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));

			if ((vs_bline_odd + vsync_lines) >= lines_f1) {
				vs_eline_evn = vs_bline_odd
						+ vsync_lines
						- lines_f1;

				writel_relaxed(vs_eline_evn, priv->io_base
						+ _REG(ENCI_DVI_VSO_ELINE_EVN));

				writel_relaxed(hs_begin, priv->io_base
						+ _REG(ENCI_DVI_VSO_END_EVN));
			} else {
				vs_eline_odd = vs_bline_odd
						+ vsync_lines;

				writel_relaxed(vs_eline_odd, priv->io_base
						+ _REG(ENCI_DVI_VSO_ELINE_ODD));

				writel_relaxed(hs_begin, priv->io_base
						+ _REG(ENCI_DVI_VSO_END_ODD));
			}
		}

		/* Program Vsync timing for odd field */
		if (((de_v_end_even - 1) + (eof_lines + 1)) >= lines_f0) {
			vs_bline_odd = (de_v_end_even - 1)
					+ (eof_lines + 1)
					- lines_f0;
			vs_eline_odd = vs_bline_odd + vsync_lines;

			writel_relaxed(vs_bline_odd,
				priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));

			writel_relaxed(vs_eline_odd,
				priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD));

			vso_begin_odd  = modulo(hs_begin
						+ (total_pixels_venc >> 1),
						total_pixels_venc);

			writel_relaxed(vso_begin_odd,
				priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
			writel_relaxed(vso_begin_odd,
				priv->io_base + _REG(ENCI_DVI_VSO_END_ODD));
		} else {
			vs_bline_evn = (de_v_end_even - 1)
					+ (eof_lines + 1);

			writel_relaxed(vs_bline_evn,
				priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));

			vso_begin_evn  = modulo(hs_begin
						+ (total_pixels_venc >> 1),
						total_pixels_venc);

			writel_relaxed(vso_begin_evn, priv->io_base
					+ _REG(ENCI_DVI_VSO_BEGIN_EVN));

			if (vs_bline_evn + vsync_lines >= lines_f0) {
				vs_eline_odd = vs_bline_evn
						+ vsync_lines
						- lines_f0;

				writel_relaxed(vs_eline_odd, priv->io_base
						+ _REG(ENCI_DVI_VSO_ELINE_ODD));

				writel_relaxed(vso_begin_evn, priv->io_base
						+ _REG(ENCI_DVI_VSO_END_ODD));
			} else {
				vs_eline_evn = vs_bline_evn + vsync_lines;

				writel_relaxed(vs_eline_evn, priv->io_base
						+ _REG(ENCI_DVI_VSO_ELINE_EVN));

				writel_relaxed(vso_begin_evn, priv->io_base
						+ _REG(ENCI_DVI_VSO_END_EVN));
			}
		}
	} else {
		writel_relaxed(vmode->encp.dvi_settings,
				priv->io_base + _REG(VENC_DVI_SETTING));
		writel_relaxed(vmode->encp.video_mode,
				priv->io_base + _REG(ENCP_VIDEO_MODE));
		writel_relaxed(vmode->encp.video_mode_adv,
				priv->io_base + _REG(ENCP_VIDEO_MODE_ADV));
		if (vmode->encp.video_prog_mode_present)
			writel_relaxed(vmode->encp.video_prog_mode,
				priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
		if (vmode->encp.video_sync_mode_present)
			writel_relaxed(vmode->encp.video_sync_mode,
				priv->io_base + _REG(ENCP_VIDEO_SYNC_MODE));
		if (vmode->encp.video_yc_dly_present)
			writel_relaxed(vmode->encp.video_yc_dly,
				priv->io_base + _REG(ENCP_VIDEO_YC_DLY));
		if (vmode->encp.video_rgb_ctrl_present)
			writel_relaxed(vmode->encp.video_rgb_ctrl,
				priv->io_base + _REG(ENCP_VIDEO_RGB_CTRL));
		if (vmode->encp.video_filt_ctrl_present)
			writel_relaxed(vmode->encp.video_filt_ctrl,
				priv->io_base + _REG(ENCP_VIDEO_FILT_CTRL));
		if (vmode->encp.video_ofld_voav_ofst_present)
			writel_relaxed(vmode->encp.video_ofld_voav_ofst,
				priv->io_base
				+ _REG(ENCP_VIDEO_OFLD_VOAV_OFST));
		writel_relaxed(vmode->encp.yfp1_htime,
				priv->io_base + _REG(ENCP_VIDEO_YFP1_HTIME));
		writel_relaxed(vmode->encp.yfp2_htime,
				priv->io_base + _REG(ENCP_VIDEO_YFP2_HTIME));
		writel_relaxed(vmode->encp.max_pxcnt,
				priv->io_base + _REG(ENCP_VIDEO_MAX_PXCNT));
		writel_relaxed(vmode->encp.hspuls_begin,
				priv->io_base + _REG(ENCP_VIDEO_HSPULS_BEGIN));
		writel_relaxed(vmode->encp.hspuls_end,
				priv->io_base + _REG(ENCP_VIDEO_HSPULS_END));
		writel_relaxed(vmode->encp.hspuls_switch,
				priv->io_base + _REG(ENCP_VIDEO_HSPULS_SWITCH));
		writel_relaxed(vmode->encp.vspuls_begin,
				priv->io_base + _REG(ENCP_VIDEO_VSPULS_BEGIN));
		writel_relaxed(vmode->encp.vspuls_end,
				priv->io_base + _REG(ENCP_VIDEO_VSPULS_END));
		writel_relaxed(vmode->encp.vspuls_bline,
				priv->io_base + _REG(ENCP_VIDEO_VSPULS_BLINE));
		writel_relaxed(vmode->encp.vspuls_eline,
				priv->io_base + _REG(ENCP_VIDEO_VSPULS_ELINE));
		if (vmode->encp.eqpuls_begin_present)
			writel_relaxed(vmode->encp.eqpuls_begin,
				priv->io_base + _REG(ENCP_VIDEO_EQPULS_BEGIN));
		if (vmode->encp.eqpuls_end_present)
			writel_relaxed(vmode->encp.eqpuls_end,
				priv->io_base + _REG(ENCP_VIDEO_EQPULS_END));
		if (vmode->encp.eqpuls_bline_present)
			writel_relaxed(vmode->encp.eqpuls_bline,
				priv->io_base + _REG(ENCP_VIDEO_EQPULS_BLINE));
		if (vmode->encp.eqpuls_eline_present)
			writel_relaxed(vmode->encp.eqpuls_eline,
				priv->io_base + _REG(ENCP_VIDEO_EQPULS_ELINE));
		writel_relaxed(vmode->encp.havon_begin,
				priv->io_base + _REG(ENCP_VIDEO_HAVON_BEGIN));
		writel_relaxed(vmode->encp.havon_end,
				priv->io_base + _REG(ENCP_VIDEO_HAVON_END));
		writel_relaxed(vmode->encp.vavon_bline,
				priv->io_base + _REG(ENCP_VIDEO_VAVON_BLINE));
		writel_relaxed(vmode->encp.vavon_eline,
				priv->io_base + _REG(ENCP_VIDEO_VAVON_ELINE));
		writel_relaxed(vmode->encp.hso_begin,
				priv->io_base + _REG(ENCP_VIDEO_HSO_BEGIN));
		writel_relaxed(vmode->encp.hso_end,
				priv->io_base + _REG(ENCP_VIDEO_HSO_END));
		writel_relaxed(vmode->encp.vso_begin,
				priv->io_base + _REG(ENCP_VIDEO_VSO_BEGIN));
		writel_relaxed(vmode->encp.vso_end,
				priv->io_base + _REG(ENCP_VIDEO_VSO_END));
		writel_relaxed(vmode->encp.vso_bline,
				priv->io_base + _REG(ENCP_VIDEO_VSO_BLINE));
		if (vmode->encp.vso_eline_present)
			writel_relaxed(vmode->encp.vso_eline,
				priv->io_base + _REG(ENCP_VIDEO_VSO_ELINE));
		if (vmode->encp.sy_val_present)
			writel_relaxed(vmode->encp.sy_val,
				priv->io_base + _REG(ENCP_VIDEO_SY_VAL));
		if (vmode->encp.sy2_val_present)
			writel_relaxed(vmode->encp.sy2_val,
				priv->io_base + _REG(ENCP_VIDEO_SY2_VAL));
		writel_relaxed(vmode->encp.max_lncnt,
				priv->io_base + _REG(ENCP_VIDEO_MAX_LNCNT));

		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));

		/* Set DE signal’s polarity is active high */
		writel_bits_relaxed(ENCP_VIDEO_MODE_DE_V_HIGH,
				    ENCP_VIDEO_MODE_DE_V_HIGH,
				    priv->io_base + _REG(ENCP_VIDEO_MODE));

		/* Program DE timing */
		de_h_begin = modulo(readl_relaxed(priv->io_base +
					_REG(ENCP_VIDEO_HAVON_BEGIN))
					+ venc_hdmi_latency,
				    total_pixels_venc);
		de_h_end = modulo(de_h_begin + active_pixels_venc,
				  total_pixels_venc);

		writel_relaxed(de_h_begin,
				priv->io_base + _REG(ENCP_DE_H_BEGIN));
		writel_relaxed(de_h_end,
				priv->io_base + _REG(ENCP_DE_H_END));

		/* Program DE timing for even field */
		de_v_begin_even = readl_relaxed(priv->io_base
						+ _REG(ENCP_VIDEO_VAVON_BLINE));
		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
			de_v_end_even = de_v_begin_even +
					(mode->vdisplay / 2);
		else
			de_v_end_even = de_v_begin_even + mode->vdisplay;

		writel_relaxed(de_v_begin_even,
				priv->io_base + _REG(ENCP_DE_V_BEGIN_EVEN));
		writel_relaxed(de_v_end_even,
				priv->io_base + _REG(ENCP_DE_V_END_EVEN));

		/* Program DE timing for odd field if needed */
		if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
			unsigned int ofld_voav_ofst =
				readl_relaxed(priv->io_base +
					_REG(ENCP_VIDEO_OFLD_VOAV_OFST));
			de_v_begin_odd = to_signed((ofld_voav_ofst & 0xf0) >> 4)
						+ de_v_begin_even
						+ ((mode->vtotal - 1) / 2);
			de_v_end_odd = de_v_begin_odd + (mode->vdisplay / 2);

			writel_relaxed(de_v_begin_odd,
				priv->io_base + _REG(ENCP_DE_V_BEGIN_ODD));
			writel_relaxed(de_v_end_odd,
				priv->io_base + _REG(ENCP_DE_V_END_ODD));
		}

		/* Program Hsync timing */
		if ((de_h_end + front_porch_venc) >= total_pixels_venc) {
			hs_begin = de_h_end
				   + front_porch_venc
				   - total_pixels_venc;
			vs_adjust  = 1;
		} else {
			hs_begin = de_h_end
				   + front_porch_venc;
			vs_adjust  = 0;
		}

		hs_end = modulo(hs_begin + hsync_pixels_venc,
				total_pixels_venc);

		writel_relaxed(hs_begin,
				priv->io_base + _REG(ENCP_DVI_HSO_BEGIN));
		writel_relaxed(hs_end,
				priv->io_base + _REG(ENCP_DVI_HSO_END));

		/* Program Vsync timing for even field */
		if (de_v_begin_even >=
				(sof_lines + vsync_lines + (1 - vs_adjust)))
			vs_bline_evn = de_v_begin_even
					- sof_lines
					- vsync_lines
					- (1 - vs_adjust);
		else
			vs_bline_evn = mode->vtotal
					+ de_v_begin_even
					- sof_lines
					- vsync_lines
					- (1 - vs_adjust);

		vs_eline_evn = modulo(vs_bline_evn + vsync_lines,
					mode->vtotal);

		writel_relaxed(vs_bline_evn,
				priv->io_base + _REG(ENCP_DVI_VSO_BLINE_EVN));
		writel_relaxed(vs_eline_evn,
				priv->io_base + _REG(ENCP_DVI_VSO_ELINE_EVN));

		vso_begin_evn = hs_begin;
		writel_relaxed(vso_begin_evn,
				priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_EVN));
		writel_relaxed(vso_begin_evn,
				priv->io_base + _REG(ENCP_DVI_VSO_END_EVN));

		/* Program Vsync timing for odd field if needed */
		if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
			vs_bline_odd = (de_v_begin_odd - 1)
					- sof_lines
					- vsync_lines;
			vs_eline_odd = (de_v_begin_odd - 1)
					- vsync_lines;
			vso_begin_odd  = modulo(hs_begin
						+ (total_pixels_venc >> 1),
						total_pixels_venc);

			writel_relaxed(vs_bline_odd,
				priv->io_base + _REG(ENCP_DVI_VSO_BLINE_ODD));
			writel_relaxed(vs_eline_odd,
				priv->io_base + _REG(ENCP_DVI_VSO_ELINE_ODD));
			writel_relaxed(vso_begin_odd,
				priv->io_base + _REG(ENCP_DVI_VSO_BEGIN_ODD));
			writel_relaxed(vso_begin_odd,
				priv->io_base + _REG(ENCP_DVI_VSO_END_ODD));
		}

		/* Select ENCP for VIU */
		meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
	}

	/* Set VPU HDMI setting */
	/* Select ENCP or ENCI data to HDMI */
	if (use_enci)
		reg = VPU_HDMI_ENCI_DATA_TO_HDMI;
	else
		reg = VPU_HDMI_ENCP_DATA_TO_HDMI;

	/* Invert polarity of HSYNC from VENC */
	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
		reg |= VPU_HDMI_INV_HSYNC;

	/* Invert polarity of VSYNC from VENC */
	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
		reg |= VPU_HDMI_INV_VSYNC;

	/* Output data format */
	reg |= ycrcb_map;

	/*
	 * Write rate to the async FIFO between VENC and HDMI.
	 * One write every 2 wr_clk.
	 */
	if (venc_repeat || yuv420_mode)
		reg |= VPU_HDMI_WR_RATE(2);

	/*
	 * Read rate to the async FIFO between VENC and HDMI.
	 * One read every 2 wr_clk.
	 */
	if (hdmi_repeat)
		reg |= VPU_HDMI_RD_RATE(2);

	writel_relaxed(reg, priv->io_base + _REG(VPU_HDMI_SETTING));

	priv->venc.hdmi_repeat = hdmi_repeat;
	priv->venc.venc_repeat = venc_repeat;
	priv->venc.hdmi_use_enci = use_enci;

	priv->venc.current_mode = MESON_VENC_MODE_HDMI;
}
EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);

void meson_venci_cvbs_mode_set(struct meson_drm *priv,
			       struct meson_cvbs_enci_mode *mode)
{
	u32 reg;

	if (mode->mode_tag == priv->venc.current_mode)
		return;

	/* CVBS Filter settings */
	writel_relaxed(ENCI_CFILT_CMPT_SEL_HIGH | 0x10,
		       priv->io_base + _REG(ENCI_CFILT_CTRL));
	writel_relaxed(ENCI_CFILT_CMPT_CR_DLY(2) |
		       ENCI_CFILT_CMPT_CB_DLY(1),
		       priv->io_base + _REG(ENCI_CFILT_CTRL2));

	/* Digital Video Select : Interlace, clk27 clk, external */
	writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));

	/* Reset Video Mode */
	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE));
	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));

	/* Horizontal sync signal output */
	writel_relaxed(mode->hso_begin,
			priv->io_base + _REG(ENCI_SYNC_HSO_BEGIN));
	writel_relaxed(mode->hso_end,
			priv->io_base + _REG(ENCI_SYNC_HSO_END));

	/* Vertical Sync lines */
	writel_relaxed(mode->vso_even,
			priv->io_base + _REG(ENCI_SYNC_VSO_EVNLN));
	writel_relaxed(mode->vso_odd,
			priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN));

	/* Macrovision max amplitude change */
	writel_relaxed(ENCI_MACV_MAX_AMP_ENABLE_CHANGE |
		       ENCI_MACV_MAX_AMP_VAL(mode->macv_max_amp),
		       priv->io_base + _REG(ENCI_MACV_MAX_AMP));

	/* Video mode */
	writel_relaxed(mode->video_prog_mode,
			priv->io_base + _REG(VENC_VIDEO_PROG_MODE));
	writel_relaxed(mode->video_mode,
			priv->io_base + _REG(ENCI_VIDEO_MODE));

	/*
	 * Advanced Video Mode :
	 * Demux shifting 0x2
	 * Blank line end at line17/22
	 * High bandwidth Luma Filter
	 * Low bandwidth Chroma Filter
	 * Bypass luma low pass filter
	 * No macrovision on CSYNC
	 */
	writel_relaxed(ENCI_VIDEO_MODE_ADV_DMXMD(2) |
		       ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 |
		       ENCI_VIDEO_MODE_ADV_YBW_HIGH,
		       priv->io_base + _REG(ENCI_VIDEO_MODE_ADV));

	writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));

	/* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
	writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));

	/* 0x3 Y, C, and Component Y delay */
	writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));

	/* Timings */
	writel_relaxed(mode->pixel_start,
			priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_START));
	writel_relaxed(mode->pixel_end,
			priv->io_base + _REG(ENCI_VFIFO2VD_PIXEL_END));

	writel_relaxed(mode->top_field_line_start,
			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_START));
	writel_relaxed(mode->top_field_line_end,
			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_TOP_END));

	writel_relaxed(mode->bottom_field_line_start,
			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_START));
	writel_relaxed(mode->bottom_field_line_end,
			priv->io_base + _REG(ENCI_VFIFO2VD_LINE_BOT_END));

	/* Internal Venc, Internal VIU Sync, Internal Vencoder */
	writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE));

	/* UNreset Interlaced TV Encoder */
	writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));

	/*
	 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
	 * Corresponding value:
	 * Y  => 00 or 10
	 * Cb => 01
	 * Cr => 11
	 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
	 */
	writel_relaxed(ENCI_VFIFO2VD_CTL_ENABLE |
		       ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
		       priv->io_base + _REG(ENCI_VFIFO2VD_CTL));

	/* Power UP Dacs */
	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING));

	/* Video Upsampling */
	/*
	 * CTRL0, CTRL1 and CTRL2:
	 * Filter0: input data sample every 2 cloks
	 * Filter1: filtering and upsample enable
	 */
	reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN |
		VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN;

	/*
	 * Upsample CTRL0:
	 * Interlace High Bandwidth Luma
	 */
	writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg,
		       priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));

	/*
	 * Upsample CTRL1:
	 * Interlace Pb
	 */
	writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg,
		       priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));

	/*
	 * Upsample CTRL2:
	 * Interlace R
	 */
	writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg,
		       priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));

	/* Select Interlace Y DACs */
	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0));
	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL1));
	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL2));
	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL3));
	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL4));
	writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL5));

	/* Select ENCI for VIU */
	meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);

	/* Enable ENCI FIFO */
	writel_relaxed(VENC_VDAC_FIFO_EN_ENCI_ENABLE,
		       priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));

	/* Select ENCI DACs 0, 1, 4, and 5 */
	writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0));
	writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1));

	/* Interlace video enable */
	writel_relaxed(ENCI_VIDEO_EN_ENABLE,
		       priv->io_base + _REG(ENCI_VIDEO_EN));

	/* Configure Video Saturation / Contrast / Brightness / Hue */
	writel_relaxed(mode->video_saturation,
			priv->io_base + _REG(ENCI_VIDEO_SAT));
	writel_relaxed(mode->video_contrast,
			priv->io_base + _REG(ENCI_VIDEO_CONT));
	writel_relaxed(mode->video_brightness,
			priv->io_base + _REG(ENCI_VIDEO_BRIGHT));
	writel_relaxed(mode->video_hue,
			priv->io_base + _REG(ENCI_VIDEO_HUE));

	/* Enable DAC0 Filter */
	writel_relaxed(VENC_VDAC_DAC0_FILT_CTRL0_EN,
		       priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0));
	writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1));

	/* 0 in Macrovision register 0 */
	writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0));

	/* Analog Synchronization and color burst value adjust */
	writel_relaxed(mode->analog_sync_adj,
			priv->io_base + _REG(ENCI_SYNC_ADJ));

	priv->venc.current_mode = mode->mode_tag;
}

/* Returns the current ENCI field polarity */
unsigned int meson_venci_get_field(struct meson_drm *priv)
{
	return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29);
}

void meson_venc_enable_vsync(struct meson_drm *priv)
{
	writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN,
		       priv->io_base + _REG(VENC_INTCTRL));
	regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
}

void meson_venc_disable_vsync(struct meson_drm *priv)
{
	regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), 0);
	writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
}

void meson_venc_init(struct meson_drm *priv)
{
	/* Disable CVBS VDAC */
	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
		regmap_write(priv->hhi, HHI_VDAC_CNTL0_G12A, 0);
		regmap_write(priv->hhi, HHI_VDAC_CNTL1_G12A, 8);
	} else {
		regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
		regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
	}

	/* Power Down Dacs */
	writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));

	/* Disable HDMI PHY */
	regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);

	/* Disable HDMI */
	writel_bits_relaxed(VPU_HDMI_ENCI_DATA_TO_HDMI |
			    VPU_HDMI_ENCP_DATA_TO_HDMI, 0,
			    priv->io_base + _REG(VPU_HDMI_SETTING));

	/* Disable all encoders */
	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
	writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));

	/* Disable VSync IRQ */
	meson_venc_disable_vsync(priv);

	priv->venc.current_mode = MESON_VENC_MODE_NONE;
}