sunxi: video: Split out TVE code

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@siol.net>
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile
index b8afd89..dbaab61 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 92c9d06..de768ba 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 @@
 
 	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_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 @@
 	int __maybe_unused clk_div, clk_double;
 	struct sunxi_lcdc_reg * const lcdc =
 		(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+	struct sunxi_tve_reg * __maybe_unused const tve =
+		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
 
 	switch (sunxi_display.monitor) {
 	case sunxi_monitor_none:
@@ -1134,7 +1085,7 @@
 		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 @@
 		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 0000000..adea78a
--- /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@skynet.be>
+ * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
+ * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@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);
+}