[U-Boot] [PATCH 0/4] sunxi: video: native vga support

Hi Ian,
Here is my last sunxi-video patch series, this time adding support for the native vga out found on the A10 / A20 SoCs, and used e.g. on the Cubietruck.
With this patch series by default (can be overridden through video-mode env.) the display will fallback to 1024x768 over VGA when no HDMI cable is plugged in on boards with a VGA connector. This way people using VGA can at least see something, which makes it a lot easier to set the env. when not using a serial console.
Regards,
Hans

It turns out that the problems I was seeing were due to a bad powersupply, so enable proper negative hsync / vsync support.
Also adjust various defconfigs to keep the hsync and vsync for the lcd panels positive, changing sync:0 into sync:3.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- arch/arm/include/asm/arch-sunxi/display.h | 2 ++ configs/A10s-OLinuXino-M-lcd7_defconfig | 2 +- configs/A13-OLinuXinoM_defconfig | 2 +- configs/A13-OLinuXino_defconfig | 2 +- configs/A20-OLinuXino_MICRO-lcd7_defconfig | 2 +- configs/Ippo_q8h_v1_2_defconfig | 2 +- configs/Ippo_q8h_v5_defconfig | 2 +- drivers/video/sunxi_display.c | 15 ++++++++------- 8 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h index dcb2fe4..908c5d9 100644 --- a/arch/arm/include/asm/arch-sunxi/display.h +++ b/arch/arm/include/asm/arch-sunxi/display.h @@ -174,6 +174,8 @@ struct sunxi_hdmi_reg { */ #define SUNXI_LCDC_X(x) (((x) - 1) << 16) #define SUNXI_LCDC_Y(y) (((y) - 1) << 0) +#define SUNXI_LCDC_TCON_VSYNC_MASK (1 << 24) +#define SUNXI_LCDC_TCON_HSYNC_MASK (1 << 25) #define SUNXI_LCDC_CTRL_IO_MAP_MASK (1 << 0) #define SUNXI_LCDC_CTRL_IO_MAP_TCON0 (0 << 0) #define SUNXI_LCDC_CTRL_IO_MAP_TCON1 (1 << 0) diff --git a/configs/A10s-OLinuXino-M-lcd7_defconfig b/configs/A10s-OLinuXino-M-lcd7_defconfig index eafa974..cbaa04d 100644 --- a/configs/A10s-OLinuXino-M-lcd7_defconfig +++ b/configs/A10s-OLinuXino-M-lcd7_defconfig @@ -3,7 +3,7 @@ CONFIG_SYS_EXTRA_OPTIONS="AXP152_POWER,SUNXI_EMAC,USB_EHCI" CONFIG_FDTFILE="sun5i-a10s-olinuxino-micro.dtb" CONFIG_MMC_SUNXI_SLOT_EXTRA=1 CONFIG_USB1_VBUS_PIN="PB10" -CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:0,vmode:0" +CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_POWER="PB9" CONFIG_VIDEO_LCD_BL_PWM="PB2" +S:CONFIG_MMC0_CD_PIN="PG1" diff --git a/configs/A13-OLinuXinoM_defconfig b/configs/A13-OLinuXinoM_defconfig index 7790460..1a99418 100644 --- a/configs/A13-OLinuXinoM_defconfig +++ b/configs/A13-OLinuXinoM_defconfig @@ -6,7 +6,7 @@ CONFIG_VIDEO_HDMI=n CONFIG_VIDEO_VGA_VIA_LCD=y # For use with the Olimex 7" LCD module, adjust timings for other displays # Set video-mode=sunxi:800x600-24@60,monitor=lcd in the env. to enable -CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:0,vmode:0" +CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_POWER="PB10" CONFIG_VIDEO_LCD_BL_PWM="PB2" +S:CONFIG_ARM=y diff --git a/configs/A13-OLinuXino_defconfig b/configs/A13-OLinuXino_defconfig index 944f2e5..7df6951 100644 --- a/configs/A13-OLinuXino_defconfig +++ b/configs/A13-OLinuXino_defconfig @@ -6,7 +6,7 @@ CONFIG_VIDEO_HDMI=n CONFIG_VIDEO_VGA_VIA_LCD=y # For use with the Olimex 7" LCD module, adjust timings for other displays # Set video-mode=sunxi:800x600-24@60,monitor=lcd in the env. to enable -CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:0,vmode:0" +CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_POWER="AXP0-0" CONFIG_VIDEO_LCD_BL_PWM="PB2" +S:CONFIG_ARM=y diff --git a/configs/A20-OLinuXino_MICRO-lcd7_defconfig b/configs/A20-OLinuXino_MICRO-lcd7_defconfig index 05674d7..71afbff 100644 --- a/configs/A20-OLinuXino_MICRO-lcd7_defconfig +++ b/configs/A20-OLinuXino_MICRO-lcd7_defconfig @@ -2,7 +2,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8),USB_EHCI" CONFIG_FDTFILE="sun7i-a20-olinuxino-micro.dtb" CONFIG_MMC_SUNXI_SLOT_EXTRA=3 -CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:0,vmode:0" +CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:16,ri:209,up:22,lo:22,hs:30,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_POWER="PH8" CONFIG_VIDEO_LCD_BL_PWM="PB2" +S:CONFIG_MMC0_CD_PIN="PH1" diff --git a/configs/Ippo_q8h_v1_2_defconfig b/configs/Ippo_q8h_v1_2_defconfig index b1d07c5..0447b06 100644 --- a/configs/Ippo_q8h_v1_2_defconfig +++ b/configs/Ippo_q8h_v1_2_defconfig @@ -1,7 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5" CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v1.2.dtb" -CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:167,up:31,lo:13,hs:1,vs:1,sync:0,vmode:0" +CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:167,up:31,lo:13,hs:1,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_POWER="PH7" CONFIG_VIDEO_LCD_BL_EN="PH6" CONFIG_VIDEO_LCD_BL_PWM="PH0" diff --git a/configs/Ippo_q8h_v5_defconfig b/configs/Ippo_q8h_v5_defconfig index f3dadca..4e82bf9 100644 --- a/configs/Ippo_q8h_v5_defconfig +++ b/configs/Ippo_q8h_v5_defconfig @@ -1,7 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=5" CONFIG_FDTFILE="sun8i-a23-ippo-q8h-v5.dtb" -CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:168,up:31,lo:13,hs:1,vs:1,sync:0,vmode:0" +CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:18,pclk_khz:33000,le:87,ri:168,up:31,lo:13,hs:1,vs:1,sync:3,vmode:0" CONFIG_VIDEO_LCD_POWER="PH7" CONFIG_VIDEO_LCD_BL_EN="PH6" CONFIG_VIDEO_LCD_BL_PWM="PH0" diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index a20ff57..669c46c 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -506,7 +506,7 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode) { struct sunxi_lcdc_reg * const lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; - int bp, clk_delay, clk_div, clk_double, pin, total; + int bp, clk_delay, clk_div, clk_double, pin, total, val;
for (pin = SUNXI_GPD(0); pin <= SUNXI_GPD(27); pin++) sunxi_gpio_set_cfgpin(pin, SUNXI_GPD0_LCD0); @@ -561,12 +561,13 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode) &lcdc->frame_ctrl[0]); }
- /* - * Bit 24 and 25 of tcon0_io_polarity can be used to invert hsync / - * vsync polarity, but this leads to noise problems, so we always - * keep the polarity positive. - */ - writel(0, &lcdc->tcon0_io_polarity); + val = 0; + if (!(mode->sync & FB_SYNC_HOR_HIGH_ACT)) + val |= SUNXI_LCDC_TCON_HSYNC_MASK; + if (!(mode->sync & FB_SYNC_VERT_HIGH_ACT)) + val |= SUNXI_LCDC_TCON_VSYNC_MASK; + writel(val, &lcdc->tcon0_io_polarity); + writel(0, &lcdc->tcon0_io_tristate); }

