All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/3] sunxi: video: Add support for TV (composite) output on H3/H5
@ 2017-05-10 16:46 Jernej Skrabec
  2017-05-10 16:46 ` [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code Jernej Skrabec
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Jernej Skrabec @ 2017-05-10 16:46 UTC (permalink / raw)
  To: u-boot

This series implements support for composite output. Driver is
implemented using DM video framework and heavily reuse code written for
older SoCs. Additionally, driver also implements plug detection.

Patch 1 splits out code used for composite output from video driver for
older SoCs.

Patch 2 adds needed changes in clock driver.

Patch 3 adds new driver for composite output.

Everything was tested on H3 (OrangePi 2) and H5 (OrangePi PC2) board.
Since this series changes video driver for old SoCs, I would kindly ask
that someone tests if everything still works as expected.

Last but not least - driver should work as-is, but to work reliably,
following patch must also be applied:
https://patchwork.ozlabs.org/patch/756736/

Best regards,
Jernej


Jernej Skrabec (3):
  sunxi: video: Split out TVE code
  sunxi: Add clock support for TV encoder
  sunxi: video: Add H3/H5 TV out driver

 arch/arm/include/asm/arch-sunxi/clock_sun6i.h |   8 +-
 arch/arm/include/asm/arch-sunxi/cpu_sun4i.h   |  10 ++
 arch/arm/include/asm/arch-sunxi/display.h     | 107 ------------------
 arch/arm/include/asm/arch-sunxi/display2.h    |  17 +++
 arch/arm/include/asm/arch-sunxi/tve.h         | 144 ++++++++++++++++++++++++
 drivers/video/sunxi/Makefile                  |   4 +-
 drivers/video/sunxi/sunxi_de2.c               |  60 ++++++++--
 drivers/video/sunxi/sunxi_display.c           |  73 ++----------
 drivers/video/sunxi/sunxi_tve.c               | 156 ++++++++++++++++++++++++++
 drivers/video/sunxi/tve.c                     |  88 +++++++++++++++
 10 files changed, 484 insertions(+), 183 deletions(-)
 create mode 100644 arch/arm/include/asm/arch-sunxi/tve.h
 create mode 100644 drivers/video/sunxi/sunxi_tve.c
 create mode 100644 drivers/video/sunxi/tve.c

-- 
2.12.2

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code
  2017-05-10 16:46 [U-Boot] [PATCH 0/3] sunxi: video: Add support for TV (composite) output on H3/H5 Jernej Skrabec
@ 2017-05-10 16:46 ` Jernej Skrabec
  2017-05-15  3:03   ` Simon Glass
  2017-05-15 19:08   ` Anatolij Gustschin
  2017-05-10 16:46 ` [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder Jernej Skrabec
  2017-05-10 16:46 ` [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver Jernej Skrabec
  2 siblings, 2 replies; 20+ messages in thread
From: Jernej Skrabec @ 2017-05-10 16:46 UTC (permalink / raw)
  To: u-boot

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>
---

 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@redhat.com>
+ * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@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@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);
+}
-- 
2.12.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder
  2017-05-10 16:46 [U-Boot] [PATCH 0/3] sunxi: video: Add support for TV (composite) output on H3/H5 Jernej Skrabec
  2017-05-10 16:46 ` [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code Jernej Skrabec
@ 2017-05-10 16:46 ` Jernej Skrabec
  2017-05-12 15:47   ` Maxime Ripard
  2017-05-15 19:25   ` Anatolij Gustschin
  2017-05-10 16:46 ` [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver Jernej Skrabec
  2 siblings, 2 replies; 20+ messages in thread
From: Jernej Skrabec @ 2017-05-10 16:46 UTC (permalink / raw)
  To: u-boot

This patch adds support for TV encoder clocks which will be used later.

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

 arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index a44ea77576..dc011cc964 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -83,7 +83,8 @@ struct sunxi_ccm_reg {
 	u32 lcd0_ch0_clk_cfg;	/* 0x118 LCD0 CH0 module clock */
 	u32 lcd1_ch0_clk_cfg;	/* 0x11c LCD1 CH0 module clock */
 #endif
-	u32 reserved14[3];
+	u32 tve_clk_cfg;	/* 0x120 TVE module clock */
+	u32 reserved14[2];
 	u32 lcd0_ch1_clk_cfg;	/* 0x12c LCD0 CH1 module clock */
 	u32 lcd1_ch1_clk_cfg;	/* 0x130 LCD1 CH1 module clock */
 	u32 csi0_clk_cfg;	/* 0x134 CSI0 module clock */
@@ -299,6 +300,7 @@ struct sunxi_ccm_reg {
 #define AHB_GATE_OFFSET_DE_BE0		12
 #define AHB_GATE_OFFSET_DE		12
 #define AHB_GATE_OFFSET_HDMI		11
+#define AHB_GATE_OFFSET_TVE		9
 #ifndef CONFIG_SUNXI_DE2
 #define AHB_GATE_OFFSET_LCD1		5
 #define AHB_GATE_OFFSET_LCD0		4
@@ -404,6 +406,9 @@ struct sunxi_ccm_reg {
 
 #define CCM_HDMI_SLOW_CTRL_DDC_GATE	(1 << 31)
 
+#define CCM_TVE_CTRL_GATE		(0x1 << 31)
+#define CCM_TVE_CTRL_M(n)		((((n) - 1) & 0xf) << 0)
+
 #if defined(CONFIG_MACH_SUN50I)
 #define MBUS_CLK_DEFAULT		0x81000002 /* PLL6x2 / 3 */
 #elif defined(CONFIG_MACH_SUN8I)
@@ -434,6 +439,7 @@ struct sunxi_ccm_reg {
 #define AHB_RESET_OFFSET_DE		12
 #define AHB_RESET_OFFSET_HDMI		11
 #define AHB_RESET_OFFSET_HDMI2		10
+#define AHB_RESET_OFFSET_TVE		9
 #ifndef CONFIG_SUNXI_DE2
 #define AHB_RESET_OFFSET_LCD1		5
 #define AHB_RESET_OFFSET_LCD0		4
-- 
2.12.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-10 16:46 [U-Boot] [PATCH 0/3] sunxi: video: Add support for TV (composite) output on H3/H5 Jernej Skrabec
  2017-05-10 16:46 ` [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code Jernej Skrabec
  2017-05-10 16:46 ` [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder Jernej Skrabec
@ 2017-05-10 16:46 ` Jernej Skrabec
  2017-05-12 16:06   ` Maxime Ripard
  2 siblings, 1 reply; 20+ messages in thread
From: Jernej Skrabec @ 2017-05-10 16:46 UTC (permalink / raw)
  To: u-boot

This commit adds support for TV (composite) output.

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

 arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  10 ++
 arch/arm/include/asm/arch-sunxi/display2.h  |  17 +++
 arch/arm/include/asm/arch-sunxi/tve.h       |  17 ++-
 drivers/video/sunxi/Makefile                |   2 +-
 drivers/video/sunxi/sunxi_de2.c             |  60 ++++++++---
 drivers/video/sunxi/sunxi_tve.c             | 156 ++++++++++++++++++++++++++++
 drivers/video/sunxi/tve.c                   |   6 +-
 7 files changed, 251 insertions(+), 17 deletions(-)
 create mode 100644 drivers/video/sunxi/sunxi_tve.c

diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
index 6aa5e91ada..2419062d45 100644
--- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -34,7 +34,9 @@
 #define SUNXI_MS_BASE			0x01c07000
 #define SUNXI_TVD_BASE			0x01c08000
 #define SUNXI_CSI0_BASE			0x01c09000
+#ifndef CONFIG_MACH_SUNXI_H3_H5
 #define SUNXI_TVE0_BASE			0x01c0a000
+#endif
 #define SUNXI_EMAC_BASE			0x01c0b000
 #define SUNXI_LCD0_BASE			0x01c0C000
 #define SUNXI_LCD1_BASE			0x01c0d000
@@ -161,10 +163,18 @@ defined(CONFIG_MACH_SUN50I)
 /* module sram */
 #define SUNXI_SRAM_C_BASE		0x01d00000
 
+#ifndef CONFIG_MACH_SUN8I_H3
 #define SUNXI_DE_FE0_BASE		0x01e00000
+#else
+#define SUNXI_TVE0_BASE			0x01e00000
+#endif
 #define SUNXI_DE_FE1_BASE		0x01e20000
 #define SUNXI_DE_BE0_BASE		0x01e60000
+#ifndef CONFIG_MACH_SUN50I_H5
 #define SUNXI_DE_BE1_BASE		0x01e40000
+#else
+#define SUNXI_TVE0_BASE			0x01e40000
+#endif
 #define SUNXI_MP_BASE			0x01e80000
 #define SUNXI_AVG_BASE			0x01ea0000
 
diff --git a/arch/arm/include/asm/arch-sunxi/display2.h b/arch/arm/include/asm/arch-sunxi/display2.h
index b5875f9605..359cacd90b 100644
--- a/arch/arm/include/asm/arch-sunxi/display2.h
+++ b/arch/arm/include/asm/arch-sunxi/display2.h
@@ -90,6 +90,23 @@ struct de_ui {
 	u32 ovl_size;
 };
 
+struct de_csc {
+	u32 csc_ctl;
+	u8 res[0xc];
+	u32 coef11;
+	u32 coef12;
+	u32 coef13;
+	u32 coef14;
+	u32 coef21;
+	u32 coef22;
+	u32 coef23;
+	u32 coef24;
+	u32 coef31;
+	u32 coef32;
+	u32 coef33;
+	u32 coef34;
+};
+
 /*
  * DE register constants.
  */
diff --git a/arch/arm/include/asm/arch-sunxi/tve.h b/arch/arm/include/asm/arch-sunxi/tve.h
index 41a14a68e4..ff34bbbc12 100644
--- a/arch/arm/include/asm/arch-sunxi/tve.h
+++ b/arch/arm/include/asm/arch-sunxi/tve.h
@@ -45,7 +45,9 @@ struct sunxi_tve_reg {
 	u32 csc_reg1;			/* 0x044 */
 	u32 csc_reg2;			/* 0x048 */
 	u32 csc_reg3;			/* 0x04c */
-	u8 res1[0xb0];			/* 0x050 */
+	u8 res1[0xa8];			/* 0x050 */
+	u32 auto_detect_cfg0;		/* 0x0f8 */
+	u32 auto_detect_cfg1;		/* 0x0fc */
 	u32 color_burst;		/* 0x100 */
 	u32 vsync_num;			/* 0x104 */
 	u32 notch_freq;			/* 0x108 */
@@ -62,6 +64,10 @@ struct sunxi_tve_reg {
 	u32 slave_para;			/* 0x134 */
 	u32 cfg1;			/* 0x138 */
 	u32 cfg2;			/* 0x13c */
+	u8 res2[0x1c4];			/* 0x140 */
+	u32 calibration;		/* 0x304 */
+	u8 res3[0x4];			/* 0x308 */
+	u32 unknown3;			/* 0x30c */
 };
 
 /*
@@ -79,12 +85,14 @@ struct sunxi_tve_reg {
 #define SUNXI_TVE_CFG0_PAL			0x07030001
 #define SUNXI_TVE_CFG0_NTSC			0x07030000
 #define SUNXI_TVE_DAC_CFG0_VGA			0x403e1ac7
-#ifdef CONFIG_MACH_SUN5I
+#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUNXI_H3_H5)
 #define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x433f0009
 #else
 #define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x403f0008
 #endif
+#define SUNXI_TVE_DAC_CFG0_DETECTION		0x433f0289
 #define SUNXI_TVE_FILTER_COMPOSITE		0x00000120
+#define SUNXI_TVE_CHROMA_FREQ_PAL		0x2a098acb
 #define SUNXI_TVE_CHROMA_FREQ_PAL_M		0x21e6efe3
 #define SUNXI_TVE_CHROMA_FREQ_PAL_NC		0x21f69446
 #define SUNXI_TVE_PORCH_NUM_PAL			0x008a0018
@@ -105,6 +113,8 @@ struct sunxi_tve_reg {
 #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_AUTO_DETECT_CFG0		0x00000280
+#define SUNXI_TVE_AUTO_DETECT_CFG1		0x028F00FF
 #define SUNXI_TVE_CSC_REG0_ENABLE		(1 << 31)
 #define SUNXI_TVE_CSC_REG0			0x08440832
 #define SUNXI_TVE_CSC_REG1			0x3b6dace1
@@ -124,6 +134,9 @@ struct sunxi_tve_reg {
 #define SUNXI_TVE_RESYNC_NUM_PAL		0x800d000c
 #define SUNXI_TVE_RESYNC_NUM_NTSC		0x000e000c
 #define SUNXI_TVE_SLAVE_PARA_COMPOSITE		0x00000000
+#define SUNXI_TVE_CALIBRATION_H3		0x02000c00
+#define SUNXI_TVE_CALIBRATION_H5		0x02850000
+#define SUNXI_TVE_UNKNOWN3_H5			0x00101110
 
 void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode);
 void tvencoder_enable(struct sunxi_tve_reg * const tve);
diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile
index dbaab61b59..1db82c53f0 100644
--- a/drivers/video/sunxi/Makefile
+++ b/drivers/video/sunxi/Makefile
@@ -6,4 +6,4 @@
 #
 
 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
+obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o sunxi_tve.o tve.o lcdc.o ../dw_hdmi.o
diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c
index 9a32c3a020..ee67764ac5 100644
--- a/drivers/video/sunxi/sunxi_de2.c
+++ b/drivers/video/sunxi/sunxi_de2.c
@@ -56,7 +56,7 @@ static void sunxi_de2_composer_init(void)
 }
 
 static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
-			       int bpp, ulong address)
+			       int bpp, ulong address, bool is_composite)
 {
 	ulong de_mux_base = (mux == 0) ?
 			    SUNXI_DE2_MUX0_BASE : SUNXI_DE2_MUX1_BASE;
@@ -72,6 +72,9 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
 		(struct de_ui *)(de_mux_base +
 				 SUNXI_DE2_MUX_CHAN_REGS +
 				 SUNXI_DE2_MUX_CHAN_SZ * 1);
+	struct de_csc * const de_csc_regs =
+		(struct de_csc *)(de_mux_base +
+				  SUNXI_DE2_MUX_DCSC_REGS);
 	u32 size = SUNXI_DE2_WH(mode->hactive.typ, mode->vactive.typ);
 	int channel;
 	u32 format;
@@ -128,7 +131,27 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
 	writel(0, de_mux_base + SUNXI_DE2_MUX_PEAK_REGS);
 	writel(0, de_mux_base + SUNXI_DE2_MUX_ASE_REGS);
 	writel(0, de_mux_base + SUNXI_DE2_MUX_FCC_REGS);
-	writel(0, de_mux_base + SUNXI_DE2_MUX_DCSC_REGS);
+
+	if (is_composite) {
+		/* set CSC coefficients */
+		writel(0x107, &de_csc_regs->coef11);
+		writel(0x204, &de_csc_regs->coef12);
+		writel(0x64, &de_csc_regs->coef13);
+		writel(0x4200, &de_csc_regs->coef14);
+		writel(0x1f68, &de_csc_regs->coef21);
+		writel(0x1ed6, &de_csc_regs->coef22);
+		writel(0x1c2, &de_csc_regs->coef23);
+		writel(0x20200, &de_csc_regs->coef24);
+		writel(0x1c2, &de_csc_regs->coef31);
+		writel(0x1e87, &de_csc_regs->coef32);
+		writel(0x1fb7, &de_csc_regs->coef33);
+		writel(0x20200, &de_csc_regs->coef34);
+
+		/* enable CSC unit */
+		writel(1, &de_csc_regs->csc_ctl);
+	} else {
+		writel(0, &de_csc_regs->csc_ctl);
+	}
 
 	switch (bpp) {
 	case 16:
@@ -153,7 +176,7 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
 
 static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
 			  enum video_log2_bpp l2bpp,
-			  struct udevice *disp, int mux)
+			  struct udevice *disp, int mux, bool is_composite)
 {
 	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
 	struct display_timing timing;
@@ -183,7 +206,7 @@ static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
 	}
 
 	sunxi_de2_composer_init();
-	sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase);
+	sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase, is_composite);
 
 	ret = display_enable(disp, 1 << l2bpp, &timing);
 	if (ret) {
@@ -204,7 +227,6 @@ static int sunxi_de2_probe(struct udevice *dev)
 	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
 	struct udevice *disp;
 	int ret;
-	int mux;
 
 	/* Before relocation we don't need to do anything */
 	if (!(gd->flags & GD_FLG_RELOC))
@@ -212,17 +234,31 @@ static int sunxi_de2_probe(struct udevice *dev)
 
 	ret = uclass_find_device_by_name(UCLASS_DISPLAY,
 					 "sunxi_dw_hdmi", &disp);
+	if (!ret) {
+		int mux;
+		if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
+			mux = 0;
+		else
+			mux = 1;
+
+		ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux,
+				     false);
+		if (!ret) {
+			video_set_flush_dcache(dev, 1);
+			return 0;
+		}
+	}
+
+	debug("%s: hdmi display not found (ret=%d)\n", __func__, ret);
+
+	ret = uclass_find_device_by_name(UCLASS_DISPLAY,
+					"sunxi_tve", &disp);
 	if (ret) {
-		debug("%s: hdmi display not found (ret=%d)\n", __func__, ret);
+		debug("%s: tv not found (ret=%d)\n", __func__, ret);
 		return ret;
 	}
 
-	if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
-		mux = 0;
-	else
-		mux = 1;
-
-	ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux);
+	ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, 1, true);
 	if (ret)
 		return ret;
 
diff --git a/drivers/video/sunxi/sunxi_tve.c b/drivers/video/sunxi/sunxi_tve.c
new file mode 100644
index 0000000000..95f54bbaf7
--- /dev/null
+++ b/drivers/video/sunxi/sunxi_tve.c
@@ -0,0 +1,156 @@
+/*
+ * Allwinner TVE driver
+ *
+ * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <display.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/lcdc.h>
+#include <asm/arch/tve.h>
+
+static int sunxi_tve_get_plug_in_status(void)
+{
+	struct sunxi_tve_reg * const tve =
+		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
+	u32 status;
+
+	status = readl(&tve->auto_detect_status) &
+		SUNXI_TVE_AUTO_DETECT_STATUS_MASK(0);
+
+	return status == SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED;
+}
+
+static int sunxi_tve_wait_for_hpd(void)
+{
+	struct sunxi_tve_reg * const tve =
+		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
+	ulong start;
+
+	/* enable auto detection */
+	writel(SUNXI_TVE_DAC_CFG0_DETECTION, &tve->dac_cfg0);
+	writel(SUNXI_TVE_AUTO_DETECT_CFG0, &tve->auto_detect_cfg0);
+	writel(SUNXI_TVE_AUTO_DETECT_CFG1, &tve->auto_detect_cfg1);
+	writel(9 << SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(0),
+	       &tve->auto_detect_debounce);
+	writel(SUNXI_TVE_AUTO_DETECT_EN_DET_EN(0), &tve->auto_detect_en);
+
+	start = get_timer(0);
+	do {
+		if (sunxi_tve_get_plug_in_status())
+			return 0;
+		udelay(100);
+	} while (get_timer(start) < 300);
+
+	return -1;
+}
+
+static void sunxi_tve_lcdc_init(const struct display_timing *edid, int bpp)
+{
+	struct sunxi_ccm_reg * const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_lcdc_reg * const lcdc =
+		(struct sunxi_lcdc_reg *)SUNXI_LCD1_BASE;
+
+	/* Reset off */
+	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD1);
+
+	/* Clock on */
+	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD1);
+
+	lcdc_init(lcdc);
+	lcdc_tcon1_mode_set(lcdc, edid, false, true);
+	lcdc_enable(lcdc, bpp);
+}
+
+static int sunxi_tve_read_timing(struct udevice *dev,
+				 struct display_timing *timing)
+{
+	/* PAL resolution */
+	timing->pixelclock.typ = 27000000;
+
+	timing->hactive.typ = 720;
+	timing->hfront_porch.typ = 5;
+	timing->hback_porch.typ = 137;
+	timing->hsync_len.typ = 2;
+
+	timing->vactive.typ = 576;
+	timing->vfront_porch.typ = 27;
+	timing->vback_porch.typ = 20;
+	timing->vsync_len.typ = 2;
+
+	timing->flags = DISPLAY_FLAGS_INTERLACED;
+
+	return 0;
+}
+
+static int sunxi_tve_enable(struct udevice *dev, int panel_bpp,
+			    const struct display_timing *edid)
+{
+	struct sunxi_tve_reg * const tve =
+		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
+
+	sunxi_tve_lcdc_init(edid, panel_bpp);
+
+	tvencoder_mode_set(tve, tve_mode_composite_pal);
+	tvencoder_enable(tve);
+
+	return 0;
+}
+
+static int sunxi_tve_probe(struct udevice *dev)
+{
+	struct sunxi_ccm_reg * const ccm =
+		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+	struct sunxi_tve_reg * const tve =
+		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
+	int ret;
+
+	/* make sure that clock is active */
+	clock_set_pll10(432000000);
+
+	/* Reset off */
+	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TVE);
+
+	/* Clock on */
+	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE);
+	writel(CCM_TVE_CTRL_GATE | CCM_TVE_CTRL_M(2), &ccm->tve_clk_cfg);
+
+#ifdef CONFIG_MACH_SUN50I_H5
+	writel(SUNXI_TVE_CALIBRATION_H5, &tve->calibration);
+	writel(SUNXI_TVE_UNKNOWN3_H5, &tve->unknown3);
+#else
+	writel(SUNXI_TVE_CALIBRATION_H3, &tve->calibration);
+#endif
+
+	ret = sunxi_tve_wait_for_hpd();
+	if (ret < 0) {
+		debug("tve can not get hpd signal\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static const struct dm_display_ops sunxi_tve_ops = {
+	.read_timing = sunxi_tve_read_timing,
+	.enable = sunxi_tve_enable,
+};
+
+U_BOOT_DRIVER(sunxi_tve) = {
+	.name	= "sunxi_tve",
+	.id	= UCLASS_DISPLAY,
+	.ops	= &sunxi_tve_ops,
+	.probe	= sunxi_tve_probe,
+};
+
+#ifdef CONFIG_MACH_SUNXI_H3_H5
+U_BOOT_DEVICE(sunxi_tve) = {
+	.name = "sunxi_tve"
+};
+#endif
diff --git a/drivers/video/sunxi/tve.c b/drivers/video/sunxi/tve.c
index adea78a69a..ef99c111e3 100644
--- a/drivers/video/sunxi/tve.c
+++ b/drivers/video/sunxi/tve.c
@@ -25,8 +25,6 @@ void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode)
 		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) |
@@ -35,6 +33,10 @@ void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode)
 		writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
 		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
 		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
+		if (mode == tve_mode_composite_pal)
+			writel(SUNXI_TVE_CHROMA_FREQ_PAL, &tve->chroma_freq);
+		else
+			writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
 		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,
-- 
2.12.2

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder
  2017-05-10 16:46 ` [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder Jernej Skrabec
@ 2017-05-12 15:47   ` Maxime Ripard
  2017-05-12 16:55     ` Jernej Škrabec
  2017-05-15 19:25   ` Anatolij Gustschin
  1 sibling, 1 reply; 20+ messages in thread
From: Maxime Ripard @ 2017-05-12 15:47 UTC (permalink / raw)
  To: u-boot

Hi Jernej,

On Wed, May 10, 2017 at 06:46:29PM +0200, Jernej Skrabec wrote:
> This patch adds support for TV encoder clocks which will be used later.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
> 
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> index a44ea77576..dc011cc964 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> @@ -83,7 +83,8 @@ struct sunxi_ccm_reg {
>  	u32 lcd0_ch0_clk_cfg;	/* 0x118 LCD0 CH0 module clock */
>  	u32 lcd1_ch0_clk_cfg;	/* 0x11c LCD1 CH0 module clock */
>  #endif
> -	u32 reserved14[3];
> +	u32 tve_clk_cfg;	/* 0x120 TVE module clock */
> +	u32 reserved14[2];

Maybe we should protect that with a comment, or an ifdef, that this is
only for the H3-generation SoCs?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170512/2e6c57fa/attachment.sig>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-10 16:46 ` [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver Jernej Skrabec
@ 2017-05-12 16:06   ` Maxime Ripard
  2017-05-13 15:02     ` [U-Boot] [linux-sunxi] " icenowy at aosc.io
  2017-05-15  3:03     ` [U-Boot] " Simon Glass
  0 siblings, 2 replies; 20+ messages in thread
From: Maxime Ripard @ 2017-05-12 16:06 UTC (permalink / raw)
  To: u-boot

Hi Jernej,

The patch content looks fine, but there's a few things that would need
to be addressed.

On Wed, May 10, 2017 at 06:46:30PM +0200, Jernej Skrabec wrote:
> This commit adds support for TV (composite) output.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
> 
>  arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  10 ++
>  arch/arm/include/asm/arch-sunxi/display2.h  |  17 +++
>  arch/arm/include/asm/arch-sunxi/tve.h       |  17 ++-
>  drivers/video/sunxi/Makefile                |   2 +-
>  drivers/video/sunxi/sunxi_de2.c             |  60 ++++++++---
>  drivers/video/sunxi/sunxi_tve.c             | 156 ++++++++++++++++++++++++++++
>  drivers/video/sunxi/tve.c                   |   6 +-

The difference between sunxi_tve and tve is not really obvious. What
about calling sunxi_tve tve-uclass, or something like that?

>  7 files changed, 251 insertions(+), 17 deletions(-)
>  create mode 100644 drivers/video/sunxi/sunxi_tve.c
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
> index 6aa5e91ada..2419062d45 100644
> --- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
> +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
> @@ -34,7 +34,9 @@
>  #define SUNXI_MS_BASE			0x01c07000
>  #define SUNXI_TVD_BASE			0x01c08000
>  #define SUNXI_CSI0_BASE			0x01c09000
> +#ifndef CONFIG_MACH_SUNXI_H3_H5
>  #define SUNXI_TVE0_BASE			0x01c0a000
> +#endif

This should be part of a seperate patch.

>  #define SUNXI_EMAC_BASE			0x01c0b000
>  #define SUNXI_LCD0_BASE			0x01c0C000
>  #define SUNXI_LCD1_BASE			0x01c0d000
> @@ -161,10 +163,18 @@ defined(CONFIG_MACH_SUN50I)
>  /* module sram */
>  #define SUNXI_SRAM_C_BASE		0x01d00000
>  
> +#ifndef CONFIG_MACH_SUN8I_H3
>  #define SUNXI_DE_FE0_BASE		0x01e00000
> +#else
> +#define SUNXI_TVE0_BASE			0x01e00000
> +#endif

This one should be in that other patch

>  #define SUNXI_DE_FE1_BASE		0x01e20000
>  #define SUNXI_DE_BE0_BASE		0x01e60000
> +#ifndef CONFIG_MACH_SUN50I_H5
>  #define SUNXI_DE_BE1_BASE		0x01e40000
> +#else
> +#define SUNXI_TVE0_BASE			0x01e40000
> +#endif

And that one too.

>  #define SUNXI_MP_BASE			0x01e80000
>  #define SUNXI_AVG_BASE			0x01ea0000
>  
> diff --git a/arch/arm/include/asm/arch-sunxi/display2.h b/arch/arm/include/asm/arch-sunxi/display2.h
> index b5875f9605..359cacd90b 100644
> --- a/arch/arm/include/asm/arch-sunxi/display2.h
> +++ b/arch/arm/include/asm/arch-sunxi/display2.h
> @@ -90,6 +90,23 @@ struct de_ui {
>  	u32 ovl_size;
>  };
>  
> +struct de_csc {
> +	u32 csc_ctl;
> +	u8 res[0xc];
> +	u32 coef11;
> +	u32 coef12;
> +	u32 coef13;
> +	u32 coef14;
> +	u32 coef21;
> +	u32 coef22;
> +	u32 coef23;
> +	u32 coef24;
> +	u32 coef31;
> +	u32 coef32;
> +	u32 coef33;
> +	u32 coef34;
> +};
> +

This should be in another patch (let's call it patch 2)

>  /*
>   * DE register constants.
>   */
> diff --git a/arch/arm/include/asm/arch-sunxi/tve.h b/arch/arm/include/asm/arch-sunxi/tve.h
> index 41a14a68e4..ff34bbbc12 100644
> --- a/arch/arm/include/asm/arch-sunxi/tve.h
> +++ b/arch/arm/include/asm/arch-sunxi/tve.h
> @@ -45,7 +45,9 @@ struct sunxi_tve_reg {
>  	u32 csc_reg1;			/* 0x044 */
>  	u32 csc_reg2;			/* 0x048 */
>  	u32 csc_reg3;			/* 0x04c */
> -	u8 res1[0xb0];			/* 0x050 */
> +	u8 res1[0xa8];			/* 0x050 */
> +	u32 auto_detect_cfg0;		/* 0x0f8 */
> +	u32 auto_detect_cfg1;		/* 0x0fc */
>  	u32 color_burst;		/* 0x100 */
>  	u32 vsync_num;			/* 0x104 */
>  	u32 notch_freq;			/* 0x108 */
> @@ -62,6 +64,10 @@ struct sunxi_tve_reg {
>  	u32 slave_para;			/* 0x134 */
>  	u32 cfg1;			/* 0x138 */
>  	u32 cfg2;			/* 0x13c */
> +	u8 res2[0x1c4];			/* 0x140 */
> +	u32 calibration;		/* 0x304 */
> +	u8 res3[0x4];			/* 0x308 */
> +	u32 unknown3;			/* 0x30c */

And these yet another one (patch 3)

>  };
>  
>  /*
> @@ -79,12 +85,14 @@ struct sunxi_tve_reg {
>  #define SUNXI_TVE_CFG0_PAL			0x07030001
>  #define SUNXI_TVE_CFG0_NTSC			0x07030000
>  #define SUNXI_TVE_DAC_CFG0_VGA			0x403e1ac7
> -#ifdef CONFIG_MACH_SUN5I
> +#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUNXI_H3_H5)
>  #define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x433f0009
>  #else
>  #define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x403f0008
>  #endif
> +#define SUNXI_TVE_DAC_CFG0_DETECTION		0x433f0289
>  #define SUNXI_TVE_FILTER_COMPOSITE		0x00000120
> +#define SUNXI_TVE_CHROMA_FREQ_PAL		0x2a098acb
>  #define SUNXI_TVE_CHROMA_FREQ_PAL_M		0x21e6efe3
>  #define SUNXI_TVE_CHROMA_FREQ_PAL_NC		0x21f69446
>  #define SUNXI_TVE_PORCH_NUM_PAL			0x008a0018
> @@ -105,6 +113,8 @@ struct sunxi_tve_reg {
>  #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_AUTO_DETECT_CFG0		0x00000280
> +#define SUNXI_TVE_AUTO_DETECT_CFG1		0x028F00FF
>  #define SUNXI_TVE_CSC_REG0_ENABLE		(1 << 31)
>  #define SUNXI_TVE_CSC_REG0			0x08440832
>  #define SUNXI_TVE_CSC_REG1			0x3b6dace1
> @@ -124,6 +134,9 @@ struct sunxi_tve_reg {
>  #define SUNXI_TVE_RESYNC_NUM_PAL		0x800d000c
>  #define SUNXI_TVE_RESYNC_NUM_NTSC		0x000e000c
>  #define SUNXI_TVE_SLAVE_PARA_COMPOSITE		0x00000000
> +#define SUNXI_TVE_CALIBRATION_H3		0x02000c00
> +#define SUNXI_TVE_CALIBRATION_H5		0x02850000
> +#define SUNXI_TVE_UNKNOWN3_H5			0x00101110

patch 3

>  
>  void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode);
>  void tvencoder_enable(struct sunxi_tve_reg * const tve);
> diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile
> index dbaab61b59..1db82c53f0 100644
> --- a/drivers/video/sunxi/Makefile
> +++ b/drivers/video/sunxi/Makefile
> @@ -6,4 +6,4 @@
>  #
>  
>  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
> +obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o sunxi_tve.o tve.o lcdc.o ../dw_hdmi.o
> diff --git a/drivers/video/sunxi/sunxi_de2.c b/drivers/video/sunxi/sunxi_de2.c
> index 9a32c3a020..ee67764ac5 100644
> --- a/drivers/video/sunxi/sunxi_de2.c
> +++ b/drivers/video/sunxi/sunxi_de2.c
> @@ -56,7 +56,7 @@ static void sunxi_de2_composer_init(void)
>  }
>  
>  static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
> -			       int bpp, ulong address)
> +			       int bpp, ulong address, bool is_composite)
>  {
>  	ulong de_mux_base = (mux == 0) ?
>  			    SUNXI_DE2_MUX0_BASE : SUNXI_DE2_MUX1_BASE;

patch 2

> @@ -72,6 +72,9 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
>  		(struct de_ui *)(de_mux_base +
>  				 SUNXI_DE2_MUX_CHAN_REGS +
>  				 SUNXI_DE2_MUX_CHAN_SZ * 1);
> +	struct de_csc * const de_csc_regs =
> +		(struct de_csc *)(de_mux_base +
> +				  SUNXI_DE2_MUX_DCSC_REGS);

patch 2

>  	u32 size = SUNXI_DE2_WH(mode->hactive.typ, mode->vactive.typ);
>  	int channel;
>  	u32 format;
> @@ -128,7 +131,27 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
>  	writel(0, de_mux_base + SUNXI_DE2_MUX_PEAK_REGS);
>  	writel(0, de_mux_base + SUNXI_DE2_MUX_ASE_REGS);
>  	writel(0, de_mux_base + SUNXI_DE2_MUX_FCC_REGS);
> -	writel(0, de_mux_base + SUNXI_DE2_MUX_DCSC_REGS);
> +
> +	if (is_composite) {
> +		/* set CSC coefficients */
> +		writel(0x107, &de_csc_regs->coef11);
> +		writel(0x204, &de_csc_regs->coef12);
> +		writel(0x64, &de_csc_regs->coef13);
> +		writel(0x4200, &de_csc_regs->coef14);
> +		writel(0x1f68, &de_csc_regs->coef21);
> +		writel(0x1ed6, &de_csc_regs->coef22);
> +		writel(0x1c2, &de_csc_regs->coef23);
> +		writel(0x20200, &de_csc_regs->coef24);
> +		writel(0x1c2, &de_csc_regs->coef31);
> +		writel(0x1e87, &de_csc_regs->coef32);
> +		writel(0x1fb7, &de_csc_regs->coef33);
> +		writel(0x20200, &de_csc_regs->coef34);
> +
> +		/* enable CSC unit */
> +		writel(1, &de_csc_regs->csc_ctl);
> +	} else {
> +		writel(0, &de_csc_regs->csc_ctl);
> +	}

patch 2

>  
>  	switch (bpp) {
>  	case 16:
> @@ -153,7 +176,7 @@ static void sunxi_de2_mode_set(int mux, const struct display_timing *mode,
>  
>  static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
>  			  enum video_log2_bpp l2bpp,
> -			  struct udevice *disp, int mux)
> +			  struct udevice *disp, int mux, bool is_composite)
>  {
>  	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
>  	struct display_timing timing;
> @@ -183,7 +206,7 @@ static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
>  	}
>  
>  	sunxi_de2_composer_init();
> -	sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase);
> +	sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase, is_composite);
>  
>  	ret = display_enable(disp, 1 << l2bpp, &timing);
>  	if (ret) {
> @@ -204,7 +227,6 @@ static int sunxi_de2_probe(struct udevice *dev)
>  	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
>  	struct udevice *disp;
>  	int ret;
> -	int mux;
>  
>  	/* Before relocation we don't need to do anything */
>  	if (!(gd->flags & GD_FLG_RELOC))
> @@ -212,17 +234,31 @@ static int sunxi_de2_probe(struct udevice *dev)
>  
>  	ret = uclass_find_device_by_name(UCLASS_DISPLAY,
>  					 "sunxi_dw_hdmi", &disp);
> +	if (!ret) {
> +		int mux;
> +		if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
> +			mux = 0;
> +		else
> +			mux = 1;
> +
> +		ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux,
> +				     false);
> +		if (!ret) {
> +			video_set_flush_dcache(dev, 1);
> +			return 0;
> +		}
> +	}
> +
> +	debug("%s: hdmi display not found (ret=%d)\n", __func__, ret);
> +
> +	ret = uclass_find_device_by_name(UCLASS_DISPLAY,
> +					"sunxi_tve", &disp);
>  	if (ret) {
> -		debug("%s: hdmi display not found (ret=%d)\n", __func__, ret);
> +		debug("%s: tv not found (ret=%d)\n", __func__, ret);
>  		return ret;
>  	}
>  
> -	if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
> -		mux = 0;
> -	else
> -		mux = 1;
> -
> -	ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux);
> +	ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, 1, true);

patch 2

>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/video/sunxi/sunxi_tve.c b/drivers/video/sunxi/sunxi_tve.c
> new file mode 100644
> index 0000000000..95f54bbaf7
> --- /dev/null
> +++ b/drivers/video/sunxi/sunxi_tve.c
> @@ -0,0 +1,156 @@
> +/*
> + * Allwinner TVE driver
> + *
> + * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <display.h>
> +#include <dm.h>
> +#include <asm/io.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/lcdc.h>
> +#include <asm/arch/tve.h>
> +
> +static int sunxi_tve_get_plug_in_status(void)
> +{
> +	struct sunxi_tve_reg * const tve =
> +		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
> +	u32 status;
> +
> +	status = readl(&tve->auto_detect_status) &
> +		SUNXI_TVE_AUTO_DETECT_STATUS_MASK(0);
> +
> +	return status == SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED;
> +}
> +
> +static int sunxi_tve_wait_for_hpd(void)
> +{
> +	struct sunxi_tve_reg * const tve =
> +		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
> +	ulong start;
> +
> +	/* enable auto detection */
> +	writel(SUNXI_TVE_DAC_CFG0_DETECTION, &tve->dac_cfg0);
> +	writel(SUNXI_TVE_AUTO_DETECT_CFG0, &tve->auto_detect_cfg0);
> +	writel(SUNXI_TVE_AUTO_DETECT_CFG1, &tve->auto_detect_cfg1);
> +	writel(9 << SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(0),
> +	       &tve->auto_detect_debounce);
> +	writel(SUNXI_TVE_AUTO_DETECT_EN_DET_EN(0), &tve->auto_detect_en);
> +
> +	start = get_timer(0);
> +	do {
> +		if (sunxi_tve_get_plug_in_status())
> +			return 0;
> +		udelay(100);
> +	} while (get_timer(start) < 300);
> +
> +	return -1;
> +}
> +
> +static void sunxi_tve_lcdc_init(const struct display_timing *edid, int bpp)
> +{
> +	struct sunxi_ccm_reg * const ccm =
> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +	struct sunxi_lcdc_reg * const lcdc =
> +		(struct sunxi_lcdc_reg *)SUNXI_LCD1_BASE;
> +
> +	/* Reset off */
> +	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD1);
> +
> +	/* Clock on */
> +	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD1);
> +
> +	lcdc_init(lcdc);
> +	lcdc_tcon1_mode_set(lcdc, edid, false, true);
> +	lcdc_enable(lcdc, bpp);
> +}
> +
> +static int sunxi_tve_read_timing(struct udevice *dev,
> +				 struct display_timing *timing)
> +{
> +	/* PAL resolution */
> +	timing->pixelclock.typ = 27000000;
> +
> +	timing->hactive.typ = 720;
> +	timing->hfront_porch.typ = 5;
> +	timing->hback_porch.typ = 137;
> +	timing->hsync_len.typ = 2;
> +
> +	timing->vactive.typ = 576;
> +	timing->vfront_porch.typ = 27;
> +	timing->vback_porch.typ = 20;
> +	timing->vsync_len.typ = 2;
> +
> +	timing->flags = DISPLAY_FLAGS_INTERLACED;
> +
> +	return 0;
> +}
> +
> +static int sunxi_tve_enable(struct udevice *dev, int panel_bpp,
> +			    const struct display_timing *edid)
> +{
> +	struct sunxi_tve_reg * const tve =
> +		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
> +
> +	sunxi_tve_lcdc_init(edid, panel_bpp);
> +
> +	tvencoder_mode_set(tve, tve_mode_composite_pal);
> +	tvencoder_enable(tve);
> +
> +	return 0;
> +}
> +
> +static int sunxi_tve_probe(struct udevice *dev)
> +{
> +	struct sunxi_ccm_reg * const ccm =
> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> +	struct sunxi_tve_reg * const tve =
> +		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
> +	int ret;
> +
> +	/* make sure that clock is active */
> +	clock_set_pll10(432000000);
> +
> +	/* Reset off */
> +	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TVE);
> +
> +	/* Clock on */
> +	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE);
> +	writel(CCM_TVE_CTRL_GATE | CCM_TVE_CTRL_M(2), &ccm->tve_clk_cfg);
> +
> +#ifdef CONFIG_MACH_SUN50I_H5
> +	writel(SUNXI_TVE_CALIBRATION_H5, &tve->calibration);
> +	writel(SUNXI_TVE_UNKNOWN3_H5, &tve->unknown3);
> +#else
> +	writel(SUNXI_TVE_CALIBRATION_H3, &tve->calibration);
> +#endif
> +
> +	ret = sunxi_tve_wait_for_hpd();
> +	if (ret < 0) {
> +		debug("tve can not get hpd signal\n");
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dm_display_ops sunxi_tve_ops = {
> +	.read_timing = sunxi_tve_read_timing,
> +	.enable = sunxi_tve_enable,
> +};
> +
> +U_BOOT_DRIVER(sunxi_tve) = {
> +	.name	= "sunxi_tve",
> +	.id	= UCLASS_DISPLAY,
> +	.ops	= &sunxi_tve_ops,
> +	.probe	= sunxi_tve_probe,
> +};
> +
> +#ifdef CONFIG_MACH_SUNXI_H3_H5
> +U_BOOT_DEVICE(sunxi_tve) = {
> +	.name = "sunxi_tve"
> +};
> +#endif

patch 3

> diff --git a/drivers/video/sunxi/tve.c b/drivers/video/sunxi/tve.c
> index adea78a69a..ef99c111e3 100644
> --- a/drivers/video/sunxi/tve.c
> +++ b/drivers/video/sunxi/tve.c
> @@ -25,8 +25,6 @@ void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode)
>  		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) |
> @@ -35,6 +33,10 @@ void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode mode)
>  		writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
>  		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
>  		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
> +		if (mode == tve_mode_composite_pal)
> +			writel(SUNXI_TVE_CHROMA_FREQ_PAL, &tve->chroma_freq);
> +		else
> +			writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
>  		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,

And patch 3 as well.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170512/687fe4ff/attachment.sig>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder
  2017-05-12 15:47   ` Maxime Ripard
@ 2017-05-12 16:55     ` Jernej Škrabec
  2017-05-12 20:27       ` Maxime Ripard
  0 siblings, 1 reply; 20+ messages in thread
From: Jernej Škrabec @ 2017-05-12 16:55 UTC (permalink / raw)
  To: u-boot

Hi Maxime,

Dne petek, 12. maj 2017 ob 17:47:17 CEST je Maxime Ripard napisal(a):
> Hi Jernej,
> 
> On Wed, May 10, 2017 at 06:46:29PM +0200, Jernej Skrabec wrote:
> > This patch adds support for TV encoder clocks which will be used later.
> > 
> > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > ---
> > 
> >  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 8 +++++++-
> >  1 file changed, 7 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index
> > a44ea77576..dc011cc964 100644
> > --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > @@ -83,7 +83,8 @@ struct sunxi_ccm_reg {
> > 
> >  	u32 lcd0_ch0_clk_cfg;	/* 0x118 LCD0 CH0 module clock */
> >  	u32 lcd1_ch0_clk_cfg;	/* 0x11c LCD1 CH0 module clock */
> >  
> >  #endif
> > 
> > -	u32 reserved14[3];
> > +	u32 tve_clk_cfg;	/* 0x120 TVE module clock */
> > +	u32 reserved14[2];
> 
> Maybe we should protect that with a comment, or an ifdef, that this is
> only for the H3-generation SoCs?

I vote for extending the comment, like: 
/* 0x120 H3/H5 TVE module clock */

Would that be ok?

Best regards,
Jernej

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder
  2017-05-12 16:55     ` Jernej Škrabec
@ 2017-05-12 20:27       ` Maxime Ripard
  0 siblings, 0 replies; 20+ messages in thread
From: Maxime Ripard @ 2017-05-12 20:27 UTC (permalink / raw)
  To: u-boot

On Fri, May 12, 2017 at 06:55:56PM +0200, Jernej Å krabec wrote:
> Hi Maxime,
> 
> Dne petek, 12. maj 2017 ob 17:47:17 CEST je Maxime Ripard napisal(a):
> > Hi Jernej,
> > 
> > On Wed, May 10, 2017 at 06:46:29PM +0200, Jernej Skrabec wrote:
> > > This patch adds support for TV encoder clocks which will be used later.
> > > 
> > > Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > > ---
> > > 
> > >  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 8 +++++++-
> > >  1 file changed, 7 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > > b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h index
> > > a44ea77576..dc011cc964 100644
> > > --- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > > +++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
> > > @@ -83,7 +83,8 @@ struct sunxi_ccm_reg {
> > > 
> > >  	u32 lcd0_ch0_clk_cfg;	/* 0x118 LCD0 CH0 module clock */
> > >  	u32 lcd1_ch0_clk_cfg;	/* 0x11c LCD1 CH0 module clock */
> > >  
> > >  #endif
> > > 
> > > -	u32 reserved14[3];
> > > +	u32 tve_clk_cfg;	/* 0x120 TVE module clock */
> > > +	u32 reserved14[2];
> > 
> > Maybe we should protect that with a comment, or an ifdef, that this is
> > only for the H3-generation SoCs?
> 
> I vote for extending the comment, like: 
> /* 0x120 H3/H5 TVE module clock */
> 
> Would that be ok?

That works, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170512/4686a5af/attachment.sig>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [linux-sunxi] Re: [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-12 16:06   ` Maxime Ripard
@ 2017-05-13 15:02     ` icenowy at aosc.io
  2017-05-13 15:14       ` Chen-Yu Tsai
  2017-05-15  3:03     ` [U-Boot] " Simon Glass
  1 sibling, 1 reply; 20+ messages in thread
From: icenowy at aosc.io @ 2017-05-13 15:02 UTC (permalink / raw)
  To: u-boot

在 2017-05-13 00:06,Maxime Ripard 写道:
> Hi Jernej,
> 
> The patch content looks fine, but there's a few things that would need
> to be addressed.
> 
> On Wed, May 10, 2017 at 06:46:30PM +0200, Jernej Skrabec wrote:
>> This commit adds support for TV (composite) output.
>> 
>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>> ---
>> 
>>  arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  10 ++
>>  arch/arm/include/asm/arch-sunxi/display2.h  |  17 +++
>>  arch/arm/include/asm/arch-sunxi/tve.h       |  17 ++-
>>  drivers/video/sunxi/Makefile                |   2 +-
>>  drivers/video/sunxi/sunxi_de2.c             |  60 ++++++++---
>>  drivers/video/sunxi/sunxi_tve.c             | 156 
>> ++++++++++++++++++++++++++++
>>  drivers/video/sunxi/tve.c                   |   6 +-
> 
> The difference between sunxi_tve and tve is not really obvious. What
> about calling sunxi_tve tve-uclass, or something like that?
> 
>>  7 files changed, 251 insertions(+), 17 deletions(-)
>>  create mode 100644 drivers/video/sunxi/sunxi_tve.c
>> 
>> diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h 
>> b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
>> index 6aa5e91ada..2419062d45 100644
>> --- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
>> +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
>> @@ -34,7 +34,9 @@
>>  #define SUNXI_MS_BASE			0x01c07000
>>  #define SUNXI_TVD_BASE			0x01c08000
>>  #define SUNXI_CSI0_BASE			0x01c09000
>> +#ifndef CONFIG_MACH_SUNXI_H3_H5
>>  #define SUNXI_TVE0_BASE			0x01c0a000
>> +#endif
> 
> This should be part of a seperate patch.
> 
>>  #define SUNXI_EMAC_BASE			0x01c0b000
>>  #define SUNXI_LCD0_BASE			0x01c0C000
>>  #define SUNXI_LCD1_BASE			0x01c0d000
>> @@ -161,10 +163,18 @@ defined(CONFIG_MACH_SUN50I)
>>  /* module sram */
>>  #define SUNXI_SRAM_C_BASE		0x01d00000
>> 
>> +#ifndef CONFIG_MACH_SUN8I_H3
>>  #define SUNXI_DE_FE0_BASE		0x01e00000
>> +#else
>> +#define SUNXI_TVE0_BASE			0x01e00000
>> +#endif
> 
> This one should be in that other patch
> 
>>  #define SUNXI_DE_FE1_BASE		0x01e20000
>>  #define SUNXI_DE_BE0_BASE		0x01e60000
>> +#ifndef CONFIG_MACH_SUN50I_H5
>>  #define SUNXI_DE_BE1_BASE		0x01e40000
>> +#else
>> +#define SUNXI_TVE0_BASE			0x01e40000
>> +#endif
> 
> And that one too.
> 
>>  #define SUNXI_MP_BASE			0x01e80000
>>  #define SUNXI_AVG_BASE			0x01ea0000
>> 
>> diff --git a/arch/arm/include/asm/arch-sunxi/display2.h 
>> b/arch/arm/include/asm/arch-sunxi/display2.h
>> index b5875f9605..359cacd90b 100644
>> --- a/arch/arm/include/asm/arch-sunxi/display2.h
>> +++ b/arch/arm/include/asm/arch-sunxi/display2.h
>> @@ -90,6 +90,23 @@ struct de_ui {
>>  	u32 ovl_size;
>>  };
>> 
>> +struct de_csc {
>> +	u32 csc_ctl;
>> +	u8 res[0xc];
>> +	u32 coef11;
>> +	u32 coef12;
>> +	u32 coef13;
>> +	u32 coef14;
>> +	u32 coef21;
>> +	u32 coef22;
>> +	u32 coef23;
>> +	u32 coef24;
>> +	u32 coef31;
>> +	u32 coef32;
>> +	u32 coef33;
>> +	u32 coef34;
>> +};
>> +
> 
> This should be in another patch (let's call it patch 2)
> 
>>  /*
>>   * DE register constants.
>>   */
>> diff --git a/arch/arm/include/asm/arch-sunxi/tve.h 
>> b/arch/arm/include/asm/arch-sunxi/tve.h
>> index 41a14a68e4..ff34bbbc12 100644
>> --- a/arch/arm/include/asm/arch-sunxi/tve.h
>> +++ b/arch/arm/include/asm/arch-sunxi/tve.h
>> @@ -45,7 +45,9 @@ struct sunxi_tve_reg {
>>  	u32 csc_reg1;			/* 0x044 */
>>  	u32 csc_reg2;			/* 0x048 */
>>  	u32 csc_reg3;			/* 0x04c */
>> -	u8 res1[0xb0];			/* 0x050 */
>> +	u8 res1[0xa8];			/* 0x050 */
>> +	u32 auto_detect_cfg0;		/* 0x0f8 */
>> +	u32 auto_detect_cfg1;		/* 0x0fc */
>>  	u32 color_burst;		/* 0x100 */
>>  	u32 vsync_num;			/* 0x104 */
>>  	u32 notch_freq;			/* 0x108 */
>> @@ -62,6 +64,10 @@ struct sunxi_tve_reg {
>>  	u32 slave_para;			/* 0x134 */
>>  	u32 cfg1;			/* 0x138 */
>>  	u32 cfg2;			/* 0x13c */
>> +	u8 res2[0x1c4];			/* 0x140 */
>> +	u32 calibration;		/* 0x304 */
>> +	u8 res3[0x4];			/* 0x308 */
>> +	u32 unknown3;			/* 0x30c */
> 
> And these yet another one (patch 3)
> 
>>  };
>> 
>>  /*
>> @@ -79,12 +85,14 @@ struct sunxi_tve_reg {
>>  #define SUNXI_TVE_CFG0_PAL			0x07030001
>>  #define SUNXI_TVE_CFG0_NTSC			0x07030000
>>  #define SUNXI_TVE_DAC_CFG0_VGA			0x403e1ac7
>> -#ifdef CONFIG_MACH_SUN5I
>> +#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUNXI_H3_H5)
>>  #define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x433f0009
>>  #else
>>  #define SUNXI_TVE_DAC_CFG0_COMPOSITE		0x403f0008
>>  #endif
>> +#define SUNXI_TVE_DAC_CFG0_DETECTION		0x433f0289
>>  #define SUNXI_TVE_FILTER_COMPOSITE		0x00000120
>> +#define SUNXI_TVE_CHROMA_FREQ_PAL		0x2a098acb
>>  #define SUNXI_TVE_CHROMA_FREQ_PAL_M		0x21e6efe3
>>  #define SUNXI_TVE_CHROMA_FREQ_PAL_NC		0x21f69446
>>  #define SUNXI_TVE_PORCH_NUM_PAL			0x008a0018
>> @@ -105,6 +113,8 @@ struct sunxi_tve_reg {
>>  #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_AUTO_DETECT_CFG0		0x00000280
>> +#define SUNXI_TVE_AUTO_DETECT_CFG1		0x028F00FF
>>  #define SUNXI_TVE_CSC_REG0_ENABLE		(1 << 31)
>>  #define SUNXI_TVE_CSC_REG0			0x08440832
>>  #define SUNXI_TVE_CSC_REG1			0x3b6dace1
>> @@ -124,6 +134,9 @@ struct sunxi_tve_reg {
>>  #define SUNXI_TVE_RESYNC_NUM_PAL		0x800d000c
>>  #define SUNXI_TVE_RESYNC_NUM_NTSC		0x000e000c
>>  #define SUNXI_TVE_SLAVE_PARA_COMPOSITE		0x00000000
>> +#define SUNXI_TVE_CALIBRATION_H3		0x02000c00
>> +#define SUNXI_TVE_CALIBRATION_H5		0x02850000
>> +#define SUNXI_TVE_UNKNOWN3_H5			0x00101110
> 
> patch 3
> 
>> 
>>  void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum 
>> tve_mode mode);
>>  void tvencoder_enable(struct sunxi_tve_reg * const tve);
>> diff --git a/drivers/video/sunxi/Makefile 
>> b/drivers/video/sunxi/Makefile
>> index dbaab61b59..1db82c53f0 100644
>> --- a/drivers/video/sunxi/Makefile
>> +++ b/drivers/video/sunxi/Makefile
>> @@ -6,4 +6,4 @@
>>  #
>> 
>>  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
>> +obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o sunxi_tve.o 
>> tve.o lcdc.o ../dw_hdmi.o
>> diff --git a/drivers/video/sunxi/sunxi_de2.c 
>> b/drivers/video/sunxi/sunxi_de2.c
>> index 9a32c3a020..ee67764ac5 100644
>> --- a/drivers/video/sunxi/sunxi_de2.c
>> +++ b/drivers/video/sunxi/sunxi_de2.c
>> @@ -56,7 +56,7 @@ static void sunxi_de2_composer_init(void)
>>  }
>> 
>>  static void sunxi_de2_mode_set(int mux, const struct display_timing 
>> *mode,
>> -			       int bpp, ulong address)
>> +			       int bpp, ulong address, bool is_composite)
>>  {
>>  	ulong de_mux_base = (mux == 0) ?
>>  			    SUNXI_DE2_MUX0_BASE : SUNXI_DE2_MUX1_BASE;
> 
> patch 2
> 
>> @@ -72,6 +72,9 @@ static void sunxi_de2_mode_set(int mux, const struct 
>> display_timing *mode,
>>  		(struct de_ui *)(de_mux_base +
>>  				 SUNXI_DE2_MUX_CHAN_REGS +
>>  				 SUNXI_DE2_MUX_CHAN_SZ * 1);
>> +	struct de_csc * const de_csc_regs =
>> +		(struct de_csc *)(de_mux_base +
>> +				  SUNXI_DE2_MUX_DCSC_REGS);
> 
> patch 2
> 
>>  	u32 size = SUNXI_DE2_WH(mode->hactive.typ, mode->vactive.typ);
>>  	int channel;
>>  	u32 format;
>> @@ -128,7 +131,27 @@ static void sunxi_de2_mode_set(int mux, const 
>> struct display_timing *mode,
>>  	writel(0, de_mux_base + SUNXI_DE2_MUX_PEAK_REGS);
>>  	writel(0, de_mux_base + SUNXI_DE2_MUX_ASE_REGS);
>>  	writel(0, de_mux_base + SUNXI_DE2_MUX_FCC_REGS);
>> -	writel(0, de_mux_base + SUNXI_DE2_MUX_DCSC_REGS);
>> +
>> +	if (is_composite) {
>> +		/* set CSC coefficients */
>> +		writel(0x107, &de_csc_regs->coef11);
>> +		writel(0x204, &de_csc_regs->coef12);
>> +		writel(0x64, &de_csc_regs->coef13);
>> +		writel(0x4200, &de_csc_regs->coef14);
>> +		writel(0x1f68, &de_csc_regs->coef21);
>> +		writel(0x1ed6, &de_csc_regs->coef22);
>> +		writel(0x1c2, &de_csc_regs->coef23);
>> +		writel(0x20200, &de_csc_regs->coef24);
>> +		writel(0x1c2, &de_csc_regs->coef31);
>> +		writel(0x1e87, &de_csc_regs->coef32);
>> +		writel(0x1fb7, &de_csc_regs->coef33);
>> +		writel(0x20200, &de_csc_regs->coef34);
>> +
>> +		/* enable CSC unit */
>> +		writel(1, &de_csc_regs->csc_ctl);
>> +	} else {
>> +		writel(0, &de_csc_regs->csc_ctl);
>> +	}
> 
> patch 2
> 
>> 
>>  	switch (bpp) {
>>  	case 16:
>> @@ -153,7 +176,7 @@ static void sunxi_de2_mode_set(int mux, const 
>> struct display_timing *mode,
>> 
>>  static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
>>  			  enum video_log2_bpp l2bpp,
>> -			  struct udevice *disp, int mux)
>> +			  struct udevice *disp, int mux, bool is_composite)
>>  {
>>  	struct video_priv *uc_priv = dev_get_uclass_priv(dev);
>>  	struct display_timing timing;
>> @@ -183,7 +206,7 @@ static int sunxi_de2_init(struct udevice *dev, 
>> ulong fbbase,
>>  	}
>> 
>>  	sunxi_de2_composer_init();
>> -	sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase);
>> +	sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase, is_composite);
>> 
>>  	ret = display_enable(disp, 1 << l2bpp, &timing);
>>  	if (ret) {
>> @@ -204,7 +227,6 @@ static int sunxi_de2_probe(struct udevice *dev)
>>  	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
>>  	struct udevice *disp;
>>  	int ret;
>> -	int mux;
>> 
>>  	/* Before relocation we don't need to do anything */
>>  	if (!(gd->flags & GD_FLG_RELOC))
>> @@ -212,17 +234,31 @@ static int sunxi_de2_probe(struct udevice *dev)
>> 
>>  	ret = uclass_find_device_by_name(UCLASS_DISPLAY,
>>  					 "sunxi_dw_hdmi", &disp);
>> +	if (!ret) {
>> +		int mux;
>> +		if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
>> +			mux = 0;
>> +		else
>> +			mux = 1;
>> +
>> +		ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux,
>> +				     false);
>> +		if (!ret) {
>> +			video_set_flush_dcache(dev, 1);
>> +			return 0;
>> +		}
>> +	}
>> +
>> +	debug("%s: hdmi display not found (ret=%d)\n", __func__, ret);
>> +
>> +	ret = uclass_find_device_by_name(UCLASS_DISPLAY,
>> +					"sunxi_tve", &disp);
>>  	if (ret) {
>> -		debug("%s: hdmi display not found (ret=%d)\n", __func__, ret);
>> +		debug("%s: tv not found (ret=%d)\n", __func__, ret);
>>  		return ret;
>>  	}
>> 
>> -	if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
>> -		mux = 0;
>> -	else
>> -		mux = 1;
>> -
>> -	ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux);
>> +	ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, 1, true);
> 
> patch 2
> 
>>  	if (ret)
>>  		return ret;
>> 
>> diff --git a/drivers/video/sunxi/sunxi_tve.c 
>> b/drivers/video/sunxi/sunxi_tve.c
>> new file mode 100644
>> index 0000000000..95f54bbaf7
>> --- /dev/null
>> +++ b/drivers/video/sunxi/sunxi_tve.c
>> @@ -0,0 +1,156 @@
>> +/*
>> + * Allwinner TVE driver
>> + *
>> + * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
>> + *
>> + * SPDX-License-Identifier:	GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <display.h>
>> +#include <dm.h>
>> +#include <asm/io.h>
>> +#include <asm/arch/clock.h>
>> +#include <asm/arch/lcdc.h>
>> +#include <asm/arch/tve.h>
>> +
>> +static int sunxi_tve_get_plug_in_status(void)
>> +{
>> +	struct sunxi_tve_reg * const tve =
>> +		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
>> +	u32 status;
>> +
>> +	status = readl(&tve->auto_detect_status) &
>> +		SUNXI_TVE_AUTO_DETECT_STATUS_MASK(0);
>> +
>> +	return status == SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED;

So TVE is now capable of hpd checking, right?

Is is a feature that exists in A10/A13/A20 or is it new in H3?

>> +}
>> +
>> +static int sunxi_tve_wait_for_hpd(void)
>> +{
>> +	struct sunxi_tve_reg * const tve =
>> +		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
>> +	ulong start;
>> +
>> +	/* enable auto detection */
>> +	writel(SUNXI_TVE_DAC_CFG0_DETECTION, &tve->dac_cfg0);
>> +	writel(SUNXI_TVE_AUTO_DETECT_CFG0, &tve->auto_detect_cfg0);
>> +	writel(SUNXI_TVE_AUTO_DETECT_CFG1, &tve->auto_detect_cfg1);
>> +	writel(9 << SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(0),
>> +	       &tve->auto_detect_debounce);
>> +	writel(SUNXI_TVE_AUTO_DETECT_EN_DET_EN(0), &tve->auto_detect_en);
>> +
>> +	start = get_timer(0);
>> +	do {
>> +		if (sunxi_tve_get_plug_in_status())
>> +			return 0;
>> +		udelay(100);
>> +	} while (get_timer(start) < 300);
>> +
>> +	return -1;
>> +}
>> +
>> +static void sunxi_tve_lcdc_init(const struct display_timing *edid, 
>> int bpp)
>> +{
>> +	struct sunxi_ccm_reg * const ccm =
>> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>> +	struct sunxi_lcdc_reg * const lcdc =
>> +		(struct sunxi_lcdc_reg *)SUNXI_LCD1_BASE;
>> +
>> +	/* Reset off */
>> +	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD1);
>> +
>> +	/* Clock on */
>> +	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD1);
>> +
>> +	lcdc_init(lcdc);
>> +	lcdc_tcon1_mode_set(lcdc, edid, false, true);
>> +	lcdc_enable(lcdc, bpp);
>> +}
>> +
>> +static int sunxi_tve_read_timing(struct udevice *dev,
>> +				 struct display_timing *timing)
>> +{
>> +	/* PAL resolution */
>> +	timing->pixelclock.typ = 27000000;
>> +
>> +	timing->hactive.typ = 720;
>> +	timing->hfront_porch.typ = 5;
>> +	timing->hback_porch.typ = 137;
>> +	timing->hsync_len.typ = 2;
>> +
>> +	timing->vactive.typ = 576;
>> +	timing->vfront_porch.typ = 27;
>> +	timing->vback_porch.typ = 20;
>> +	timing->vsync_len.typ = 2;
>> +
>> +	timing->flags = DISPLAY_FLAGS_INTERLACED;
>> +
>> +	return 0;
>> +}
>> +
>> +static int sunxi_tve_enable(struct udevice *dev, int panel_bpp,
>> +			    const struct display_timing *edid)
>> +{
>> +	struct sunxi_tve_reg * const tve =
>> +		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
>> +
>> +	sunxi_tve_lcdc_init(edid, panel_bpp);
>> +
>> +	tvencoder_mode_set(tve, tve_mode_composite_pal);
>> +	tvencoder_enable(tve);
>> +
>> +	return 0;
>> +}
>> +
>> +static int sunxi_tve_probe(struct udevice *dev)
>> +{
>> +	struct sunxi_ccm_reg * const ccm =
>> +		(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>> +	struct sunxi_tve_reg * const tve =
>> +		(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
>> +	int ret;
>> +
>> +	/* make sure that clock is active */
>> +	clock_set_pll10(432000000);
>> +
>> +	/* Reset off */
>> +	setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TVE);
>> +
>> +	/* Clock on */
>> +	setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE);
>> +	writel(CCM_TVE_CTRL_GATE | CCM_TVE_CTRL_M(2), &ccm->tve_clk_cfg);
>> +
>> +#ifdef CONFIG_MACH_SUN50I_H5
>> +	writel(SUNXI_TVE_CALIBRATION_H5, &tve->calibration);
>> +	writel(SUNXI_TVE_UNKNOWN3_H5, &tve->unknown3);
>> +#else
>> +	writel(SUNXI_TVE_CALIBRATION_H3, &tve->calibration);
>> +#endif
>> +
>> +	ret = sunxi_tve_wait_for_hpd();
>> +	if (ret < 0) {
>> +		debug("tve can not get hpd signal\n");
>> +		return -1;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct dm_display_ops sunxi_tve_ops = {
>> +	.read_timing = sunxi_tve_read_timing,
>> +	.enable = sunxi_tve_enable,
>> +};
>> +
>> +U_BOOT_DRIVER(sunxi_tve) = {
>> +	.name	= "sunxi_tve",
>> +	.id	= UCLASS_DISPLAY,
>> +	.ops	= &sunxi_tve_ops,
>> +	.probe	= sunxi_tve_probe,
>> +};
>> +
>> +#ifdef CONFIG_MACH_SUNXI_H3_H5
>> +U_BOOT_DEVICE(sunxi_tve) = {
>> +	.name = "sunxi_tve"
>> +};
>> +#endif
> 
> patch 3
> 
>> diff --git a/drivers/video/sunxi/tve.c b/drivers/video/sunxi/tve.c
>> index adea78a69a..ef99c111e3 100644
>> --- a/drivers/video/sunxi/tve.c
>> +++ b/drivers/video/sunxi/tve.c
>> @@ -25,8 +25,6 @@ void tvencoder_mode_set(struct sunxi_tve_reg * const 
>> tve, enum tve_mode mode)
>>  		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) |
>> @@ -35,6 +33,10 @@ void tvencoder_mode_set(struct sunxi_tve_reg * 
>> const tve, enum tve_mode mode)
>>  		writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
>>  		writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
>>  		writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
>> +		if (mode == tve_mode_composite_pal)
>> +			writel(SUNXI_TVE_CHROMA_FREQ_PAL, &tve->chroma_freq);
>> +		else
>> +			writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
>>  		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,
> 
> And patch 3 as well.
> 
> Thanks!
> Maxime
> 
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [linux-sunxi] Re: [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-13 15:02     ` [U-Boot] [linux-sunxi] " icenowy at aosc.io
@ 2017-05-13 15:14       ` Chen-Yu Tsai
  2017-05-15  6:31         ` Maxime Ripard
  0 siblings, 1 reply; 20+ messages in thread
From: Chen-Yu Tsai @ 2017-05-13 15:14 UTC (permalink / raw)
  To: u-boot

On Sat, May 13, 2017 at 11:02 PM,  <icenowy@aosc.io> wrote:
> 在 2017-05-13 00:06,Maxime Ripard 写道:
>>
>> Hi Jernej,
>>
>> The patch content looks fine, but there's a few things that would need
>> to be addressed.
>>
>> On Wed, May 10, 2017 at 06:46:30PM +0200, Jernej Skrabec wrote:
>>>
>>> This commit adds support for TV (composite) output.
>>>
>>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>>> ---
>>>
>>>  arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  10 ++
>>>  arch/arm/include/asm/arch-sunxi/display2.h  |  17 +++
>>>  arch/arm/include/asm/arch-sunxi/tve.h       |  17 ++-
>>>  drivers/video/sunxi/Makefile                |   2 +-
>>>  drivers/video/sunxi/sunxi_de2.c             |  60 ++++++++---
>>>  drivers/video/sunxi/sunxi_tve.c             | 156
>>> ++++++++++++++++++++++++++++
>>>  drivers/video/sunxi/tve.c                   |   6 +-
>>
>>
>> The difference between sunxi_tve and tve is not really obvious. What
>> about calling sunxi_tve tve-uclass, or something like that?
>>
>>>  7 files changed, 251 insertions(+), 17 deletions(-)
>>>  create mode 100644 drivers/video/sunxi/sunxi_tve.c
>>>
>>> diff --git a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
>>> b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
>>> index 6aa5e91ada..2419062d45 100644
>>> --- a/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
>>> +++ b/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
>>> @@ -34,7 +34,9 @@
>>>  #define SUNXI_MS_BASE                  0x01c07000
>>>  #define SUNXI_TVD_BASE                 0x01c08000
>>>  #define SUNXI_CSI0_BASE                        0x01c09000
>>> +#ifndef CONFIG_MACH_SUNXI_H3_H5
>>>  #define SUNXI_TVE0_BASE                        0x01c0a000
>>> +#endif
>>
>>
>> This should be part of a seperate patch.
>>
>>>  #define SUNXI_EMAC_BASE                        0x01c0b000
>>>  #define SUNXI_LCD0_BASE                        0x01c0C000
>>>  #define SUNXI_LCD1_BASE                        0x01c0d000
>>> @@ -161,10 +163,18 @@ defined(CONFIG_MACH_SUN50I)
>>>  /* module sram */
>>>  #define SUNXI_SRAM_C_BASE              0x01d00000
>>>
>>> +#ifndef CONFIG_MACH_SUN8I_H3
>>>  #define SUNXI_DE_FE0_BASE              0x01e00000
>>> +#else
>>> +#define SUNXI_TVE0_BASE                        0x01e00000
>>> +#endif
>>
>>
>> This one should be in that other patch
>>
>>>  #define SUNXI_DE_FE1_BASE              0x01e20000
>>>  #define SUNXI_DE_BE0_BASE              0x01e60000
>>> +#ifndef CONFIG_MACH_SUN50I_H5
>>>  #define SUNXI_DE_BE1_BASE              0x01e40000
>>> +#else
>>> +#define SUNXI_TVE0_BASE                        0x01e40000
>>> +#endif
>>
>>
>> And that one too.
>>
>>>  #define SUNXI_MP_BASE                  0x01e80000
>>>  #define SUNXI_AVG_BASE                 0x01ea0000
>>>
>>> diff --git a/arch/arm/include/asm/arch-sunxi/display2.h
>>> b/arch/arm/include/asm/arch-sunxi/display2.h
>>> index b5875f9605..359cacd90b 100644
>>> --- a/arch/arm/include/asm/arch-sunxi/display2.h
>>> +++ b/arch/arm/include/asm/arch-sunxi/display2.h
>>> @@ -90,6 +90,23 @@ struct de_ui {
>>>         u32 ovl_size;
>>>  };
>>>
>>> +struct de_csc {
>>> +       u32 csc_ctl;
>>> +       u8 res[0xc];
>>> +       u32 coef11;
>>> +       u32 coef12;
>>> +       u32 coef13;
>>> +       u32 coef14;
>>> +       u32 coef21;
>>> +       u32 coef22;
>>> +       u32 coef23;
>>> +       u32 coef24;
>>> +       u32 coef31;
>>> +       u32 coef32;
>>> +       u32 coef33;
>>> +       u32 coef34;
>>> +};
>>> +
>>
>>
>> This should be in another patch (let's call it patch 2)
>>
>>>  /*
>>>   * DE register constants.
>>>   */
>>> diff --git a/arch/arm/include/asm/arch-sunxi/tve.h
>>> b/arch/arm/include/asm/arch-sunxi/tve.h
>>> index 41a14a68e4..ff34bbbc12 100644
>>> --- a/arch/arm/include/asm/arch-sunxi/tve.h
>>> +++ b/arch/arm/include/asm/arch-sunxi/tve.h
>>> @@ -45,7 +45,9 @@ struct sunxi_tve_reg {
>>>         u32 csc_reg1;                   /* 0x044 */
>>>         u32 csc_reg2;                   /* 0x048 */
>>>         u32 csc_reg3;                   /* 0x04c */
>>> -       u8 res1[0xb0];                  /* 0x050 */
>>> +       u8 res1[0xa8];                  /* 0x050 */
>>> +       u32 auto_detect_cfg0;           /* 0x0f8 */
>>> +       u32 auto_detect_cfg1;           /* 0x0fc */
>>>         u32 color_burst;                /* 0x100 */
>>>         u32 vsync_num;                  /* 0x104 */
>>>         u32 notch_freq;                 /* 0x108 */
>>> @@ -62,6 +64,10 @@ struct sunxi_tve_reg {
>>>         u32 slave_para;                 /* 0x134 */
>>>         u32 cfg1;                       /* 0x138 */
>>>         u32 cfg2;                       /* 0x13c */
>>> +       u8 res2[0x1c4];                 /* 0x140 */
>>> +       u32 calibration;                /* 0x304 */
>>> +       u8 res3[0x4];                   /* 0x308 */
>>> +       u32 unknown3;                   /* 0x30c */
>>
>>
>> And these yet another one (patch 3)
>>
>>>  };
>>>
>>>  /*
>>> @@ -79,12 +85,14 @@ struct sunxi_tve_reg {
>>>  #define SUNXI_TVE_CFG0_PAL                     0x07030001
>>>  #define SUNXI_TVE_CFG0_NTSC                    0x07030000
>>>  #define SUNXI_TVE_DAC_CFG0_VGA                 0x403e1ac7
>>> -#ifdef CONFIG_MACH_SUN5I
>>> +#if defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUNXI_H3_H5)
>>>  #define SUNXI_TVE_DAC_CFG0_COMPOSITE           0x433f0009
>>>  #else
>>>  #define SUNXI_TVE_DAC_CFG0_COMPOSITE           0x403f0008
>>>  #endif
>>> +#define SUNXI_TVE_DAC_CFG0_DETECTION           0x433f0289
>>>  #define SUNXI_TVE_FILTER_COMPOSITE             0x00000120
>>> +#define SUNXI_TVE_CHROMA_FREQ_PAL              0x2a098acb
>>>  #define SUNXI_TVE_CHROMA_FREQ_PAL_M            0x21e6efe3
>>>  #define SUNXI_TVE_CHROMA_FREQ_PAL_NC           0x21f69446
>>>  #define SUNXI_TVE_PORCH_NUM_PAL                        0x008a0018
>>> @@ -105,6 +113,8 @@ struct sunxi_tve_reg {
>>>  #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_AUTO_DETECT_CFG0             0x00000280
>>> +#define SUNXI_TVE_AUTO_DETECT_CFG1             0x028F00FF
>>>  #define SUNXI_TVE_CSC_REG0_ENABLE              (1 << 31)
>>>  #define SUNXI_TVE_CSC_REG0                     0x08440832
>>>  #define SUNXI_TVE_CSC_REG1                     0x3b6dace1
>>> @@ -124,6 +134,9 @@ struct sunxi_tve_reg {
>>>  #define SUNXI_TVE_RESYNC_NUM_PAL               0x800d000c
>>>  #define SUNXI_TVE_RESYNC_NUM_NTSC              0x000e000c
>>>  #define SUNXI_TVE_SLAVE_PARA_COMPOSITE         0x00000000
>>> +#define SUNXI_TVE_CALIBRATION_H3               0x02000c00
>>> +#define SUNXI_TVE_CALIBRATION_H5               0x02850000
>>> +#define SUNXI_TVE_UNKNOWN3_H5                  0x00101110
>>
>>
>> patch 3
>>
>>>
>>>  void tvencoder_mode_set(struct sunxi_tve_reg * const tve, enum tve_mode
>>> mode);
>>>  void tvencoder_enable(struct sunxi_tve_reg * const tve);
>>> diff --git a/drivers/video/sunxi/Makefile b/drivers/video/sunxi/Makefile
>>> index dbaab61b59..1db82c53f0 100644
>>> --- a/drivers/video/sunxi/Makefile
>>> +++ b/drivers/video/sunxi/Makefile
>>> @@ -6,4 +6,4 @@
>>>  #
>>>
>>>  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
>>> +obj-$(CONFIG_VIDEO_DE2) += sunxi_de2.o sunxi_dw_hdmi.o sunxi_tve.o tve.o
>>> lcdc.o ../dw_hdmi.o
>>> diff --git a/drivers/video/sunxi/sunxi_de2.c
>>> b/drivers/video/sunxi/sunxi_de2.c
>>> index 9a32c3a020..ee67764ac5 100644
>>> --- a/drivers/video/sunxi/sunxi_de2.c
>>> +++ b/drivers/video/sunxi/sunxi_de2.c
>>> @@ -56,7 +56,7 @@ static void sunxi_de2_composer_init(void)
>>>  }
>>>
>>>  static void sunxi_de2_mode_set(int mux, const struct display_timing
>>> *mode,
>>> -                              int bpp, ulong address)
>>> +                              int bpp, ulong address, bool is_composite)
>>>  {
>>>         ulong de_mux_base = (mux == 0) ?
>>>                             SUNXI_DE2_MUX0_BASE : SUNXI_DE2_MUX1_BASE;
>>
>>
>> patch 2
>>
>>> @@ -72,6 +72,9 @@ static void sunxi_de2_mode_set(int mux, const struct
>>> display_timing *mode,
>>>                 (struct de_ui *)(de_mux_base +
>>>                                  SUNXI_DE2_MUX_CHAN_REGS +
>>>                                  SUNXI_DE2_MUX_CHAN_SZ * 1);
>>> +       struct de_csc * const de_csc_regs =
>>> +               (struct de_csc *)(de_mux_base +
>>> +                                 SUNXI_DE2_MUX_DCSC_REGS);
>>
>>
>> patch 2
>>
>>>         u32 size = SUNXI_DE2_WH(mode->hactive.typ, mode->vactive.typ);
>>>         int channel;
>>>         u32 format;
>>> @@ -128,7 +131,27 @@ static void sunxi_de2_mode_set(int mux, const struct
>>> display_timing *mode,
>>>         writel(0, de_mux_base + SUNXI_DE2_MUX_PEAK_REGS);
>>>         writel(0, de_mux_base + SUNXI_DE2_MUX_ASE_REGS);
>>>         writel(0, de_mux_base + SUNXI_DE2_MUX_FCC_REGS);
>>> -       writel(0, de_mux_base + SUNXI_DE2_MUX_DCSC_REGS);
>>> +
>>> +       if (is_composite) {
>>> +               /* set CSC coefficients */
>>> +               writel(0x107, &de_csc_regs->coef11);
>>> +               writel(0x204, &de_csc_regs->coef12);
>>> +               writel(0x64, &de_csc_regs->coef13);
>>> +               writel(0x4200, &de_csc_regs->coef14);
>>> +               writel(0x1f68, &de_csc_regs->coef21);
>>> +               writel(0x1ed6, &de_csc_regs->coef22);
>>> +               writel(0x1c2, &de_csc_regs->coef23);
>>> +               writel(0x20200, &de_csc_regs->coef24);
>>> +               writel(0x1c2, &de_csc_regs->coef31);
>>> +               writel(0x1e87, &de_csc_regs->coef32);
>>> +               writel(0x1fb7, &de_csc_regs->coef33);
>>> +               writel(0x20200, &de_csc_regs->coef34);
>>> +
>>> +               /* enable CSC unit */
>>> +               writel(1, &de_csc_regs->csc_ctl);
>>> +       } else {
>>> +               writel(0, &de_csc_regs->csc_ctl);
>>> +       }
>>
>>
>> patch 2
>>
>>>
>>>         switch (bpp) {
>>>         case 16:
>>> @@ -153,7 +176,7 @@ static void sunxi_de2_mode_set(int mux, const struct
>>> display_timing *mode,
>>>
>>>  static int sunxi_de2_init(struct udevice *dev, ulong fbbase,
>>>                           enum video_log2_bpp l2bpp,
>>> -                         struct udevice *disp, int mux)
>>> +                         struct udevice *disp, int mux, bool
>>> is_composite)
>>>  {
>>>         struct video_priv *uc_priv = dev_get_uclass_priv(dev);
>>>         struct display_timing timing;
>>> @@ -183,7 +206,7 @@ static int sunxi_de2_init(struct udevice *dev, ulong
>>> fbbase,
>>>         }
>>>
>>>         sunxi_de2_composer_init();
>>> -       sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase);
>>> +       sunxi_de2_mode_set(mux, &timing, 1 << l2bpp, fbbase,
>>> is_composite);
>>>
>>>         ret = display_enable(disp, 1 << l2bpp, &timing);
>>>         if (ret) {
>>> @@ -204,7 +227,6 @@ static int sunxi_de2_probe(struct udevice *dev)
>>>         struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
>>>         struct udevice *disp;
>>>         int ret;
>>> -       int mux;
>>>
>>>         /* Before relocation we don't need to do anything */
>>>         if (!(gd->flags & GD_FLG_RELOC))
>>> @@ -212,17 +234,31 @@ static int sunxi_de2_probe(struct udevice *dev)
>>>
>>>         ret = uclass_find_device_by_name(UCLASS_DISPLAY,
>>>                                          "sunxi_dw_hdmi", &disp);
>>> +       if (!ret) {
>>> +               int mux;
>>> +               if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
>>> +                       mux = 0;
>>> +               else
>>> +                       mux = 1;
>>> +
>>> +               ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp,
>>> mux,
>>> +                                    false);
>>> +               if (!ret) {
>>> +                       video_set_flush_dcache(dev, 1);
>>> +                       return 0;
>>> +               }
>>> +       }
>>> +
>>> +       debug("%s: hdmi display not found (ret=%d)\n", __func__, ret);
>>> +
>>> +       ret = uclass_find_device_by_name(UCLASS_DISPLAY,
>>> +                                       "sunxi_tve", &disp);
>>>         if (ret) {
>>> -               debug("%s: hdmi display not found (ret=%d)\n", __func__,
>>> ret);
>>> +               debug("%s: tv not found (ret=%d)\n", __func__, ret);
>>>                 return ret;
>>>         }
>>>
>>> -       if (IS_ENABLED(CONFIG_MACH_SUNXI_H3_H5))
>>> -               mux = 0;
>>> -       else
>>> -               mux = 1;
>>> -
>>> -       ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, mux);
>>> +       ret = sunxi_de2_init(dev, plat->base, VIDEO_BPP32, disp, 1,
>>> true);
>>
>>
>> patch 2
>>
>>>         if (ret)
>>>                 return ret;
>>>
>>> diff --git a/drivers/video/sunxi/sunxi_tve.c
>>> b/drivers/video/sunxi/sunxi_tve.c
>>> new file mode 100644
>>> index 0000000000..95f54bbaf7
>>> --- /dev/null
>>> +++ b/drivers/video/sunxi/sunxi_tve.c
>>> @@ -0,0 +1,156 @@
>>> +/*
>>> + * Allwinner TVE driver
>>> + *
>>> + * (C) Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
>>> + *
>>> + * SPDX-License-Identifier:    GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <display.h>
>>> +#include <dm.h>
>>> +#include <asm/io.h>
>>> +#include <asm/arch/clock.h>
>>> +#include <asm/arch/lcdc.h>
>>> +#include <asm/arch/tve.h>
>>> +
>>> +static int sunxi_tve_get_plug_in_status(void)
>>> +{
>>> +       struct sunxi_tve_reg * const tve =
>>> +               (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
>>> +       u32 status;
>>> +
>>> +       status = readl(&tve->auto_detect_status) &
>>> +               SUNXI_TVE_AUTO_DETECT_STATUS_MASK(0);
>>> +
>>> +       return status == SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED;
>
>
> So TVE is now capable of hpd checking, right?
>
> Is is a feature that exists in A10/A13/A20 or is it new in H3?

AFAIK this is also available in the earlier SoCs.
Maxime mentioned that it was unreliable though.

ChenYu

>
>>> +}
>>> +
>>> +static int sunxi_tve_wait_for_hpd(void)
>>> +{
>>> +       struct sunxi_tve_reg * const tve =
>>> +               (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
>>> +       ulong start;
>>> +
>>> +       /* enable auto detection */
>>> +       writel(SUNXI_TVE_DAC_CFG0_DETECTION, &tve->dac_cfg0);
>>> +       writel(SUNXI_TVE_AUTO_DETECT_CFG0, &tve->auto_detect_cfg0);
>>> +       writel(SUNXI_TVE_AUTO_DETECT_CFG1, &tve->auto_detect_cfg1);
>>> +       writel(9 << SUNXI_TVE_AUTO_DETECT_DEBOUNCE_SHIFT(0),
>>> +              &tve->auto_detect_debounce);
>>> +       writel(SUNXI_TVE_AUTO_DETECT_EN_DET_EN(0), &tve->auto_detect_en);
>>> +
>>> +       start = get_timer(0);
>>> +       do {
>>> +               if (sunxi_tve_get_plug_in_status())
>>> +                       return 0;
>>> +               udelay(100);
>>> +       } while (get_timer(start) < 300);
>>> +
>>> +       return -1;
>>> +}
>>> +
>>> +static void sunxi_tve_lcdc_init(const struct display_timing *edid, int
>>> bpp)
>>> +{
>>> +       struct sunxi_ccm_reg * const ccm =
>>> +               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>>> +       struct sunxi_lcdc_reg * const lcdc =
>>> +               (struct sunxi_lcdc_reg *)SUNXI_LCD1_BASE;
>>> +
>>> +       /* Reset off */
>>> +       setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD1);
>>> +
>>> +       /* Clock on */
>>> +       setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_LCD1);
>>> +
>>> +       lcdc_init(lcdc);
>>> +       lcdc_tcon1_mode_set(lcdc, edid, false, true);
>>> +       lcdc_enable(lcdc, bpp);
>>> +}
>>> +
>>> +static int sunxi_tve_read_timing(struct udevice *dev,
>>> +                                struct display_timing *timing)
>>> +{
>>> +       /* PAL resolution */
>>> +       timing->pixelclock.typ = 27000000;
>>> +
>>> +       timing->hactive.typ = 720;
>>> +       timing->hfront_porch.typ = 5;
>>> +       timing->hback_porch.typ = 137;
>>> +       timing->hsync_len.typ = 2;
>>> +
>>> +       timing->vactive.typ = 576;
>>> +       timing->vfront_porch.typ = 27;
>>> +       timing->vback_porch.typ = 20;
>>> +       timing->vsync_len.typ = 2;
>>> +
>>> +       timing->flags = DISPLAY_FLAGS_INTERLACED;
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int sunxi_tve_enable(struct udevice *dev, int panel_bpp,
>>> +                           const struct display_timing *edid)
>>> +{
>>> +       struct sunxi_tve_reg * const tve =
>>> +               (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
>>> +
>>> +       sunxi_tve_lcdc_init(edid, panel_bpp);
>>> +
>>> +       tvencoder_mode_set(tve, tve_mode_composite_pal);
>>> +       tvencoder_enable(tve);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int sunxi_tve_probe(struct udevice *dev)
>>> +{
>>> +       struct sunxi_ccm_reg * const ccm =
>>> +               (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
>>> +       struct sunxi_tve_reg * const tve =
>>> +               (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
>>> +       int ret;
>>> +
>>> +       /* make sure that clock is active */
>>> +       clock_set_pll10(432000000);
>>> +
>>> +       /* Reset off */
>>> +       setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TVE);
>>> +
>>> +       /* Clock on */
>>> +       setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE);
>>> +       writel(CCM_TVE_CTRL_GATE | CCM_TVE_CTRL_M(2), &ccm->tve_clk_cfg);
>>> +
>>> +#ifdef CONFIG_MACH_SUN50I_H5
>>> +       writel(SUNXI_TVE_CALIBRATION_H5, &tve->calibration);
>>> +       writel(SUNXI_TVE_UNKNOWN3_H5, &tve->unknown3);
>>> +#else
>>> +       writel(SUNXI_TVE_CALIBRATION_H3, &tve->calibration);
>>> +#endif
>>> +
>>> +       ret = sunxi_tve_wait_for_hpd();
>>> +       if (ret < 0) {
>>> +               debug("tve can not get hpd signal\n");
>>> +               return -1;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static const struct dm_display_ops sunxi_tve_ops = {
>>> +       .read_timing = sunxi_tve_read_timing,
>>> +       .enable = sunxi_tve_enable,
>>> +};
>>> +
>>> +U_BOOT_DRIVER(sunxi_tve) = {
>>> +       .name   = "sunxi_tve",
>>> +       .id     = UCLASS_DISPLAY,
>>> +       .ops    = &sunxi_tve_ops,
>>> +       .probe  = sunxi_tve_probe,
>>> +};
>>> +
>>> +#ifdef CONFIG_MACH_SUNXI_H3_H5
>>> +U_BOOT_DEVICE(sunxi_tve) = {
>>> +       .name = "sunxi_tve"
>>> +};
>>> +#endif
>>
>>
>> patch 3
>>
>>> diff --git a/drivers/video/sunxi/tve.c b/drivers/video/sunxi/tve.c
>>> index adea78a69a..ef99c111e3 100644
>>> --- a/drivers/video/sunxi/tve.c
>>> +++ b/drivers/video/sunxi/tve.c
>>> @@ -25,8 +25,6 @@ void tvencoder_mode_set(struct sunxi_tve_reg * const
>>> tve, enum tve_mode mode)
>>>                 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) |
>>> @@ -35,6 +33,10 @@ void tvencoder_mode_set(struct sunxi_tve_reg * const
>>> tve, enum tve_mode mode)
>>>                 writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
>>>                 writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
>>>                 writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
>>> +               if (mode == tve_mode_composite_pal)
>>> +                       writel(SUNXI_TVE_CHROMA_FREQ_PAL,
>>> &tve->chroma_freq);
>>> +               else
>>> +                       writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC,
>>> &tve->chroma_freq);
>>>                 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,
>>
>>
>> And patch 3 as well.
>>
>> Thanks!
>> Maxime
>>
>> --
>> Maxime Ripard, Free Electrons
>> Embedded Linux and Kernel engineering
>> http://free-electrons.com
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to linux-sunxi+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code
  2017-05-10 16:46 ` [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code Jernej Skrabec
@ 2017-05-15  3:03   ` Simon Glass
  2017-05-15 19:08   ` Anatolij Gustschin
  1 sibling, 0 replies; 20+ messages in thread
From: Simon Glass @ 2017-05-15  3:03 UTC (permalink / raw)
  To: u-boot

On 10 May 2017 at 10:46, Jernej Skrabec <jernej.skrabec@siol.net> wrote:
> 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>
> ---
>
>  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

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-12 16:06   ` Maxime Ripard
  2017-05-13 15:02     ` [U-Boot] [linux-sunxi] " icenowy at aosc.io
@ 2017-05-15  3:03     ` Simon Glass
  2017-05-15  6:11       ` Maxime Ripard
  1 sibling, 1 reply; 20+ messages in thread
From: Simon Glass @ 2017-05-15  3:03 UTC (permalink / raw)
  To: u-boot

Hi,

On 12 May 2017 at 10:06, Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> Hi Jernej,
>
> The patch content looks fine, but there's a few things that would need
> to be addressed.
>
> On Wed, May 10, 2017 at 06:46:30PM +0200, Jernej Skrabec wrote:
>> This commit adds support for TV (composite) output.
>>
>> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>> ---
>>
>>  arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  10 ++
>>  arch/arm/include/asm/arch-sunxi/display2.h  |  17 +++
>>  arch/arm/include/asm/arch-sunxi/tve.h       |  17 ++-
>>  drivers/video/sunxi/Makefile                |   2 +-
>>  drivers/video/sunxi/sunxi_de2.c             |  60 ++++++++---
>>  drivers/video/sunxi/sunxi_tve.c             | 156 ++++++++++++++++++++++++++++
>>  drivers/video/sunxi/tve.c                   |   6 +-
>
> The difference between sunxi_tve and tve is not really obvious. What
> about calling sunxi_tve tve-uclass, or something like that?

That name is reserved for actual uclasses.

Regards,
Simon

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-15  3:03     ` [U-Boot] " Simon Glass
@ 2017-05-15  6:11       ` Maxime Ripard
  2017-05-15 19:47         ` Jernej Škrabec
  2017-05-15 20:05         ` Simon Glass
  0 siblings, 2 replies; 20+ messages in thread
From: Maxime Ripard @ 2017-05-15  6:11 UTC (permalink / raw)
  To: u-boot

On Sun, May 14, 2017 at 09:03:19PM -0600, Simon Glass wrote:
> Hi,
> 
> On 12 May 2017 at 10:06, Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> > Hi Jernej,
> >
> > The patch content looks fine, but there's a few things that would need
> > to be addressed.
> >
> > On Wed, May 10, 2017 at 06:46:30PM +0200, Jernej Skrabec wrote:
> >> This commit adds support for TV (composite) output.
> >>
> >> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> >> ---
> >>
> >>  arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  10 ++
> >>  arch/arm/include/asm/arch-sunxi/display2.h  |  17 +++
> >>  arch/arm/include/asm/arch-sunxi/tve.h       |  17 ++-
> >>  drivers/video/sunxi/Makefile                |   2 +-
> >>  drivers/video/sunxi/sunxi_de2.c             |  60 ++++++++---
> >>  drivers/video/sunxi/sunxi_tve.c             | 156 ++++++++++++++++++++++++++++
> >>  drivers/video/sunxi/tve.c                   |   6 +-
> >
> > The difference between sunxi_tve and tve is not really obvious. What
> > about calling sunxi_tve tve-uclass, or something like that?
> 
> That name is reserved for actual uclasses.

Ok. How are the driver-part usually called?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170515/600c1f73/attachment.sig>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [linux-sunxi] Re: [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-13 15:14       ` Chen-Yu Tsai
@ 2017-05-15  6:31         ` Maxime Ripard
  2017-05-15 20:10           ` Jernej Škrabec
  0 siblings, 1 reply; 20+ messages in thread
From: Maxime Ripard @ 2017-05-15  6:31 UTC (permalink / raw)
  To: u-boot

On Sat, May 13, 2017 at 11:14:00PM +0800, Chen-Yu Tsai wrote:
> >>> +static int sunxi_tve_get_plug_in_status(void)
> >>> +{
> >>> +       struct sunxi_tve_reg * const tve =
> >>> +               (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
> >>> +       u32 status;
> >>> +
> >>> +       status = readl(&tve->auto_detect_status) &
> >>> +               SUNXI_TVE_AUTO_DETECT_STATUS_MASK(0);
> >>> +
> >>> +       return status == SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED;
> >
> >
> > So TVE is now capable of hpd checking, right?
> >
> > Is is a feature that exists in A10/A13/A20 or is it new in H3?
> 
> AFAIK this is also available in the earlier SoCs.
> Maxime mentioned that it was unreliable though.

This was supposed to be there, but those registers were
undocumented. It would be nice to try to see if it works.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170515/a6e61b57/attachment.sig>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code
  2017-05-10 16:46 ` [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code Jernej Skrabec
  2017-05-15  3:03   ` Simon Glass
@ 2017-05-15 19:08   ` Anatolij Gustschin
  1 sibling, 0 replies; 20+ messages in thread
From: Anatolij Gustschin @ 2017-05-15 19:08 UTC (permalink / raw)
  To: u-boot

On Wed, 10 May 2017 18:46:28 +0200
Jernej Skrabec jernej.skrabec at siol.net wrote:

> 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>
> ---
> 
>  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

applied to u-boot-video/master, thanks!

--
Anatolij

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder
  2017-05-10 16:46 ` [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder Jernej Skrabec
  2017-05-12 15:47   ` Maxime Ripard
@ 2017-05-15 19:25   ` Anatolij Gustschin
  1 sibling, 0 replies; 20+ messages in thread
From: Anatolij Gustschin @ 2017-05-15 19:25 UTC (permalink / raw)
  To: u-boot

On Wed, 10 May 2017 18:46:29 +0200
Jernej Skrabec jernej.skrabec at siol.net wrote:

> This patch adds support for TV encoder clocks which will be used later.
> 
> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> ---
> 
>  arch/arm/include/asm/arch-sunxi/clock_sun6i.h | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)

applied to u-boot-video/master, with comment extended as discussed.
Thanks!

--
Anatolij

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-15  6:11       ` Maxime Ripard
@ 2017-05-15 19:47         ` Jernej Škrabec
  2017-05-15 20:00           ` Anatolij Gustschin
  2017-05-15 20:05         ` Simon Glass
  1 sibling, 1 reply; 20+ messages in thread
From: Jernej Škrabec @ 2017-05-15 19:47 UTC (permalink / raw)
  To: u-boot

Hi,

Dne ponedeljek, 15. maj 2017 ob 08:11:55 CEST je Maxime Ripard napisal(a):
> On Sun, May 14, 2017 at 09:03:19PM -0600, Simon Glass wrote:
> > Hi,
> > 
> > On 12 May 2017 at 10:06, Maxime Ripard <maxime.ripard@free-electrons.com> 
wrote:
> > > Hi Jernej,
> > > 
> > > The patch content looks fine, but there's a few things that would need
> > > to be addressed.
> > > 
> > > On Wed, May 10, 2017 at 06:46:30PM +0200, Jernej Skrabec wrote:
> > >> This commit adds support for TV (composite) output.
> > >> 
> > >> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
> > >> ---
> > >> 
> > >>  arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  10 ++
> > >>  arch/arm/include/asm/arch-sunxi/display2.h  |  17 +++
> > >>  arch/arm/include/asm/arch-sunxi/tve.h       |  17 ++-
> > >>  drivers/video/sunxi/Makefile                |   2 +-
> > >>  drivers/video/sunxi/sunxi_de2.c             |  60 ++++++++---
> > >>  drivers/video/sunxi/sunxi_tve.c             | 156
> > >>  ++++++++++++++++++++++++++++ drivers/video/sunxi/tve.c               
> > >>     |   6 +-
> > > 
> > > The difference between sunxi_tve and tve is not really obvious. What
> > > about calling sunxi_tve tve-uclass, or something like that?
> > 
> > That name is reserved for actual uclasses.
> 
> Ok. How are the driver-part usually called?

I wanted to suggest that common part should be renamed to tve_common.c, but 
Anatolij already merged the patch.

Best regards,
Jernej

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-15 19:47         ` Jernej Škrabec
@ 2017-05-15 20:00           ` Anatolij Gustschin
  0 siblings, 0 replies; 20+ messages in thread
From: Anatolij Gustschin @ 2017-05-15 20:00 UTC (permalink / raw)
  To: u-boot

Hi,

On Mon, 15 May 2017 21:47:57 +0200
Jernej Å krabec jernej.skrabec at siol.net wrote:
...
> > > >>  ++++++++++++++++++++++++++++ drivers/video/sunxi/tve.c               
> > > >>     |   6 +-  
> > > > 
> > > > The difference between sunxi_tve and tve is not really obvious. What
> > > > about calling sunxi_tve tve-uclass, or something like that?  
> > > 
> > > That name is reserved for actual uclasses.  
> > 
> > Ok. How are the driver-part usually called?  
> 
> I wanted to suggest that common part should be renamed to tve_common.c, but 
> Anatolij already merged the patch.

I'm ok with renaming it to tve_common.c. If no one has any
objections, please send a renaming patch and base the rework
of patch 3/3 on it. Thanks!

--
Anatolij

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-15  6:11       ` Maxime Ripard
  2017-05-15 19:47         ` Jernej Škrabec
@ 2017-05-15 20:05         ` Simon Glass
  1 sibling, 0 replies; 20+ messages in thread
From: Simon Glass @ 2017-05-15 20:05 UTC (permalink / raw)
  To: u-boot

Hi Maxime,

On 15 May 2017 at 00:11, Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> On Sun, May 14, 2017 at 09:03:19PM -0600, Simon Glass wrote:
>> Hi,
>>
>> On 12 May 2017 at 10:06, Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
>> > Hi Jernej,
>> >
>> > The patch content looks fine, but there's a few things that would need
>> > to be addressed.
>> >
>> > On Wed, May 10, 2017 at 06:46:30PM +0200, Jernej Skrabec wrote:
>> >> This commit adds support for TV (composite) output.
>> >>
>> >> Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
>> >> ---
>> >>
>> >>  arch/arm/include/asm/arch-sunxi/cpu_sun4i.h |  10 ++
>> >>  arch/arm/include/asm/arch-sunxi/display2.h  |  17 +++
>> >>  arch/arm/include/asm/arch-sunxi/tve.h       |  17 ++-
>> >>  drivers/video/sunxi/Makefile                |   2 +-
>> >>  drivers/video/sunxi/sunxi_de2.c             |  60 ++++++++---
>> >>  drivers/video/sunxi/sunxi_tve.c             | 156 ++++++++++++++++++++++++++++
>> >>  drivers/video/sunxi/tve.c                   |   6 +-
>> >
>> > The difference between sunxi_tve and tve is not really obvious. What
>> > about calling sunxi_tve tve-uclass, or something like that?
>>
>> That name is reserved for actual uclasses.
>
> Ok. How are the driver-part usually called?

Well, something without the word 'uclass', and ideally using
underscores instead of hyphens.

Regards,
Simon

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [U-Boot] [linux-sunxi] Re: [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver
  2017-05-15  6:31         ` Maxime Ripard
@ 2017-05-15 20:10           ` Jernej Škrabec
  0 siblings, 0 replies; 20+ messages in thread
From: Jernej Škrabec @ 2017-05-15 20:10 UTC (permalink / raw)
  To: u-boot

Hi,

Dne ponedeljek, 15. maj 2017 ob 08:31:22 CEST je Maxime Ripard napisal(a):
> On Sat, May 13, 2017 at 11:14:00PM +0800, Chen-Yu Tsai wrote:
> > >>> +static int sunxi_tve_get_plug_in_status(void)
> > >>> +{
> > >>> +       struct sunxi_tve_reg * const tve =
> > >>> +               (struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
> > >>> +       u32 status;
> > >>> +
> > >>> +       status = readl(&tve->auto_detect_status) &
> > >>> +               SUNXI_TVE_AUTO_DETECT_STATUS_MASK(0);
> > >>> +
> > >>> +       return status == SUNXI_TVE_AUTO_DETECT_STATUS_CONNECTED;
> > > 
> > > So TVE is now capable of hpd checking, right?
> > > 
> > > Is is a feature that exists in A10/A13/A20 or is it new in H3?
> > 
> > AFAIK this is also available in the earlier SoCs.
> > Maxime mentioned that it was unreliable though.
> 
> This was supposed to be there, but those registers were
> undocumented. It would be nice to try to see if it works.

AFAIK, H3 and newer SoCs with TV out have two additional registers for hot 
plug detection. Here are named SUNXI_TVE_AUTO_DETECT_CFG0 and 
SUNXI_TVE_AUTO_DETECT_CFG1 and they are somewhat explained in R40 manual.

I'm not sure if this changes reliability a lot or not.

Best regards,
Jernej

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2017-05-15 20:10 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-10 16:46 [U-Boot] [PATCH 0/3] sunxi: video: Add support for TV (composite) output on H3/H5 Jernej Skrabec
2017-05-10 16:46 ` [U-Boot] [PATCH 1/3] sunxi: video: Split out TVE code Jernej Skrabec
2017-05-15  3:03   ` Simon Glass
2017-05-15 19:08   ` Anatolij Gustschin
2017-05-10 16:46 ` [U-Boot] [PATCH 2/3] sunxi: Add clock support for TV encoder Jernej Skrabec
2017-05-12 15:47   ` Maxime Ripard
2017-05-12 16:55     ` Jernej Škrabec
2017-05-12 20:27       ` Maxime Ripard
2017-05-15 19:25   ` Anatolij Gustschin
2017-05-10 16:46 ` [U-Boot] [PATCH 3/3] sunxi: video: Add H3/H5 TV out driver Jernej Skrabec
2017-05-12 16:06   ` Maxime Ripard
2017-05-13 15:02     ` [U-Boot] [linux-sunxi] " icenowy at aosc.io
2017-05-13 15:14       ` Chen-Yu Tsai
2017-05-15  6:31         ` Maxime Ripard
2017-05-15 20:10           ` Jernej Škrabec
2017-05-15  3:03     ` [U-Boot] " Simon Glass
2017-05-15  6:11       ` Maxime Ripard
2017-05-15 19:47         ` Jernej Škrabec
2017-05-15 20:00           ` Anatolij Gustschin
2017-05-15 20:05         ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.