* [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.