sunxi: video: Add VGA output support
Add support for VGA directly from the sunxi SoC / display engine. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Ian Campbell <ijc@hellion.org.uk>
This commit is contained in:
parent
49d2703dd8
commit
d9786d2380
@ -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)
|
||||
|
@ -160,6 +160,52 @@ struct sunxi_hdmi_reg {
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
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.
|
||||
*/
|
||||
@ -299,6 +345,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 */
|
||||
|
@ -294,9 +294,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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -569,8 +569,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)
|
||||
@ -624,6 +623,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)
|
||||
{
|
||||
@ -735,6 +737,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
|
||||
@ -757,13 +790,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);
|
||||
@ -771,7 +805,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();
|
||||
@ -782,7 +815,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();
|
||||
@ -862,7 +902,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;
|
||||
@ -894,7 +934,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
|
||||
@ -950,7 +990,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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user