lkml.org 
[lkml]   [2017]   [Apr]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v3 06/11] drm/meson: Add support for HDMI venc modes and settings
Date
This patch adds support for the supported HDMI Venc modes and add the VPP mux
value to switch to ENCP encoder.

Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/gpu/drm/meson/meson_venc.c | 1245 +++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/meson/meson_venc.h | 7 +
drivers/gpu/drm/meson/meson_vpp.h | 2 +
3 files changed, 1249 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c
index f7c87017..31dc275 100644
--- a/drivers/gpu/drm/meson/meson_venc.c
+++ b/drivers/gpu/drm/meson/meson_venc.c
@@ -30,12 +30,37 @@
* 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
- *
- * What is missing :
* - 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 :
+ * _____ _____ ____________________
+ * 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 */
@@ -91,6 +116,1219 @@ struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc = {
.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 = 0x810b,
+ .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 = 8107,
+ .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,
+ },
+};
+
+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 },
+ { 34, &meson_hdmi_encp_mode_1080p30 },
+ { 31, &meson_hdmi_encp_mode_1080p50 },
+ { 16, &meson_hdmi_encp_mode_1080p60 },
+ { 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;
+}
+
+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);
+
+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,
+ struct drm_display_mode *mode)
+{
+ union meson_hdmi_venc_mode *vmode = NULL;
+ 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;
+
+ vmode = meson_venc_hdmi_get_vic_vmode(vic);
+ if (!vmode) {
+ dev_err(priv->dev, "%s: Fatal Error, unsupported vic %d\n",
+ __func__, vic);
+ return;
+ }
+
+ /* 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;
+ }
+
+ /* 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(0x1f, 0x1f,
+ 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(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL));
+ writel_relaxed(0x12, 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(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(0x26, 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, Y_Cb_Y_Cr select */
+ writel_relaxed(0x4e01, 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(1, 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(BIT(14), BIT(14),
+ 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);
+ }
+
+ writel_relaxed((use_enci ? 1 : 2) |
+ (mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) |
+ (mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) |
+ 4 << 5 |
+ (venc_repeat ? 1 << 8 : 0) |
+ (hdmi_repeat ? 1 << 12 : 0),
+ 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)
{
@@ -223,9 +1461,6 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv,
writel_relaxed(mode->analog_sync_adj,
priv->io_base + _REG(ENCI_SYNC_ADJ));

- /* Setup 27MHz vclk2 for ENCI and VDAC */
- meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS);
-
priv->venc.current_mode = mode->mode_tag;
}

diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h
index 77d4a7d..a1b96e8 100644
--- a/drivers/gpu/drm/meson/meson_venc.h
+++ b/drivers/gpu/drm/meson/meson_venc.h
@@ -30,6 +30,7 @@ enum {
MESON_VENC_MODE_NONE = 0,
MESON_VENC_MODE_CVBS_PAL,
MESON_VENC_MODE_CVBS_NTSC,
+ MESON_VENC_MODE_HDMI,
};

struct meson_cvbs_enci_mode {
@@ -56,12 +57,18 @@ struct meson_cvbs_enci_mode {
unsigned int analog_sync_adj;
};

+/* HDMI Clock parameters */
+bool meson_venc_hdmi_supported_vic(int vic);
+bool meson_venc_hdmi_venc_repeat(int vic);
+
/* CVBS Timings and Parameters */
extern struct meson_cvbs_enci_mode meson_cvbs_enci_pal;
extern struct meson_cvbs_enci_mode meson_cvbs_enci_ntsc;

void meson_venci_cvbs_mode_set(struct meson_drm *priv,
struct meson_cvbs_enci_mode *mode);
+void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,
+ struct drm_display_mode *mode);
unsigned int meson_venci_get_field(struct meson_drm *priv);

void meson_venc_enable_vsync(struct meson_drm *priv);
diff --git a/drivers/gpu/drm/meson/meson_vpp.h b/drivers/gpu/drm/meson/meson_vpp.h
index ede3b26..815177c 100644
--- a/drivers/gpu/drm/meson/meson_vpp.h
+++ b/drivers/gpu/drm/meson/meson_vpp.h
@@ -23,6 +23,8 @@

/* Mux VIU/VPP to ENCI */
#define MESON_VIU_VPP_MUX_ENCI 0x5
+/* Mux VIU/VPP to ENCP */
+#define MESON_VIU_VPP_MUX_ENCP 0xA

void meson_vpp_setup_mux(struct meson_drm *priv, unsigned int mux);

--
1.9.1
\
 
 \ /
  Last update: 2017-04-04 14:17    [W:0.180 / U:1.244 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site