On Sat, 2014-12-27 at 16:53 +0100, Hans de Goede wrote:
It turns out that the problems I was seeing were due to a bad powersupply, so enable proper negative hsync / vsync support.
Also adjust various defconfigs to keep the hsync and vsync for the lcd panels positive, changing sync:0 into sync:3.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk

Add support for using PORTD hsync/vsync pins with tcon1, this is a preparation patch for adding native VGA support.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- drivers/video/sunxi_display.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index 669c46c..0dd5aa1 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -574,11 +574,12 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode) #ifdef CONFIG_VIDEO_HDMI
static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, - int *clk_div, int *clk_double) + int *clk_div, int *clk_double, + bool use_portd_hvsync) { struct sunxi_lcdc_reg * const lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; - int bp, clk_delay, total; + int bp, clk_delay, total, val;
/* Use tcon1 */ clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK, @@ -608,6 +609,21 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len), &lcdc->tcon1_timing_sync);
+ if (use_portd_hvsync) { + sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD0_LCD0); + sunxi_gpio_set_cfgpin(SUNXI_GPD(27), SUNXI_GPD0_LCD0); + + val = 0; + if (mode->sync & FB_SYNC_HOR_HIGH_ACT) + val |= SUNXI_LCDC_TCON_HSYNC_MASK; + if (mode->sync & FB_SYNC_VERT_HIGH_ACT) + val |= SUNXI_LCDC_TCON_VSYNC_MASK; + writel(val, &lcdc->tcon1_io_polarity); + + clrbits_le32(&lcdc->tcon1_io_tristate, + SUNXI_LCDC_TCON_VSYNC_MASK | + SUNXI_LCDC_TCON_HSYNC_MASK); + } sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double); }
@@ -751,7 +767,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, #ifdef CONFIG_VIDEO_HDMI int clk_div, clk_double; sunxi_composer_mode_set(mode, address); - sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double); + sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0); sunxi_hdmi_mode_set(mode, clk_div, clk_double); sunxi_composer_enable(); sunxi_lcdc_enable();

