[U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code

Jernej Skrabec jernej.skrabec at siol.net
Wed May 10 16:46:28 UTC 2017


Newer SoCs use same TV encoder unit. Split it out so it can be reused
with new DM video driver.

Signed-off-by: Jernej Skrabec <jernej.skrabec at siol.net>
---

 arch/arm/include/asm/arch-sunxi/display.h | 107 ------------------------
 arch/arm/include/asm/arch-sunxi/tve.h     | 131 ++++++++++++++++++++++++++++++
 drivers/video/sunxi/Makefile              |   2 +-
 drivers/video/sunxi/sunxi_display.c       |  73 +++--------------
 drivers/video/sunxi/tve.c                 |  86 ++++++++++++++++++++
 5 files changed, 230 insertions(+), 169 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-sunxi/tve.h
 create mode 100644 drivers/video/sunxi/tve.c

diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h
index 93803addfb..e10197784e 100644
--- a/arch/arm/include/asm/arch-sunxi/display.h
+++ b/arch/arm/include/asm/arch-sunxi/display.h
@@ -225,52 +225,6 @@ struct sunxi_hdmi_reg {
 };
 
 /*
- * This is based on the A10s User Manual, and the A10s only supports
- * composite video and not vga like the A10 / A20 does, still other
- * than the removed vga out capability the tvencoder seems to be the same.
- * "unknown#" registers are registers which are used in the A10 kernel code,
- * but not documented in the A10s User Manual.
- */
-struct sunxi_tve_reg {
-	u32 gctrl;			/* 0x000 */
-	u32 cfg0;			/* 0x004 */
-	u32 dac_cfg0;			/* 0x008 */
-	u32 filter;			/* 0x00c */
-	u32 chroma_freq;		/* 0x010 */
-	u32 porch_num;			/* 0x014 */
-	u32 unknown0;			/* 0x018 */
-	u32 line_num;			/* 0x01c */
-	u32 blank_black_level;		/* 0x020 */
-	u32 unknown1;			/* 0x024, seems to be 1 byte per dac */
-	u8 res0[0x08];			/* 0x028 */
-	u32 auto_detect_en;		/* 0x030 */
-	u32 auto_detect_int_status;	/* 0x034 */
-	u32 auto_detect_status;		/* 0x038 */
-	u32 auto_detect_debounce;	/* 0x03c */
-	u32 csc_reg0;			/* 0x040 */
-	u32 csc_reg1;			/* 0x044 */
-	u32 csc_reg2;			/* 0x048 */
-	u32 csc_reg3;			/* 0x04c */
-	u8 res1[0xb0];			/* 0x050 */
-	u32 color_burst;		/* 0x100 */
-	u32 vsync_num;			/* 0x104 */
-	u32 notch_freq;			/* 0x108 */
-	u32 cbr_level;			/* 0x10c */
-	u32 burst_phase;		/* 0x110 */
-	u32 burst_width;		/* 0x114 */
-	u32 unknown2;			/* 0x118 */
-	u32 sync_vbi_level;		/* 0x11c */
-	u32 white_level;		/* 0x120 */
-	u32 active_num;			/* 0x124 */
-	u32 chroma_bw_gain;		/* 0x128 */
-	u32 notch_width;		/* 0x12c */
-	u32 resync_num;			/* 0x130 */
-	u32 slave_para;			/* 0x134 */
-	u32 cfg1;			/* 0x138 */
-	u32 cfg2;			/* 0x13c */
-};
-
-/*
  * DE-FE register constants.
  */
 #define SUNXI_DE_FE_WIDTH(x)			(((x) - 1) << 0)
@@ -394,67 +348,6 @@ struct sunxi_tve_reg {
 #define SUNXI_HMDI_DDC_LINE_CTRL_SCL_ENABLE	(1 << 8)
 #define SUNXI_HMDI_DDC_LINE_CTRL_SDA_ENABLE	(1 << 9)
 
-/*
- * TVE register constants.
- */
-#define SUNXI_TVE_GCTRL_ENABLE			(1 << 0)
-/*
- * Select input 0 to disable dac, 1 - 4 to feed dac from tve0, 5 - 8 to feed
- * dac from tve1. When using tve1 the mux value must be written to both tve0's
- * and tve1's gctrl reg.
- */
-#define SUNXI_TVE_GCTRL_DAC_INPUT_MASK(dac)	(0xf << (((dac) + 1) * 4))
-#define SUNXI_TVE_GCTRL_DAC_INPUT(dac, sel)	((sel) << (((dac) + 1) * 4))
-#define SUNXI_TVE_CFG0_VGA			0x20000000
-#define SUNXI_TVE_CFG0_PAL			0x07030001
-#define SUNXI_TVE_CFG0_NTSC			0x07030000
-#define SUNXI_TVE_DAC_CFG0_VGA			0x403e1ac7
-#ifdef CONFIG_MACH_SUN5I
-#define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x433f0009
-#else
-#define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x403f0008
-#endif
-#define SUNXI_TVE_FILTER_COMPOSITE		0x00000120
-#define SUNXI_TVE_CHROMA_FREQ_PAL_M		0x21e6efe3
-#define SUNXI_TVE_CHROMA_FREQ_PAL_NC		0x21f69446
-#define SUNXI_TVE_PORCH_NUM_PAL			0x008a0018
-#define SUNXI_TVE_PORCH_NUM_NTSC		0x00760020
-#define SUNXI_TVE_LINE_NUM_PAL			0x00160271
-#define SUNXI_TVE_LINE_NUM_NTSC			0x0016020d
-#define SUNXI_TVE_BLANK_BLACK_LEVEL_PAL		0x00fc00fc
-#define SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC	0x00f0011a
-#define SUNXI_TVE_UNKNOWN1_VGA			0x00000000
-#define SUNXI_TVE_UNKNOWN1_COMPOSITE		0x18181818
-#define SUNXI_TVE_AUTO_DETECT_EN_DET_EN(dac)	(1 << ((dac) + 0))
-#define SUNXI_TVE_AUTO_DETECT_EN_INT_EN(dac)	(1 << ((dac) + 16))
-#define SUNXI_TVE_AUTO_DETECT_INT_STATUS(dac)	(1 << ((dac) + 0))
-#define SUNXI_TVE_AUTO_DETECT_STATUS_SHIFT(dac)	((dac) * 8)
-#define SUNXI_TVE_AUTO_DETECT_STATUS_MASK(dac)	(3 << ((dac) * 8))
-#define SUNXI_TVE_AUTO_DETECT_STATUS_NONE	0
-#define SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED	1
-#define SUNXI_TVE_AUTO_DETECT_STATUS_SHORT_GND	3
-#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(d)	((d) * 8)
-#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_MASK(d)	(0xf << ((d) * 8))
-#define SUNXI_TVE_CSC_REG0_ENABLE		(1 << 31)
-#define SUNXI_TVE_CSC_REG0			0x08440832
-#define SUNXI_TVE_CSC_REG1			0x3b6dace1
-#define SUNXI_TVE_CSC_REG2			0x0e1d13dc
-#define SUNXI_TVE_CSC_REG3			0x00108080
-#define SUNXI_TVE_COLOR_BURST_PAL_M		0x00000000
-#define SUNXI_TVE_CBR_LEVEL_PAL			0x00002828
-#define SUNXI_TVE_CBR_LEVEL_NTSC		0x0000004f
-#define SUNXI_TVE_BURST_PHASE_NTSC		0x00000000
-#define SUNXI_TVE_BURST_WIDTH_COMPOSITE		0x0016447e
-#define SUNXI_TVE_UNKNOWN2_PAL			0x0000e0e0
-#define SUNXI_TVE_UNKNOWN2_NTSC			0x0000a0a0
-#define SUNXI_TVE_SYNC_VBI_LEVEL_NTSC		0x001000f0
-#define SUNXI_TVE_ACTIVE_NUM_COMPOSITE		0x000005a0
-#define SUNXI_TVE_CHROMA_BW_GAIN_COMP		0x00000002
-#define SUNXI_TVE_NOTCH_WIDTH_COMPOSITE		0x00000101
-#define SUNXI_TVE_RESYNC_NUM_PAL		0x800d000c
-#define SUNXI_TVE_RESYNC_NUM_NTSC		0x000e000c
-#define SUNXI_TVE_SLAVE_PARA_COMPOSITE		0x00000000
-
 int sunxi_simplefb_setup(void *blob);
 
 #endif /* _SUNXI_DISPLAY_H */
diff --git a/arch/arm/include/asm/arch-sunxi/tve.h b/arch/arm/include/asm/arch-sunxi/tve.h
new file mode 100644
index 0000000000..41a14a68e4
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/tve.h
@@ -0,0 +1,131 @@
+/*
+ * Sunxi TV encoder register and constant defines
+ *
+ * (C) Copyright 2014 Hans de Goede <hdegoede at redhat.com>
+ * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec at siol.net>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _TVE_H
+#define _TVE_H
+
+enum tve_mode {
+	tve_mode_vga,
+	tve_mode_composite_pal,
+	tve_mode_composite_ntsc,
+	tve_mode_composite_pal_m,
+	tve_mode_composite_pal_nc,
+};
+
+/*
+ * This is based on the A10s User Manual, and the A10s only supports
+ * composite video and not vga like the A10 / A20 does, still other
+ * than the removed vga out capability the tvencoder seems to be the same.
+ * "unknown#" registers are registers which are used in the A10 kernel code,
+ * but not documented in the A10s User Manual.
+ */
+struct sunxi_tve_reg {
+	u32 gctrl;			/* 0x000 */
+	u32 cfg0;			/* 0x004 */
+	u32 dac_cfg0;			/* 0x008 */
+	u32 filter;			/* 0x00c */
+	u32 chroma_freq;		/* 0x010 */
+	u32 porch_num;			/* 0x014 */
+	u32 unknown0;			/* 0x018 */
+	u32 line_num;			/* 0x01c */
+	u32 blank_black_level;		/* 0x020 */
+	u32 unknown1;			/* 0x024, seems to be 1 byte per dac */
+	u8 res0[0x08];			/* 0x028 */
+	u32 auto_detect_en;		/* 0x030 */
+	u32 auto_detect_int_status;	/* 0x034 */
+	u32 auto_detect_status;		/* 0x038 */
+	u32 auto_detect_debounce;	/* 0x03c */
+	u32 csc_reg0;			/* 0x040 */
+	u32 csc_reg1;			/* 0x044 */
+	u32 csc_reg2;			/* 0x048 */
+	u32 csc_reg3;			/* 0x04c */
+	u8 res1[0xb0];			/* 0x050 */
+	u32 color_burst;		/* 0x100 */
+	u32 vsync_num;			/* 0x104 */
+	u32 notch_freq;			/* 0x108 */
+	u32 cbr_level;			/* 0x10c */
+	u32 burst_phase;		/* 0x110 */
+	u32 burst_width;		/* 0x114 */
+	u32 unknown2;			/* 0x118 */
+	u32 sync_vbi_level;		/* 0x11c */
+	u32 white_level;		/* 0x120 */
+	u32 active_num;			/* 0x124 */
+	u32 chroma_bw_gain;		/* 0x128 */
+	u32 notch_width;		/* 0x12c */
+	u32 resync_num;			/* 0x130 */
+	u32 slave_para;			/* 0x134 */
+	u32 cfg1;			/* 0x138 */
+	u32 cfg2;			/* 0x13c */
+};
+
+/*
+ * TVE register constants.
+ */
+#define SUNXI_TVE_GCTRL_ENABLE			(1 << 0)
+/*
+ * Select input 0 to disable dac, 1 - 4 to feed dac from tve0, 5 - 8 to feed
+ * dac from tve1. When using tve1 the mux value must be written to both tve0's
+ * and tve1's gctrl reg.
+ */
+#define SUNXI_TVE_GCTRL_DAC_INPUT_MASK(dac)	(0xf << (((dac) + 1) * 4))
+#define SUNXI_TVE_GCTRL_DAC_INPUT(dac, sel)	((sel) << (((dac) + 1) * 4))
+#define SUNXI_TVE_CFG0_VGA			0x20000000
+#define SUNXI_TVE_CFG0_PAL			0x07030001
+#define SUNXI_TVE_CFG0_NTSC			0x07030000
+#define SUNXI_TVE_DAC_CFG0_VGA			0x403e1ac7
+#ifdef CONFIG_MACH_SUN5I
+#define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x433f0009
+#else
+#define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x403f0008
+#endif
+#define SUNXI_TVE_FILTER_COMPOSITE		0x00000120
+#define SUNXI_TVE_CHROMA_FREQ_PAL_M		0x21e6efe3
+#define SUNXI_TVE_CHROMA_FREQ_PAL_NC		0x21f69446
+#define SUNXI_TVE_PORCH_NUM_PAL			0x008a0018
+#define SUNXI_TVE_PORCH_NUM_NTSC		0x00760020
+#define SUNXI_TVE_LINE_NUM_PAL			0x00160271
+#define SUNXI_TVE_LINE_NUM_NTSC			0x0016020d
+#define SUNXI_TVE_BLANK_BLACK_LEVEL_PAL		0x00fc00fc
+#define SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC	0x00f0011a
+#define SUNXI_TVE_UNKNOWN1_VGA			0x00000000
+#define SUNXI_TVE_UNKNOWN1_COMPOSITE		0x18181818
+#define SUNXI_TVE_AUTO_DETECT_EN_DET_EN(dac)	(1 << ((dac) + 0))
+#define SUNXI_TVE_AUTO_DETECT_EN_INT_EN(dac)	(1 << ((dac) + 16))
+#define SUNXI_TVE_AUTO_DETECT_INT_STATUS(dac)	(1 << ((dac) + 0))
+#define SUNXI_TVE_AUTO_DETECT_STATUS_SHIFT(dac)	((dac) * 8)
+#define SUNXI_TVE_AUTO_DETECT_STATUS_MASK(dac)	(3 << ((dac) * 8))
+#define SUNXI_TVE_AUTO_DETECT_STATUS_NONE	0
+#define SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED	1
+#define SUNXI_TVE_AUTO_DETECT_STATUS_SHORT_GND	3
+#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(d)	((d) * 8)
+#define SUNXI_TVE_AUTO_DETECT_DEBOUNCE_MASK(d)	(0xf << ((d) * 8))
+#define SUNXI_TVE_CSC_REG0_ENABLE		(1 << 31)
+#define SUNXI_TVE_CSC_REG0			0x08440832
+#define SUNXI_TVE_CSC_REG1			0x3b6dace1
+#define SUNXI_TVE_CSC_REG2			0x0e1d13dc
+#define SUNXI_TVE_CSC_REG3			0x00108080
+#define SUNXI_TVE_COLOR_BURST_PAL_M		0x00000000
+#define SUNXI_TVE_CBR_LEVEL_PAL			0x00002828
+#define SUNXI_TVE_CBR_LEVEL_NTSC		0x0000004f
+#define SUNXI_TVE_BURST_PHASE_NTSC		0x00000000
+#define SUNXI_TVE_BURST_WIDTH_COMPOSITE		0x0016447e
+#define SUNXI_TVE_UNKNOWN2_PAL			0x0000e0e0
+#define SUNXI_TVE_UNKNOWN2_NTSC			0x0000a0a0
+#define SUNXI_TVE_SYNC_VBI_LEVEL_NTSC		0x001000f0
+#define SUNXI_TVE_ACTIVE_NUM_COMPOSITE		0x000005a0
+#define SUNXI_TVE_CHROMA_BW_GAIN_COMP		0x00000002
+#define SUNXI_TVE_NOTCH_WIDTH_COMPOSITE		0x00000101
+#define SUNXI_TVE_RESYNC_NUM_PAL		0x800d000c
+#define SUNXI_TVE_RESYNC_NUM_NTSC		0x000e000c
+#define SUNXI_TVE_SLAVE_PARA_COMPOSITE		0x00000000
+
+void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode);
+void tvencoder_enable(struct sunxi_tve_reg * const tve);
+
+#endif /* _TVE_H */
diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile
index b8afd892ad..dbaab61b59 100644
--- a/drivers/video/sunxi/Makefile
+++ b/drivers/video/sunxi/Makefile
@@ -5,5 +5,5 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o lcdc.o ../videomodes.o
+obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o lcdc.o tve.o ../videomodes.o
 obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o lcdc.o ../dw_hdmi.o
diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c
index 92c9d06054..2ff50994b4 100644
--- a/drivers/video/sunxi/sunxi_display.c
+++ b/drivers/video/sunxi/sunxi_display.c
@@ -14,6 +14,7 @@
 #include <asm/arch/gpio.h>
 #include <asm/arch/lcdc.h>
 #include <asm/arch/pwm.h>
+#include <asm/arch/tve.h>
 #include <asm/global_data.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
@@ -929,63 +930,19 @@ static void sunxi_tvencoder_mode_set(void)
 
 	switch (sunxi_display.monitor) {
 	case sunxi_monitor_vga:
-		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
-		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
-		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
-		writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
-		writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
-		writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
+		tvencoder_mode_set(tve, tve_mode_vga);
 		break;
 	case sunxi_monitor_composite_pal_nc:
-		writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
-		/* Fall through */
+		tvencoder_mode_set(tve, tve_mode_composite_pal_nc);
+		break;
 	case sunxi_monitor_composite_pal:
-		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
-		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
-		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
-		       SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
-		writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
-		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
-		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
-		writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
-		writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
-		writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
-		writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
-		writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
-		writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
-		writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
-		writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
-		writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
-		writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
-		writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
-		writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
+		tvencoder_mode_set(tve, tve_mode_composite_pal);
 		break;
 	case sunxi_monitor_composite_pal_m:
-		writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
-		writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
-		/* Fall through */
+		tvencoder_mode_set(tve, tve_mode_composite_pal_m);
+		break;
 	case sunxi_monitor_composite_ntsc:
-		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
-		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
-		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
-		       SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
-		writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
-		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
-		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
-		writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
-		writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
-		writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
-		writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
-		writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
-		writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
-		writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
-		writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
-		writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
-		writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
-		writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
-		writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
-		writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
-		writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
+		tvencoder_mode_set(tve, tve_mode_composite_ntsc);
 		break;
 	case sunxi_monitor_none:
 	case sunxi_monitor_dvi:
@@ -995,14 +952,6 @@ static void sunxi_tvencoder_mode_set(void)
 	}
 }
 
-static void sunxi_tvencoder_enable(void)
-{
-	struct sunxi_tve_reg * const tve =
-		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
-
-	setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
-}
-
 #endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
 
 static void sunxi_drc_init(void)
@@ -1080,6 +1029,8 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
 	int __maybe_unused clk_div, clk_double;
 	struct sunxi_lcdc_reg * const lcdc =
 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+	struct sunxi_tve_reg * const tve =
+		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
 
 	switch (sunxi_display.monitor) {
 	case sunxi_monitor_none:
@@ -1134,7 +1085,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
 		sunxi_tvencoder_mode_set();
 		sunxi_composer_enable();
 		lcdc_enable(lcdc, sunxi_display.depth);
-		sunxi_tvencoder_enable();
+		tvencoder_enable(tve);
 #elif defined CONFIG_VIDEO_VGA_VIA_LCD
 		sunxi_composer_mode_set(mode, address);
 		sunxi_lcdc_tcon0_mode_set(mode, true);
@@ -1153,7 +1104,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
 		sunxi_tvencoder_mode_set();
 		sunxi_composer_enable();
 		lcdc_enable(lcdc, sunxi_display.depth);
-		sunxi_tvencoder_enable();
+		tvencoder_enable(tve);
 #endif
 		break;
 	}
diff --git a/drivers/video/sunxi/tve.c b/drivers/video/sunxi/tve.c
new file mode 100644
index 0000000000..adea78a69a
--- /dev/null
+++ b/drivers/video/sunxi/tve.c
@@ -0,0 +1,86 @@
+/*
+ * TV encoder driver for Allwinner SoCs.
+ *
+ * (C) Copyright 2013-2014 Luc Verhaegen <libv at skynet.be>
+ * (C) Copyright 2014-2015 Hans de Goede <hdegoede at redhat.com>
+ * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec at siol.net>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+
+#include <asm/arch/tve.h>
+#include <asm/io.h>
+
+void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode)
+{
+	switch (mode) {
+	case tve_mode_vga:
+		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
+		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
+		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
+		writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
+		writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
+		writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
+		break;
+	case tve_mode_composite_pal_nc:
+		writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
+		/* Fall through */
+	case tve_mode_composite_pal:
+		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
+		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
+		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
+		       SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
+		writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
+		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
+		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
+		writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
+		writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
+		writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL,
+		       &tve->blank_black_level);
+		writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
+		writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
+		writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
+		writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
+		writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
+		writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
+		writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
+		writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
+		writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
+		break;
+	case tve_mode_composite_pal_m:
+		writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
+		writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
+		/* Fall through */
+	case tve_mode_composite_ntsc:
+		writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
+		       SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
+		       SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
+		       SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
+		writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
+		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
+		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
+		writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
+		writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
+		writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC,
+		       &tve->blank_black_level);
+		writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
+		writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
+		writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
+		writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
+		writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
+		writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
+		writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
+		writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
+		writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
+		writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
+		writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
+		break;
+	}
+}
+
+void tvencoder_enable(struct sunxi_tve_reg * const tve)
+{
+	setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
+}
-- 
2.12.2



More information about the U-Boot mailing list