* [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 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 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 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 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 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] [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-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 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] [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] [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] [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
* [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] [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
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 a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox