1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2016 BayLibre, SAS
5 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
8 #include <linux/bitfield.h>
9 #include <linux/export.h>
10 #include <linux/iopoll.h>
12 #include <drm/drm_modes.h>
14 #include "meson_drv.h"
15 #include "meson_registers.h"
16 #include "meson_venc.h"
17 #include "meson_vpp.h"
22 * VENC Handle the pixels encoding to the output formats.
23 * We handle the following encodings :
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
31 * - LCD Panel encoding via ENCL
32 * - TV Panel encoding via ENCT
38 * _____ _____ ____________________
39 * vd1---| |-| | | VENC /---------|----VDAC
40 * vd2---| VIU |-| VPP |-|-----ENCI/-ENCI_DVI-|-|
41 * osd1--| |-| | | \ | X--HDMI-TX
42 * osd2--|_____|-|_____| | |\-ENCP--ENCP_DVI-|-|
44 * | \--ENCL-----------|----LVDS
45 * |____________________|
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.
55 * The ENCI and ENCP encoders needs specially defined parameters for each
56 * supported mode and thus cannot be determined from standard video timings.
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.
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 */
71 struct meson_cvbs_enci_mode meson_cvbs_enci_pal = {
72 .mode_tag = MESON_VENC_MODE_CVBS_PAL,
78 .video_prog_mode = 0xff,
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,
90 .video_brightness = 0,
92 .analog_sync_adj = 0x8080,
95 struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
96 .mode_tag = MESON_VENC_MODE_CVBS_NTSC,
102 .video_prog_mode = 0xf0,
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,
114 .video_brightness = 0,
116 .analog_sync_adj = 0x9c00,
119 union meson_hdmi_venc_mode {
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;
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;
185 unsigned int sy2_val;
186 bool sy2_val_present;
187 unsigned int max_lncnt;
191 static union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = {
198 .video_prog_mode = 0xf0,
204 .top_field_line_start = 18,
205 .top_field_line_end = 258,
206 .bottom_field_line_start = 19,
207 .bottom_field_line_end = 259,
211 static union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = {
218 .video_prog_mode = 0xff,
224 .top_field_line_start = 22,
225 .top_field_line_end = 310,
226 .bottom_field_line_start = 23,
227 .bottom_field_line_end = 311,
231 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_480p = {
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,
242 .video_filt_ctrl = 0x2052,
243 .video_filt_ctrl_present = true,
244 /* video_ofld_voav_ofst */
248 .hspuls_begin = 0x22,
270 .sy_val_present = true,
272 .sy2_val_present = true,
277 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_576p = {
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,
288 .video_filt_ctrl = 0x52,
289 .video_filt_ctrl_present = true,
290 /* video_ofld_voav_ofst */
316 .sy_val_present = true,
318 .sy2_val_present = true,
323 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p60 = {
325 .dvi_settings = 0x2029,
326 .video_mode = 0x4040,
327 .video_mode_adv = 0x19,
328 /* video_prog_mode */
329 /* video_sync_mode */
332 /* video_filt_ctrl */
333 /* video_ofld_voav_ofst */
358 .vso_eline_present = true,
365 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_720p50 = {
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,
375 .video_yc_dly_present = true,
377 /* video_filt_ctrl */
378 /* video_ofld_voav_ofst */
403 .vso_eline_present = true,
410 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i60 = {
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,
421 /* video_filt_ctrl */
422 .video_ofld_voav_ofst = 0x11,
423 .video_ofld_voav_ofst_present = true,
438 .eqpuls_begin = 2288,
439 .eqpuls_begin_present = true,
441 .eqpuls_end_present = true,
443 .eqpuls_bline_present = true,
445 .eqpuls_eline_present = true,
452 .vso_eline_present = true,
459 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080i50 = {
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,
470 /* video_filt_ctrl */
471 .video_ofld_voav_ofst = 0x11,
472 .video_ofld_voav_ofst_present = true,
487 .eqpuls_begin = 2288,
488 .eqpuls_begin_present = true,
490 .eqpuls_end_present = true,
492 .eqpuls_bline_present = true,
494 .eqpuls_eline_present = true,
501 .vso_eline_present = true,
508 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p24 = {
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,
518 .video_yc_dly_present = true,
520 .video_rgb_ctrl_present = true,
521 .video_filt_ctrl = 0x1052,
522 .video_filt_ctrl_present = true,
523 /* video_ofld_voav_ofst */
541 .eqpuls_bline_present = true,
543 .eqpuls_eline_present = true,
550 .vso_eline_present = true,
557 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p30 = {
560 .video_mode = 0x4040,
561 .video_mode_adv = 0x18,
562 .video_prog_mode = 0x100,
563 .video_prog_mode_present = true,
564 /* video_sync_mode */
567 .video_filt_ctrl = 0x1052,
568 .video_filt_ctrl_present = true,
569 /* video_ofld_voav_ofst */
573 .hspuls_begin = 2156,
594 .vso_eline_present = true,
601 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p50 = {
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,
611 .video_yc_dly_present = true,
613 .video_rgb_ctrl_present = true,
614 /* video_filt_ctrl */
615 /* video_ofld_voav_ofst */
633 .eqpuls_bline_present = true,
635 .eqpuls_eline_present = true,
642 .vso_eline_present = true,
649 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = {
652 .video_mode = 0x4040,
653 .video_mode_adv = 0x18,
654 .video_prog_mode = 0x100,
655 .video_prog_mode_present = true,
656 /* video_sync_mode */
659 .video_filt_ctrl = 0x1052,
660 .video_filt_ctrl_present = true,
661 /* video_ofld_voav_ofst */
665 .hspuls_begin = 2156,
686 .vso_eline_present = true,
693 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = {
696 .video_mode = 0x4040,
697 .video_mode_adv = 0x8,
698 /* video_sync_mode */
701 .video_filt_ctrl = 0x1000,
702 .video_filt_ctrl_present = true,
703 /* video_ofld_voav_ofst */
705 .yfp2_htime = 140+3840,
706 .max_pxcnt = 3840+1660-1,
707 .hspuls_begin = 2156+1920,
711 .vspuls_end = 2059+1920,
723 .hso_end = 2156+1920,
724 .vso_begin = 2100+1920,
725 .vso_end = 2164+1920,
728 .vso_eline_present = true,
735 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = {
738 .video_mode = 0x4040,
739 .video_mode_adv = 0x8,
740 /* video_sync_mode */
743 .video_filt_ctrl = 0x1000,
744 .video_filt_ctrl_present = true,
745 /* video_ofld_voav_ofst */
747 .yfp2_htime = 140+3840,
748 .max_pxcnt = 3840+1440-1,
749 .hspuls_begin = 2156+1920,
753 .vspuls_end = 2059+1920,
765 .hso_end = 2156+1920,
766 .vso_begin = 2100+1920,
767 .vso_end = 2164+1920,
770 .vso_eline_present = true,
777 static union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = {
780 .video_mode = 0x4040,
781 .video_mode_adv = 0x8,
782 /* video_sync_mode */
785 .video_filt_ctrl = 0x1000,
786 .video_filt_ctrl_present = true,
787 /* video_ofld_voav_ofst */
789 .yfp2_htime = 140+3840,
790 .max_pxcnt = 3840+560-1,
791 .hspuls_begin = 2156+1920,
795 .vspuls_end = 2059+1920,
807 .hso_end = 2156+1920,
808 .vso_begin = 2100+1920,
809 .vso_end = 2164+1920,
812 .vso_eline_present = true,
819 static struct meson_hdmi_venc_vic_mode {
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 */
848 static signed int to_signed(unsigned int a)
856 static unsigned long modulo(unsigned long a, unsigned long b)
865 meson_venc_hdmi_supported_mode(const struct drm_display_mode *mode)
867 if (mode->flags & ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC |
868 DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC))
871 if (mode->hdisplay < 400 || mode->hdisplay > 1920)
872 return MODE_BAD_HVALUE;
874 if (mode->vdisplay < 480 || mode->vdisplay > 1920)
875 return MODE_BAD_VVALUE;
879 EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_mode);
881 bool meson_venc_hdmi_supported_vic(int vic)
883 struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
885 while (vmode->vic && vmode->mode) {
886 if (vmode->vic == vic)
893 EXPORT_SYMBOL_GPL(meson_venc_hdmi_supported_vic);
895 static void meson_venc_hdmi_get_dmt_vmode(const struct drm_display_mode *mode,
896 union meson_hdmi_venc_mode *dmt_mode)
898 memset(dmt_mode, 0, sizeof(*dmt_mode));
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 +
907 dmt_mode->encp.vavon_bline = mode->vtotal - mode->vsync_start;
908 dmt_mode->encp.vavon_eline = dmt_mode->encp.vavon_bline +
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;
920 static union meson_hdmi_venc_mode *meson_venc_hdmi_get_vic_vmode(int vic)
922 struct meson_hdmi_venc_vic_mode *vmode = meson_hdmi_venc_vic_modes;
924 while (vmode->vic && vmode->mode) {
925 if (vmode->vic == vic)
933 bool meson_venc_hdmi_venc_repeat(int vic)
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 */
948 EXPORT_SYMBOL_GPL(meson_venc_hdmi_venc_repeat);
950 void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
951 unsigned int ycrcb_map,
953 const struct drm_display_mode *mode)
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;
985 /* Use VENCI for 480i and 576i and double HDMI pixels */
986 if (mode->flags & DRM_MODE_FLAG_DBLCLK) {
989 venc_hdmi_latency = 1;
992 if (meson_venc_hdmi_supported_vic(vic)) {
993 vmode = meson_venc_hdmi_get_vic_vmode(vic);
995 dev_err(priv->dev, "%s: Fatal Error, unsupported mode "
996 DRM_MODE_FMT "\n", __func__,
1001 meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);
1006 /* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */
1007 if (meson_venc_hdmi_venc_repeat(vic))
1010 eof_lines = mode->vsync_start - mode->vdisplay;
1011 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1013 sof_lines = mode->vtotal - mode->vsync_end;
1014 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1016 vsync_lines = mode->vsync_end - mode->vsync_start;
1017 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
1020 total_pixels_venc = mode->htotal;
1022 total_pixels_venc /= 2;
1024 total_pixels_venc *= 2;
1026 active_pixels_venc = mode->hdisplay;
1028 active_pixels_venc /= 2;
1030 active_pixels_venc *= 2;
1032 front_porch_venc = (mode->hsync_start - mode->hdisplay);
1034 front_porch_venc /= 2;
1036 front_porch_venc *= 2;
1038 hsync_pixels_venc = (mode->hsync_end - mode->hsync_start);
1040 hsync_pixels_venc /= 2;
1042 hsync_pixels_venc *= 2;
1045 writel_bits_relaxed(0xff, 0xff,
1046 priv->io_base + _REG(VENC_VDAC_SETTING));
1048 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
1049 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
1052 unsigned int lines_f0;
1053 unsigned int lines_f1;
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));
1062 /* Digital Video Select : Interlace, clk27 clk, external */
1063 writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
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));
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));
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));
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));
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));
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
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));
1106 writel(vmode->enci.sch_adjust,
1107 priv->io_base + _REG(ENCI_VIDEO_SCH));
1109 /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
1110 writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
1112 if (vmode->enci.yc_delay)
1113 writel_relaxed(vmode->enci.yc_delay,
1114 priv->io_base + _REG(ENCI_YC_DELAY));
1117 /* UNreset Interlaced TV Encoder */
1118 writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
1121 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
1122 * Corresponding value:
1126 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
1128 writel_relaxed(ENCI_VFIFO2VD_CTL_ENABLE |
1129 ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
1130 priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
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));
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));
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));
1148 /* Select ENCI for VIU */
1149 meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
1151 /* Interlace video enable */
1152 writel_relaxed(ENCI_VIDEO_EN_ENABLE,
1153 priv->io_base + _REG(ENCI_VIDEO_EN));
1155 lines_f0 = mode->vtotal >> 1;
1156 lines_f1 = lines_f0 + 1;
1158 de_h_begin = modulo(readl_relaxed(priv->io_base +
1159 _REG(ENCI_VFIFO2VD_PIXEL_START))
1160 + venc_hdmi_latency,
1162 de_h_end = modulo(de_h_begin + active_pixels_venc,
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));
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;
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));
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;
1192 hs_begin = de_h_end + front_porch_venc;
1196 hs_end = modulo(hs_begin + hsync_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));
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)
1209 vs_eline_evn = vs_bline_evn + vsync_lines;
1211 writel_relaxed(vs_bline_evn,
1212 priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
1214 writel_relaxed(vs_eline_evn,
1215 priv->io_base + _REG(ENCI_DVI_VSO_ELINE_EVN));
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));
1222 vs_bline_odd = (de_v_end_odd - 1)
1226 writel_relaxed(vs_bline_odd,
1227 priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
1229 writel_relaxed(hs_begin,
1230 priv->io_base + _REG(ENCI_DVI_VSO_BEGIN_ODD));
1232 if ((vs_bline_odd + vsync_lines) >= lines_f1) {
1233 vs_eline_evn = vs_bline_odd
1237 writel_relaxed(vs_eline_evn, priv->io_base
1238 + _REG(ENCI_DVI_VSO_ELINE_EVN));
1240 writel_relaxed(hs_begin, priv->io_base
1241 + _REG(ENCI_DVI_VSO_END_EVN));
1243 vs_eline_odd = vs_bline_odd
1246 writel_relaxed(vs_eline_odd, priv->io_base
1247 + _REG(ENCI_DVI_VSO_ELINE_ODD));
1249 writel_relaxed(hs_begin, priv->io_base
1250 + _REG(ENCI_DVI_VSO_END_ODD));
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)
1259 vs_eline_odd = vs_bline_odd + vsync_lines;
1261 writel_relaxed(vs_bline_odd,
1262 priv->io_base + _REG(ENCI_DVI_VSO_BLINE_ODD));
1264 writel_relaxed(vs_eline_odd,
1265 priv->io_base + _REG(ENCI_DVI_VSO_ELINE_ODD));
1267 vso_begin_odd = modulo(hs_begin
1268 + (total_pixels_venc >> 1),
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));
1276 vs_bline_evn = (de_v_end_even - 1)
1279 writel_relaxed(vs_bline_evn,
1280 priv->io_base + _REG(ENCI_DVI_VSO_BLINE_EVN));
1282 vso_begin_evn = modulo(hs_begin
1283 + (total_pixels_venc >> 1),
1286 writel_relaxed(vso_begin_evn, priv->io_base
1287 + _REG(ENCI_DVI_VSO_BEGIN_EVN));
1289 if (vs_bline_evn + vsync_lines >= lines_f0) {
1290 vs_eline_odd = vs_bline_evn
1294 writel_relaxed(vs_eline_odd, priv->io_base
1295 + _REG(ENCI_DVI_VSO_ELINE_ODD));
1297 writel_relaxed(vso_begin_evn, priv->io_base
1298 + _REG(ENCI_DVI_VSO_END_ODD));
1300 vs_eline_evn = vs_bline_evn + vsync_lines;
1302 writel_relaxed(vs_eline_evn, priv->io_base
1303 + _REG(ENCI_DVI_VSO_ELINE_EVN));
1305 writel_relaxed(vso_begin_evn, priv->io_base
1306 + _REG(ENCI_DVI_VSO_END_EVN));
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,
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));
1397 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
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));
1404 /* Program DE timing */
1405 de_h_begin = modulo(readl_relaxed(priv->io_base +
1406 _REG(ENCP_VIDEO_HAVON_BEGIN))
1407 + venc_hdmi_latency,
1409 de_h_end = modulo(de_h_begin + active_pixels_venc,
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));
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);
1424 de_v_end_even = de_v_begin_even + mode->vdisplay;
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));
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)
1438 + ((mode->vtotal - 1) / 2);
1439 de_v_end_odd = de_v_begin_odd + (mode->vdisplay / 2);
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));
1447 /* Program Hsync timing */
1448 if ((de_h_end + front_porch_venc) >= total_pixels_venc) {
1451 - total_pixels_venc;
1459 hs_end = modulo(hs_begin + hsync_pixels_venc,
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));
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
1475 vs_bline_evn = mode->vtotal
1481 vs_eline_evn = modulo(vs_bline_evn + vsync_lines,
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));
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));
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)
1500 vs_eline_odd = (de_v_begin_odd - 1)
1502 vso_begin_odd = modulo(hs_begin
1503 + (total_pixels_venc >> 1),
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));
1516 /* Select ENCP for VIU */
1517 meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP);
1520 /* Set VPU HDMI setting */
1521 /* Select ENCP or ENCI data to HDMI */
1523 reg = VPU_HDMI_ENCI_DATA_TO_HDMI;
1525 reg = VPU_HDMI_ENCP_DATA_TO_HDMI;
1527 /* Invert polarity of HSYNC from VENC */
1528 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
1529 reg |= VPU_HDMI_INV_HSYNC;
1531 /* Invert polarity of VSYNC from VENC */
1532 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
1533 reg |= VPU_HDMI_INV_VSYNC;
1535 /* Output data format */
1539 * Write rate to the async FIFO between VENC and HDMI.
1540 * One write every 2 wr_clk.
1542 if (venc_repeat || yuv420_mode)
1543 reg |= VPU_HDMI_WR_RATE(2);
1546 * Read rate to the async FIFO between VENC and HDMI.
1547 * One read every 2 wr_clk.
1550 reg |= VPU_HDMI_RD_RATE(2);
1552 writel_relaxed(reg, priv->io_base + _REG(VPU_HDMI_SETTING));
1554 priv->venc.hdmi_repeat = hdmi_repeat;
1555 priv->venc.venc_repeat = venc_repeat;
1556 priv->venc.hdmi_use_enci = use_enci;
1558 priv->venc.current_mode = MESON_VENC_MODE_HDMI;
1560 EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set);
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,
1581 static void meson_encl_set_gamma_table(struct meson_drm *priv, u16 *data,
1587 writel_bits_relaxed(L_GAMMA_CNTL_PORT_EN, 0,
1588 priv->io_base + _REG(L_GAMMA_CNTL_PORT));
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);
1593 pr_warn("%s: GAMMA ADR_RDY timeout\n", __func__);
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));
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,
1604 pr_warn_once("%s: GAMMA WR_RDY timeout\n", __func__);
1606 writel_relaxed(data[i], priv->io_base + _REG(L_GAMMA_DATA_PORT));
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);
1612 pr_warn("%s: GAMMA ADR_RDY timeout\n", __func__);
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));
1619 void meson_encl_load_gamma(struct meson_drm *priv)
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);
1625 writel_bits_relaxed(L_GAMMA_CNTL_PORT_EN, L_GAMMA_CNTL_PORT_EN,
1626 priv->io_base + _REG(L_GAMMA_CNTL_PORT));
1629 void meson_venc_mipi_dsi_mode_set(struct meson_drm *priv,
1630 const struct drm_display_mode *mode)
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;
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;
1652 hso_end = mode->hsync_end - mode->hsync_start;
1656 vso_eline = mode->vsync_end - mode->vsync_start;
1658 meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCL);
1660 writel_relaxed(0, priv->io_base + _REG(ENCL_VIDEO_EN));
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));
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));
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));
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));
1694 writel_relaxed(1, priv->io_base + _REG(ENCL_VIDEO_EN));
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 */
1699 writel_relaxed(L_DITH_CNTL_DITH10_EN, priv->io_base + _REG(L_DITH_CNTL_ADDR));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
1757 priv->venc.current_mode = MESON_VENC_MODE_MIPI_DSI;
1759 EXPORT_SYMBOL_GPL(meson_venc_mipi_dsi_mode_set);
1761 void meson_venci_cvbs_mode_set(struct meson_drm *priv,
1762 struct meson_cvbs_enci_mode *mode)
1766 if (mode->mode_tag == priv->venc.current_mode)
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));
1776 /* Digital Video Select : Interlace, clk27 clk, external */
1777 writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING));
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));
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));
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));
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));
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));
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
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));
1820 writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH));
1822 /* Sync mode : MASTER Master mode, free run, send HSO/VSO out */
1823 writel_relaxed(0x07, priv->io_base + _REG(ENCI_SYNC_MODE));
1825 /* 0x3 Y, C, and Component Y delay */
1826 writel_relaxed(mode->yc_delay, priv->io_base + _REG(ENCI_YC_DELAY));
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));
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));
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));
1844 /* Internal Venc, Internal VIU Sync, Internal Vencoder */
1845 writel_relaxed(0, priv->io_base + _REG(VENC_SYNC_ROUTE));
1847 /* UNreset Interlaced TV Encoder */
1848 writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST));
1851 * Enable Vfifo2vd and set Y_Cb_Y_Cr:
1852 * Corresponding value:
1856 * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y
1858 writel_relaxed(ENCI_VFIFO2VD_CTL_ENABLE |
1859 ENCI_VFIFO2VD_CTL_VD_SEL(0x4e),
1860 priv->io_base + _REG(ENCI_VFIFO2VD_CTL));
1863 writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING));
1865 /* Video Upsampling */
1867 * CTRL0, CTRL1 and CTRL2:
1868 * Filter0: input data sample every 2 cloks
1869 * Filter1: filtering and upsample enable
1871 reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN |
1872 VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN;
1876 * Interlace High Bandwidth Luma
1878 writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg,
1879 priv->io_base + _REG(VENC_UPSAMPLE_CTRL0));
1885 writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg,
1886 priv->io_base + _REG(VENC_UPSAMPLE_CTRL1));
1892 writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg,
1893 priv->io_base + _REG(VENC_UPSAMPLE_CTRL2));
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));
1903 /* Select ENCI for VIU */
1904 meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI);
1906 /* Enable ENCI FIFO */
1907 writel_relaxed(VENC_VDAC_FIFO_EN_ENCI_ENABLE,
1908 priv->io_base + _REG(VENC_VDAC_FIFO_CTRL));
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));
1914 /* Interlace video enable */
1915 writel_relaxed(ENCI_VIDEO_EN_ENABLE,
1916 priv->io_base + _REG(ENCI_VIDEO_EN));
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));
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));
1933 /* 0 in Macrovision register 0 */
1934 writel_relaxed(0, priv->io_base + _REG(ENCI_MACV_N0));
1936 /* Analog Synchronization and color burst value adjust */
1937 writel_relaxed(mode->analog_sync_adj,
1938 priv->io_base + _REG(ENCI_SYNC_ADJ));
1940 priv->venc.current_mode = mode->mode_tag;
1943 /* Returns the current ENCI field polarity */
1944 unsigned int meson_venci_get_field(struct meson_drm *priv)
1946 return readl_relaxed(priv->io_base + _REG(ENCI_INFO_READ)) & BIT(29);
1949 void meson_venc_enable_vsync(struct meson_drm *priv)
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));
1957 writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN,
1958 priv->io_base + _REG(VENC_INTCTRL));
1960 regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
1963 void meson_venc_disable_vsync(struct meson_drm *priv)
1965 regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), 0);
1966 writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
1969 void meson_venc_init(struct meson_drm *priv)
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);
1976 regmap_write(priv->hhi, HHI_VDAC_CNTL0, 0);
1977 regmap_write(priv->hhi, HHI_VDAC_CNTL1, 8);
1980 /* Power Down Dacs */
1981 writel_relaxed(0xff, priv->io_base + _REG(VENC_VDAC_SETTING));
1983 /* Disable HDMI PHY */
1984 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
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));
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));
1996 /* Disable VSync IRQ */
1997 meson_venc_disable_vsync(priv);
1999 priv->venc.current_mode = MESON_VENC_MODE_NONE;