On Sat, 2014-12-27 at 16:53 +0100, Hans de Goede wrote:
Add support for using PORTD hsync/vsync pins with tcon1, this is a preparation patch for adding native VGA support.
Signed-off-by: Hans de Goede hdegoede@redhat.com
Acked-by: Ian Campbell ijc@hellion.org.uk

If a board has no LCD, but does have VGA fallback to VGA when no HDMI cable is connected (unless hpd=0).
Signed-off-by: Hans de Goede hdegoede@redhat.com --- doc/README.video | 3 +-- drivers/video/sunxi_display.c | 47 ++++++++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 23 deletions(-)
diff --git a/doc/README.video b/doc/README.video index cfe6318..2c55d6a 100644 --- a/doc/README.video +++ b/doc/README.video @@ -50,8 +50,7 @@ The sunxi u-boot driver supports the following video-mode options:
- hpd=[0|1] - Enable use of the hdmi HotPlug Detect feature 0: Disabled. Configure dvi/hdmi output even if no cable is detected - 1: Enabled. If a LCD has been configured fallback to the LCD when no cable is - detected, if no LCD is configured, disable video ouput. + 1: Enabled. Fallback to the lcd / vga / none in that order (if available) Defaults to hpd=1.
- edid=[0|1] - Enable use of DDC + EDID to get monitor info diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index 0dd5aa1..c462203 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -837,6 +837,32 @@ void *video_hw_init(void) printf("Unknown monitor: '%s', falling back to '%s'\n", mon, mon_desc[sunxi_display.monitor]);
+#ifdef CONFIG_VIDEO_HDMI + /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */ + if (sunxi_display.monitor == sunxi_monitor_dvi || + sunxi_display.monitor == sunxi_monitor_hdmi) { + /* Always call hdp_detect, as it also enables clocks, etc. */ + ret = sunxi_hdmi_hpd_detect(); + if (ret) { + printf("HDMI connected: "); + if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0) + mode = &custom; + } else if (hpd) { + sunxi_hdmi_shutdown(); + /* Fallback to lcd / vga / none */ + if (lcd_mode[0]) { + sunxi_display.monitor = sunxi_monitor_lcd; + } else { +#ifdef CONFIG_VIDEO_VGA_VIA_LCD + sunxi_display.monitor = sunxi_monitor_vga; +#else + sunxi_display.monitor = sunxi_monitor_none; +#endif + } + } /* else continue with hdmi/dvi without a cable connected */ + } +#endif + switch (sunxi_display.monitor) { case sunxi_monitor_none: return NULL; @@ -846,27 +872,6 @@ void *video_hw_init(void) printf("HDMI/DVI not supported on this board\n"); sunxi_display.monitor = sunxi_monitor_none; return NULL; -#else - /* Always call hdp_detect, as it also enables clocks, etc. */ - ret = sunxi_hdmi_hpd_detect(); - if (ret) { - printf("HDMI connected: "); - if (edid && sunxi_hdmi_edid_get_mode(&custom) == 0) - mode = &custom; - break; - } - if (!hpd) - break; /* User has requested to ignore hpd */ - - sunxi_hdmi_shutdown(); - - if (lcd_mode[0] == 0) { - sunxi_display.monitor = sunxi_monitor_none; - return NULL; /* No LCD, bail */ - } - - /* Fall back / through to LCD */ - sunxi_display.monitor = sunxi_monitor_lcd; #endif case sunxi_monitor_lcd: if (lcd_mode[0]) {

Add support for VGA directly from the sunxi SoC / display engine.
Signed-off-by: Hans de Goede hdegoede@redhat.com --- arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 2 + arch/arm/include/asm/arch-sunxi/display.h | 76 +++++++++++++++++++++++++++ board/sunxi/Kconfig | 9 +++- configs/A20-OLinuXino_MICRO_defconfig | 1 + configs/Cubietruck_defconfig | 1 + configs/Mele_A1000G_defconfig | 1 + configs/Mele_A1000_defconfig | 1 + configs/Mele_M3_defconfig | 1 + drivers/video/sunxi_display.c | 60 ++++++++++++++++++--- 9 files changed, 143 insertions(+), 9 deletions(-)
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h index dbc5e58..64b5c38 100644 --- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h +++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h @@ -190,6 +190,8 @@ struct sunxi_ccm_reg { #define AHB_GATE_OFFSET_HDMI 11 #define AHB_GATE_OFFSET_LCD1 5 #define AHB_GATE_OFFSET_LCD0 4 +#define AHB_GATE_OFFSET_TVE1 3 +#define AHB_GATE_OFFSET_TVE0 2
#define CCM_AHB_GATE_GPS (0x1 << 26) #define CCM_AHB_GATE_SDRAM (0x1 << 14) diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h index 908c5d9..8c25ad4 100644 --- a/arch/arm/include/asm/arch-sunxi/display.h +++ b/arch/arm/include/asm/arch-sunxi/display.h @@ -158,6 +158,52 @@ 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 + * then 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 */ + u8 res2[0x04]; /* 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-BE register constants. */ #define SUNXI_DE_BE_WIDTH(x) (((x) - 1) << 0) @@ -296,6 +342,36 @@ struct sunxi_hdmi_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_GCTRL_CFG0_VGA 0x20000000 +#define SUNXI_TVE_GCTRL_DAC_CFG0_VGA 0x403e1ac7 +#define SUNXI_TVE_GCTRL_UNKNOWN1_VGA 0x00000000 +#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 + int sunxi_simplefb_setup(void *blob);
#endif /* _SUNXI_DISPLAY_H */ diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index c7643cb..0cbfb26 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -291,9 +291,16 @@ config VIDEO_HDMI ---help--- Say Y here to add support for outputting video over HDMI.
+config VIDEO_VGA + boolean "VGA output support" + depends on VIDEO && (MACH_SUN4I || MACH_SUN7I) + default n + ---help--- + Say Y here to add support for outputting video over VGA. + config VIDEO_VGA_VIA_LCD boolean "VGA via LCD controller support" - depends on VIDEO + depends on VIDEO && MACH_SUN5I default n ---help--- Say Y here to add support for external DACs connected to the parallel diff --git a/configs/A20-OLinuXino_MICRO_defconfig b/configs/A20-OLinuXino_MICRO_defconfig index 1b9668d..1c5a6f7 100644 --- a/configs/A20-OLinuXino_MICRO_defconfig +++ b/configs/A20-OLinuXino_MICRO_defconfig @@ -2,6 +2,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8),USB_EHCI" CONFIG_FDTFILE="sun7i-a20-olinuxino-micro.dtb" CONFIG_MMC_SUNXI_SLOT_EXTRA=3 +CONFIG_VIDEO_VGA=y +S:CONFIG_MMC0_CD_PIN="PH1" +S:CONFIG_MMC3_CD_PIN="PH11" +S:CONFIG_ARM=y diff --git a/configs/Cubietruck_defconfig b/configs/Cubietruck_defconfig index b1f9f93..bc44410 100644 --- a/configs/Cubietruck_defconfig +++ b/configs/Cubietruck_defconfig @@ -1,6 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_GMAC,RGMII,AHCI,SATAPWR=SUNXI_GPH(12),USB_EHCI" CONFIG_FDTFILE="sun7i-a20-cubietruck.dtb" +CONFIG_VIDEO_VGA=y +S:CONFIG_ARM=y +S:CONFIG_ARCH_SUNXI=y +S:CONFIG_MACH_SUN7I=y diff --git a/configs/Mele_A1000G_defconfig b/configs/Mele_A1000G_defconfig index 2f4bf72..9cb3285 100644 --- a/configs/Mele_A1000G_defconfig +++ b/configs/Mele_A1000G_defconfig @@ -1,6 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_EMAC,MACPWR=SUNXI_GPH(15),AHCI,USB_EHCI" CONFIG_FDTFILE="sun4i-a10-a1000.dtb" +CONFIG_VIDEO_VGA=y +S:CONFIG_ARM=y +S:CONFIG_ARCH_SUNXI=y +S:CONFIG_MACH_SUN4I=y diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig index e2912b0..97d9454 100644 --- a/configs/Mele_A1000_defconfig +++ b/configs/Mele_A1000_defconfig @@ -1,6 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_EMAC,MACPWR=SUNXI_GPH(15),AHCI,USB_EHCI" CONFIG_FDTFILE="sun4i-a10-a1000.dtb" +CONFIG_VIDEO_VGA=y +S:CONFIG_ARM=y +S:CONFIG_ARCH_SUNXI=y +S:CONFIG_MACH_SUN4I=y diff --git a/configs/Mele_M3_defconfig b/configs/Mele_M3_defconfig index fe9ba11..141d565 100644 --- a/configs/Mele_M3_defconfig +++ b/configs/Mele_M3_defconfig @@ -1,6 +1,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_GMAC,USB_EHCI" CONFIG_FDTFILE="sun7i-a20-m3.dtb" +CONFIG_VIDEO_VGA=y +S:CONFIG_MMC_SUNXI_SLOT_EXTRA=2 +S:CONFIG_MMC0_CD_PIN="PH1" +S:CONFIG_ARM=y diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index c462203..6666c1f 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -571,8 +571,7 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode) writel(0, &lcdc->tcon0_io_tristate); }
-#ifdef CONFIG_VIDEO_HDMI - +#if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, int *clk_div, int *clk_double, bool use_portd_hvsync) @@ -626,6 +625,9 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, } sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double); } +#endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA */ + +#ifdef CONFIG_VIDEO_HDMI
static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode) { @@ -737,6 +739,37 @@ static void sunxi_hdmi_enable(void)
#endif /* CONFIG_VIDEO_HDMI */
+#ifdef CONFIG_VIDEO_VGA + +static void sunxi_vga_mode_set(void) +{ + 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; + + /* Clock on */ + setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0); + + /* Set TVE in VGA mode */ + 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_GCTRL_CFG0_VGA, &tve->cfg0); + writel(SUNXI_TVE_GCTRL_DAC_CFG0_VGA, &tve->dac_cfg0); + writel(SUNXI_TVE_GCTRL_UNKNOWN1_VGA, &tve->unknown1); +} + +static void sunxi_vga_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 */ + static void sunxi_drc_init(void) { #if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I @@ -759,13 +792,14 @@ static void sunxi_engines_init(void) static void sunxi_mode_set(const struct ctfb_res_modes *mode, unsigned int address) { + int __maybe_unused clk_div, clk_double; + switch (sunxi_display.monitor) { case sunxi_monitor_none: break; case sunxi_monitor_dvi: - case sunxi_monitor_hdmi: { + case sunxi_monitor_hdmi: #ifdef CONFIG_VIDEO_HDMI - int clk_div, clk_double; sunxi_composer_mode_set(mode, address); sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0); sunxi_hdmi_mode_set(mode, clk_div, clk_double); @@ -773,7 +807,6 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, sunxi_lcdc_enable(); sunxi_hdmi_enable(); #endif - } break; case sunxi_monitor_lcd: sunxi_lcdc_panel_enable(); @@ -784,7 +817,14 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, sunxi_lcdc_backlight_enable(); break; case sunxi_monitor_vga: -#ifdef CONFIG_VIDEO_VGA_VIA_LCD +#ifdef CONFIG_VIDEO_VGA + sunxi_composer_mode_set(mode, address); + sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1); + sunxi_vga_mode_set(); + sunxi_composer_enable(); + sunxi_lcdc_enable(); + sunxi_vga_enable(); +#elif defined CONFIG_VIDEO_VGA_VIA_LCD sunxi_composer_mode_set(mode, address); sunxi_lcdc_tcon0_mode_set(mode); sunxi_composer_enable(); @@ -853,7 +893,7 @@ void *video_hw_init(void) if (lcd_mode[0]) { sunxi_display.monitor = sunxi_monitor_lcd; } else { -#ifdef CONFIG_VIDEO_VGA_VIA_LCD +#if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA sunxi_display.monitor = sunxi_monitor_vga; #else sunxi_display.monitor = sunxi_monitor_none; @@ -883,7 +923,7 @@ void *video_hw_init(void) sunxi_display.monitor = sunxi_monitor_none; return NULL; case sunxi_monitor_vga: -#ifdef CONFIG_VIDEO_VGA_VIA_LCD +#if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA sunxi_display.depth = 18; break; #else @@ -939,7 +979,11 @@ int sunxi_simplefb_setup(void *blob) pipeline = "de_be0-lcd0"; break; case sunxi_monitor_vga: +#ifdef CONFIG_VIDEO_VGA + pipeline = "de_be0-lcd0-tve0"; +#elif defined CONFIG_VIDEO_VGA_VIA_LCD pipeline = "de_be0-lcd0"; +#endif break; }

On Sat, 2014-12-27 at 16:53 +0100, Hans de Goede wrote:
diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h index 908c5d9..8c25ad4 100644 --- a/arch/arm/include/asm/arch-sunxi/display.h +++ b/arch/arm/include/asm/arch-sunxi/display.h @@ -158,6 +158,52 @@ 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
- then the removed vga out capability the tvencoder seems to be the same.
You mean "other than" I think.
Other than (sorry ;-)) that: Acked-by: Ian Campbell ijc@hellion.org.uk

Hi,
On 29-12-14 15:18, Ian Campbell wrote:
On Sat, 2014-12-27 at 16:53 +0100, Hans de Goede wrote:
diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h index 908c5d9..8c25ad4 100644 --- a/arch/arm/include/asm/arch-sunxi/display.h +++ b/arch/arm/include/asm/arch-sunxi/display.h @@ -158,6 +158,52 @@ 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
- then the removed vga out capability the tvencoder seems to be the same.
You mean "other than" I think.
Fixed in my personal tree, and added your ack.
Thanks for all the reviews!
I'll go and poke Anatolij to get his ack for the videomodes.c changes, with that (+ a respin of a few remaining patches you had comments on) the entire display series can be queued up for merging in next.
Regards,
Hans
participants (2)
-
Hans de Goede
-
Ian Campbell