Update H5/A64 disp2 u-boot driver

HDMI output works on H5 and A54, CVBS doesn't work on H5 yet (?)
This commit is contained in:
zador-blood-stained 2017-02-21 16:13:14 +03:00
parent 89ccaa6457
commit 6bf30d53dc

View file

@ -1,12 +1,35 @@
commit ff787b168972bc8747ea152b38d4bc9447ba2fbe
Author: Jernej Skrabec <jernej.skrabec@siol.net>
Date: Mon Feb 20 21:54:02 2017 +0100
sunxi: video: Add video driver for H3/H5/A64 SoC
This patch adds support for hdmi and composite output. It is designed
in the same way as video driver for older Allwinner SoCs.
HDMI: First it checks if monitor is attached. If it is, recommended
timings are read from EDID. After that, DE2, TCON and HDMI are
configured according to this timings.
Composite output doesn't use any check if monitor is attached. This
can be added later.
32MB of RAM is used for framebuffer. This is just enough to support
4K resolution.
SimpleFB is also supported by this driver.
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
diff --git a/u-boot/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/u-boot/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index 4d5e910..848b042 100644
index 3f87672..4e93af5 100644
--- a/u-boot/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/u-boot/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -67,12 +67,20 @@ struct sunxi_ccm_reg {
@@ -67,14 +67,24 @@ struct sunxi_ccm_reg {
u32 dram_pll_cfg; /* 0xf8 PLL_DDR cfg register, A33 only */
u32 mbus_reset; /* 0xfc MBUS reset control, A33 only */
u32 dram_clk_gate; /* 0x100 DRAM module gating */
+#if defined CONFIG_MACH_SUN8I_H3 || defined CONFIG_MACH_SUN50I_H5
+#if defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
+ u32 de_clk_cfg; /* 0x104 DE module clock */
+#else
u32 be0_clk_cfg; /* 0x104 BE0 module clock */
@ -15,19 +38,24 @@ index 4d5e910..848b042 100644
u32 fe0_clk_cfg; /* 0x10c FE0 module clock */
u32 fe1_clk_cfg; /* 0x110 FE1 module clock */
u32 mp_clk_cfg; /* 0x114 MP module clock */
+#if defined CONFIG_MACH_SUN8I_H3 || defined CONFIG_MACH_SUN50I_H5
+#if defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
+ u32 tcon0_clk_cfg; /* 0x118 TCON0 module clock */
+ u32 tcon1_clk_cfg; /* 0x11c TCON1 module clock */
+#else
u32 lcd0_ch0_clk_cfg; /* 0x118 LCD0 CH0 module clock */
+#endif
u32 lcd1_ch0_clk_cfg; /* 0x11c LCD1 CH0 module clock */
u32 reserved14[3];
- u32 reserved14[3];
+#endif
+ u32 tve_clk_cfg; /* 0x120 TVE module clock */
+ u32 reserved14[2];
u32 lcd0_ch1_clk_cfg; /* 0x12c LCD0 CH1 module clock */
@@ -85,7 +93,11 @@ struct sunxi_ccm_reg {
u32 lcd1_ch1_clk_cfg; /* 0x130 LCD1 CH1 module clock */
u32 csi0_clk_cfg; /* 0x134 CSI0 module clock */
@@ -85,7 +95,11 @@ struct sunxi_ccm_reg {
u32 dmic_clk_cfg; /* 0x148 Digital Mic module clock*/
u32 reserved15;
u32 hdmi_clk_cfg; /* 0x150 HDMI module clock */
+#if defined CONFIG_MACH_SUN8I_H3 || defined CONFIG_MACH_SUN50I_H5
+#if defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
+ u32 hdmi_slow_clk_cfg; /* 0x154 HDMI slow module clock */
+#else
u32 ps_clk_cfg; /* 0x154 PS module clock */
@ -35,7 +63,7 @@ index 4d5e910..848b042 100644
u32 mtc_clk_cfg; /* 0x158 MTC module clock */
u32 mbus0_clk_cfg; /* 0x15c MBUS0 module clock */
u32 mbus1_clk_cfg; /* 0x160 MBUS1 module clock */
@@ -220,6 +232,15 @@ struct sunxi_ccm_reg {
@@ -220,6 +234,15 @@ struct sunxi_ccm_reg {
#define CCM_MIPI_PLL_CTRL_LDO_EN (0x3 << 22)
#define CCM_MIPI_PLL_CTRL_EN (0x1 << 31)
@ -51,12 +79,13 @@ index 4d5e910..848b042 100644
#if defined(CONFIG_MACH_SUN50I)
#define CCM_PLL11_CTRL_N(n) ((((n) - 1) & 0x7f) << 8)
#else
@@ -275,9 +296,12 @@ struct sunxi_ccm_reg {
@@ -271,9 +294,13 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_DRC0 25
#define AHB_GATE_OFFSET_DE_FE0 14
#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
#define AHB_GATE_OFFSET_LCD1 5
#define AHB_GATE_OFFSET_LCD0 4
+#define AHB_GATE_OFFSET_TCON1 4
@ -64,17 +93,23 @@ index 4d5e910..848b042 100644
#define CCM_MMC_CTRL_M(x) ((x) - 1)
#define CCM_MMC_CTRL_OCLK_DLY(x) ((x) << 8)
@@ -351,6 +375,9 @@ struct sunxi_ccm_reg {
@@ -347,6 +374,15 @@ struct sunxi_ccm_reg {
#define CCM_LCD_CH0_CTRL_RST 0
#define CCM_LCD_CH0_CTRL_GATE (0x1 << 31)
+#define CCM_TVE_CTRL_GATE (0x1 << 31)
+#define CCM_TVE_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
+
+#define CCM_TCON0_CTRL_GATE (0x1 << 31)
+#define CCM_TCON0_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
+
+#define CCM_TCON1_CTRL_GATE (0x1 << 31)
+#define CCM_TCON1_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
+
#define CCM_LCD_CH1_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
#define CCM_LCD_CH1_CTRL_HALF_SCLK1 0 /* no seperate sclk1 & 2 on sun6i */
#define CCM_LCD_CH1_CTRL_PLL3 (0 << 24)
@@ -360,6 +387,7 @@ struct sunxi_ccm_reg {
@@ -356,6 +392,7 @@ struct sunxi_ccm_reg {
#define CCM_LCD_CH1_CTRL_GATE (0x1 << 31)
#define CCM_HDMI_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
@ -82,7 +117,7 @@ index 4d5e910..848b042 100644
#define CCM_HDMI_CTRL_PLL_MASK (3 << 24)
#define CCM_HDMI_CTRL_PLL3 (0 << 24)
#define CCM_HDMI_CTRL_PLL7 (1 << 24)
@@ -368,6 +396,8 @@ struct sunxi_ccm_reg {
@@ -364,6 +401,8 @@ struct sunxi_ccm_reg {
#define CCM_HDMI_CTRL_DDC_GATE (0x1 << 30)
#define CCM_HDMI_CTRL_GATE (0x1 << 31)
@ -91,13 +126,14 @@ index 4d5e910..848b042 100644
#if defined(CONFIG_MACH_SUN50I)
#define MBUS_CLK_DEFAULT 0x81000002 /* PLL6x2 / 3 */
#elif defined(CONFIG_MACH_SUN8I)
@@ -395,9 +425,13 @@ struct sunxi_ccm_reg {
@@ -391,9 +430,14 @@ struct sunxi_ccm_reg {
#define AHB_RESET_OFFSET_DRC0 25
#define AHB_RESET_OFFSET_DE_FE0 14
#define AHB_RESET_OFFSET_DE_BE0 12
+#define AHB_RESET_OFFSET_DE 12
#define AHB_RESET_OFFSET_HDMI 11
+#define AHB_RESET_OFFSET_HDMI2 10
+#define AHB_RESET_OFFSET_TVE 9
#define AHB_RESET_OFFSET_LCD1 5
#define AHB_RESET_OFFSET_LCD0 4
+#define AHB_RESET_OFFSET_TCON1 4
@ -105,7 +141,7 @@ index 4d5e910..848b042 100644
/* ahb_reset2 offsets */
#define AHB_RESET_OFFSET_EPHY 2
@@ -420,6 +454,13 @@ struct sunxi_ccm_reg {
@@ -416,6 +460,13 @@ struct sunxi_ccm_reg {
#define CCM_DE_CTRL_PLL10 (5 << 24)
#define CCM_DE_CTRL_GATE (1 << 31)
@ -119,7 +155,7 @@ index 4d5e910..848b042 100644
/* CCU security switch, H3 only */
#define CCM_SEC_SWITCH_MBUS_NONSEC (1 << 2)
#define CCM_SEC_SWITCH_BUS_NONSEC (1 << 1)
@@ -428,7 +469,9 @@ struct sunxi_ccm_reg {
@@ -424,7 +475,9 @@ struct sunxi_ccm_reg {
#ifndef __ASSEMBLY__
void clock_set_pll1(unsigned int hz);
void clock_set_pll3(unsigned int hz);
@ -130,7 +166,7 @@ index 4d5e910..848b042 100644
void clock_set_mipi_pll(unsigned int hz);
unsigned int clock_get_pll3(void);
diff --git a/u-boot/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h b/u-boot/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
index 7232f6d..d971c17 100644
index 3c85222..4a72dae 100644
--- a/u-boot/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
+++ b/u-boot/arch/arm/include/asm/arch-sunxi/cpu_sun4i.h
@@ -18,6 +18,8 @@
@ -142,21 +178,42 @@ index 7232f6d..d971c17 100644
#ifdef CONFIG_MACH_SUN8I_A83T
#define SUNXI_CPUCFG_BASE 0x01700000
#endif
@@ -46,7 +48,9 @@
@@ -32,7 +34,9 @@
#define SUNXI_MS_BASE 0x01c07000
#define SUNXI_TVD_BASE 0x01c08000
#define SUNXI_CSI0_BASE 0x01c09000
+#ifndef CONFIG_MACH_SUN8I_H3
#define SUNXI_TVE0_BASE 0x01c0a000
+#endif
#define SUNXI_EMAC_BASE 0x01c0b000
#define SUNXI_LCD0_BASE 0x01c0C000
#define SUNXI_LCD1_BASE 0x01c0d000
@@ -46,7 +50,9 @@
#define SUNXI_USB1_BASE 0x01c14000
#endif
#define SUNXI_SS_BASE 0x01c15000
+#if !defined CONFIG_MACH_SUN8I_H3 && !defined CONFIG_MACH_SUN50I_H5
+#if !defined(CONFIG_MACH_SUN8I_H3) && !defined(CONFIG_MACH_SUN50I)
#define SUNXI_HDMI_BASE 0x01c16000
+#endif
#define SUNXI_SPI2_BASE 0x01c17000
#define SUNXI_SATA_BASE 0x01c18000
#ifdef CONFIG_SUNXI_GEN_SUN4I
@@ -163,6 +167,10 @@ defined(CONFIG_MACH_SUN50I)
@@ -157,13 +163,21 @@ 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
#define SUNXI_DE_BE1_BASE 0x01e40000
#define SUNXI_MP_BASE 0x01e80000
#define SUNXI_AVG_BASE 0x01ea0000
+#if defined CONFIG_MACH_SUN8I_H3 || defined CONFIG_MACH_SUN50I_H5
+#if defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
+#define SUNXI_HDMI_BASE 0x01ee0000
+#endif
+
@ -165,10 +222,10 @@ index 7232f6d..d971c17 100644
diff --git a/u-boot/arch/arm/include/asm/arch-sunxi/display2.h b/u-boot/arch/arm/include/asm/arch-sunxi/display2.h
new file mode 100644
index 0000000..b1d99d7
index 0000000..6021be9
--- /dev/null
+++ b/u-boot/arch/arm/include/asm/arch-sunxi/display2.h
@@ -0,0 +1,377 @@
@@ -0,0 +1,490 @@
+/*
+ * Sunxi platform display controller register and constant defines
+ *
@ -307,6 +364,24 @@ index 0000000..b1d99d7
+ u32 ovl_size; /* 88 */
+};
+
+struct de_csc {
+ u32 csc_ctl;
+ u32 rsv[3];
+ u32 coef11;
+ u32 coef12;
+ u32 coef13;
+ u32 coef14;
+ u32 coef21;
+ u32 coef22;
+ u32 coef23;
+ u32 coef24;
+ u32 coef31;
+ u32 coef32;
+ u32 coef33;
+ u32 coef34;
+ u32 alpha;
+};
+
+struct sunxi_dwc_hdmi {
+ u8 reserved0[0x100];
+ u8 ih_fc_stat0;
@ -459,10 +534,50 @@ index 0000000..b1d99d7
+ u32 phy_status;
+};
+
+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[8]; /* 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 register constants.
+ */
+#define SUNXI_DE2_MUX0_BASE (u8 *)(SUNXI_DE2_BASE + 0x100000)
+#define SUNXI_DE2_MUX1_BASE (u8 *)(SUNXI_DE2_BASE + 0x200000)
+
+#define SUNXI_DE2_MUX_GLB_REGS 0x00000
+#define SUNXI_DE2_MUX_BLD_REGS 0x01000
@ -544,10 +659,65 @@ index 0000000..b1d99d7
+
+#define SUNXI_HDMI_HPD_DETECT (1 << 19)
+
+/*
+ * 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_PAL 0x07070001
+#define SUNXI_TVE_CFG0_NTSC 0x07070000
+#define SUNXI_TVE_DAC_CFG0_COMPOSITE 0x433f0009
+#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
+
+#endif /* _SUNXI_DISPLAY_H */
diff --git a/u-boot/arch/arm/mach-sunxi/clock_sun6i.c b/u-boot/arch/arm/mach-sunxi/clock_sun6i.c
index a70c9cd..756c55c 100644
index d123b3a..7af7791 100644
--- a/u-boot/arch/arm/mach-sunxi/clock_sun6i.c
+++ b/u-boot/arch/arm/mach-sunxi/clock_sun6i.c
@@ -145,6 +145,17 @@ void clock_set_pll3(unsigned int clk)
@ -593,19 +763,19 @@ index a70c9cd..756c55c 100644
void clock_set_pll11(unsigned int clk, bool sigma_delta_enable)
{
diff --git a/u-boot/board/sunxi/Kconfig b/u-boot/board/sunxi/Kconfig
index 42adff1..d91e0d1 100644
index 37b4252..8ba8644 100644
--- a/u-boot/board/sunxi/Kconfig
+++ b/u-boot/board/sunxi/Kconfig
@@ -532,7 +532,7 @@ config AXP_GPIO
@@ -485,7 +485,7 @@ config AXP_GPIO
config VIDEO
bool "Enable graphical uboot console on HDMI, LCD or VGA"
- depends on !MACH_SUN8I_A83T && !MACH_SUN8I_H3 && !MACH_SUN9I && !MACH_SUN50I
+ depends on !MACH_SUN8I_A83T && !MACH_SUN9I && !MACH_SUN50I
+ depends on !MACH_SUN8I_A83T && !MACH_SUN9I
default y
---help---
Say Y here to add support for using a cfb console on the HDMI, LCD
@@ -541,7 +541,7 @@ config VIDEO
@@ -494,7 +494,7 @@ config VIDEO
config VIDEO_HDMI
bool "HDMI output support"
@ -614,11 +784,30 @@ index 42adff1..d91e0d1 100644
default y
---help---
Say Y here to add support for outputting video over HDMI.
@@ -535,7 +535,7 @@ config VIDEO_VGA_EXTERNAL_DAC_EN
config VIDEO_COMPOSITE
bool "Composite video output support"
- depends on VIDEO && (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I)
+ depends on VIDEO && (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I_H3 || MACH_SUN50I_H5)
default n
---help---
Say Y here to add support for outputting composite video.
diff --git a/u-boot/configs/orangepi_pc2_defconfig b/u-boot/configs/orangepi_pc2_defconfig
index d17e4d3..f65a321 100644
--- a/u-boot/configs/orangepi_pc2_defconfig
+++ b/u-boot/configs/orangepi_pc2_defconfig
@@ -12,3 +12,4 @@ CONFIG_CONSOLE_MUX=y
@@ -12,3 +12,5 @@ CONFIG_CONSOLE_MUX=y
# CONFIG_CMD_FPGA is not set
CONFIG_SUN8I_EMAC=y
CONFIG_USB_EHCI_HCD=y
+CONFIG_VIDEO=y
+CONFIG_VIDEO_COMPOSITE=y
diff --git a/u-boot/configs/pine64_plus_defconfig b/u-boot/configs/pine64_plus_defconfig
index a76f66a..9e2c3be 100644
--- a/u-boot/configs/pine64_plus_defconfig
+++ b/u-boot/configs/pine64_plus_defconfig
@@ -11,3 +11,4 @@ CONFIG_SPL=y
# CONFIG_CMD_FPGA is not set
CONFIG_SUN8I_EMAC=y
CONFIG_USB_EHCI_HCD=y
@ -637,10 +826,10 @@ index db34904..3097b82 100644
obj-$(CONFIG_VIDEO_VESA) += vesa.o
diff --git a/u-boot/drivers/video/sunxi_display2.c b/u-boot/drivers/video/sunxi_display2.c
new file mode 100644
index 0000000..db376d9
index 0000000..ecef9f6
--- /dev/null
+++ b/u-boot/drivers/video/sunxi_display2.c
@@ -0,0 +1,1037 @@
@@ -0,0 +1,1273 @@
+/*
+ * Display driver for sunxi Allwinner SoCs with DE2.
+ *
@ -678,6 +867,8 @@ index 0000000..db376d9
+ sunxi_monitor_none,
+ sunxi_monitor_dvi,
+ sunxi_monitor_hdmi,
+ sunxi_monitor_composite_pal,
+ sunxi_monitor_composite_ntsc,
+};
+#define SUNXI_MONITOR_LAST sunxi_monitor_hdmi
+
@ -689,6 +880,42 @@ index 0000000..db376d9
+ unsigned int fb_size;
+} sunxi_display;
+
+const struct ctfb_res_modes composite_video_modes[2] = {
+ /* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */
+ { 720, 576, 50, 37037, 27000, 137, 5, 20, 27, 2, 2, 0, FB_VMODE_INTERLACED },
+ { 720, 480, 60, 37037, 27000, 116, 20, 16, 27, 2, 2, 0, FB_VMODE_INTERLACED },
+};
+
+static bool sunxi_is_composite(void)
+{
+ switch (sunxi_display.monitor) {
+ case sunxi_monitor_none:
+ case sunxi_monitor_dvi:
+ case sunxi_monitor_hdmi:
+ return false;
+ case sunxi_monitor_composite_pal:
+ case sunxi_monitor_composite_ntsc:
+ return true;
+ }
+
+ return false; /* Never reached */
+}
+
+static bool sunxi_is_hdmi(void)
+{
+ switch (sunxi_display.monitor) {
+ case sunxi_monitor_none:
+ case sunxi_monitor_composite_pal:
+ case sunxi_monitor_composite_ntsc:
+ return false;
+ case sunxi_monitor_dvi:
+ case sunxi_monitor_hdmi:
+ return true;
+ }
+
+ return false; /* Never reached */
+}
+
+#ifdef CONFIG_VIDEO_HDMI
+
+static void sunxi_hdmi_phy_init(void)
@ -989,6 +1216,14 @@ index 0000000..db376d9
+{
+ struct sunxi_ccm_reg * const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+#if defined(CONFIG_MACH_SUN50I) && !defined(CONFIG_MACH_SUN50I_H5)
+ u32 reg_value;
+
+ /* set SRAM for video use (A64 only) */
+ reg_value = readl(SUNXI_SRAMC_BASE + 0x04);
+ reg_value &= ~(0x01 << 24);
+ writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
+#endif
+
+ clock_set_pll10(432000000);
+
@ -1004,29 +1239,37 @@ index 0000000..db376d9
+ setbits_le32(&ccm->de_clk_cfg, CCM_DE2_CTRL_GATE);
+}
+
+static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
+static void sunxi_composer_mode_set(int mux, const struct ctfb_res_modes *mode,
+ unsigned int address)
+{
+ void *de_mux_base = (mux == 0) ? SUNXI_DE2_MUX0_BASE : SUNXI_DE2_MUX1_BASE;
+ struct de_clk * const de_clk_regs =
+ (struct de_clk *)(SUNXI_DE2_BASE);
+ struct de_glb * const de_glb_regs =
+ (struct de_glb *)(SUNXI_DE2_MUX0_BASE +
+ (struct de_glb *)(de_mux_base +
+ SUNXI_DE2_MUX_GLB_REGS);
+ struct de_bld * const de_bld_regs =
+ (struct de_bld *)(SUNXI_DE2_MUX0_BASE +
+ (struct de_bld *)(de_mux_base +
+ SUNXI_DE2_MUX_BLD_REGS);
+ struct de_ui * const de_ui_regs =
+ (struct de_ui *)(SUNXI_DE2_MUX0_BASE +
+ (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->xres, mode->yres);
+ int channel, i;
+ int channel;
+ u32 data;
+
+ /* enable clock */
+ setbits_le32(&de_clk_regs->rst_cfg, 1);
+ setbits_le32(&de_clk_regs->gate_cfg, 1);
+ setbits_le32(&de_clk_regs->bus_cfg, 1);
+#ifdef CONFIG_MACH_SUN8I_H3
+ setbits_le32(&de_clk_regs->rst_cfg, (mux == 0) ? 1 : 4);
+#else
+ setbits_le32(&de_clk_regs->rst_cfg, (mux == 0) ? 1 : 2);
+#endif
+ setbits_le32(&de_clk_regs->gate_cfg, (mux == 0) ? 1 : 2);
+ setbits_le32(&de_clk_regs->bus_cfg, (mux == 0) ? 1 : 2);
+
+ clrbits_le32(&de_clk_regs->sel_cfg, 1);
+
@ -1036,7 +1279,7 @@ index 0000000..db376d9
+ writel(size, &de_glb_regs->size);
+
+ for (channel = 0; channel < 4; channel++) {
+ void *chan = SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_CHAN_REGS +
+ void *chan = de_mux_base + SUNXI_DE2_MUX_CHAN_REGS +
+ SUNXI_DE2_MUX_CHAN_SZ * channel;
+ memset(chan, 0, channel == 0 ?
+ sizeof(struct de_vi) : sizeof(struct de_ui));
@ -1051,30 +1294,46 @@ index 0000000..db376d9
+ writel(0xff000000, &de_bld_regs->bkcolor);
+
+ writel(0x03010301, &de_bld_regs->bld_mode[0]);
+ writel(0x03010301, &de_bld_regs->bld_mode[1]);
+
+ writel(size, &de_bld_regs->output_size);
+ writel(mode->vmode & FB_VMODE_INTERLACED ? 2 : 0,
+ &de_bld_regs->out_ctl);
+ &de_bld_regs->out_ctl);
+ writel(0, &de_bld_regs->ck_ctl);
+
+ for (i = 0; i < 4; i++) {
+ writel(0xff000000, &de_bld_regs->attr[i].fcolor);
+ writel(size, &de_bld_regs->attr[i].insize);
+ }
+ writel(0xff000000, &de_bld_regs->attr[0].fcolor);
+ writel(size, &de_bld_regs->attr[0].insize);
+
+ /* Disable all other units */
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_VSU_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_GSU1_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_GSU2_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_GSU3_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_FCE_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_BWS_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_LTI_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_PEAK_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_ASE_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_FCC_REGS);
+ writel(0, SUNXI_DE2_MUX0_BASE + SUNXI_DE2_MUX_DCSC_REGS);
+ writel(0, de_mux_base + SUNXI_DE2_MUX_VSU_REGS);
+ writel(0, de_mux_base + SUNXI_DE2_MUX_GSU1_REGS);
+ writel(0, de_mux_base + SUNXI_DE2_MUX_GSU2_REGS);
+ writel(0, de_mux_base + SUNXI_DE2_MUX_GSU3_REGS);
+ writel(0, de_mux_base + SUNXI_DE2_MUX_FCE_REGS);
+ writel(0, de_mux_base + SUNXI_DE2_MUX_BWS_REGS);
+ writel(0, de_mux_base + SUNXI_DE2_MUX_LTI_REGS);
+ 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);
+
+ if (sunxi_is_composite()) {
+ 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);
+ writel(0x20200, &de_csc_regs->alpha);
+
+ writel(1, &de_csc_regs->csc_ctl);
+ } else {
+ writel(0, &de_csc_regs->csc_ctl);
+ }
+
+ data = SUNXI_DE2_UI_CFG_ATTR_EN |
+ SUNXI_DE2_UI_CFG_ATTR_FMT(SUNXI_DE2_FORMAT_XRGB_8888) |
@ -1088,10 +1347,15 @@ index 0000000..db376d9
+ writel(size, &de_ui_regs->ovl_size);
+}
+
+static void sunxi_composer_enable(void)
+static void sunxi_composer_enable(int mux)
+{
+ struct de_glb * const de_glb_regs =
+ (struct de_glb *)(SUNXI_DE2_MUX0_BASE +
+ struct de_glb *de_glb_regs;
+
+ if (mux == 0)
+ de_glb_regs = (struct de_glb *)(SUNXI_DE2_MUX0_BASE +
+ SUNXI_DE2_MUX_GLB_REGS);
+ else
+ de_glb_regs = (struct de_glb *)(SUNXI_DE2_MUX1_BASE +
+ SUNXI_DE2_MUX_GLB_REGS);
+
+ writel(1, &de_glb_regs->dbuff);
@ -1145,25 +1409,44 @@ index 0000000..db376d9
+ dotclock, (clock_get_pll3() / 1000) / x,
+ best_n, best_m, x);
+
+#if defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I_H5)
+ writel(CCM_TCON0_CTRL_GATE | CCM_TCON0_CTRL_M(x),
+ &ccm->tcon0_clk_cfg);
+#else
+ writel(CCM_TCON1_CTRL_GATE | CCM_TCON1_CTRL_M(x),
+ &ccm->tcon1_clk_cfg);
+#endif
+
+ *clk_div = x;
+}
+
+static void sunxi_lcdc_init(void)
+static void sunxi_lcdc_init(int num)
+{
+ struct sunxi_ccm_reg * const ccm =
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ struct sunxi_lcdc_reg * const lcdc =
+ (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+ struct sunxi_lcdc_reg *lcdc;
+
+ /* Reset off */
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TCON0);
+ if (num == 0) {
+ lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+
+ /* Clock on */
+ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TCON0);
+ setbits_le32(&ccm->tcon0_clk_cfg, CCM_TCON0_CTRL_GATE);
+ /* Reset off */
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TCON0);
+
+ /* Clock on */
+ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TCON0);
+ setbits_le32(&ccm->tcon0_clk_cfg, CCM_TCON0_CTRL_GATE);
+ } else {
+ lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD1_BASE;
+
+ /* Reset off */
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TCON1);
+
+ /* Clock on */
+ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TCON1);
+#if !defined(CONFIG_MACH_SUN50I_H5) && defined(CONFIG_MACH_SUN50I)
+ setbits_le32(&ccm->tcon1_clk_cfg, CCM_TCON1_CTRL_GATE);
+#endif
+ }
+
+ /* Init lcdc */
+ writel(0, &lcdc->ctrl); /* Disable tcon */
@ -1173,10 +1456,14 @@ index 0000000..db376d9
+ writel(0x0fffffff, &lcdc->tcon1_io_tristate);
+}
+
+static void sunxi_lcdc_enable(void)
+static void sunxi_lcdc_enable(int num)
+{
+ struct sunxi_lcdc_reg * const lcdc =
+ (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+ struct sunxi_lcdc_reg *lcdc;
+
+ if (num == 0)
+ lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+ else
+ lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD1_BASE;
+
+ setbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_TCON_ENABLE);
+}
@ -1193,14 +1480,19 @@ index 0000000..db376d9
+ return (delay > 31) ? 31 : delay;
+}
+
+#if defined CONFIG_VIDEO_HDMI
+static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
+#if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_COMPOSITE
+static void sunxi_lcdc_tcon1_mode_set(int num,
+ const struct ctfb_res_modes *mode,
+ int *clk_div)
+{
+ struct sunxi_lcdc_reg * const lcdc =
+ (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+ struct sunxi_lcdc_reg *lcdc;
+ int bp, clk_delay, total, yres;
+
+ if (num == 0)
+ lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
+ else
+ lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD1_BASE;
+
+ clk_delay = sunxi_lcdc_get_clk_delay(mode);
+ writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
+ ((mode->vmode == FB_VMODE_INTERLACED) ?
@ -1232,9 +1524,10 @@ index 0000000..db376d9
+ writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
+ &lcdc->tcon1_timing_sync);
+
+ sunxi_lcdc_pll_set(mode->pixclock_khz, clk_div);
+ if (!sunxi_is_composite())
+ sunxi_lcdc_pll_set(mode->pixclock_khz, clk_div);
+}
+#endif /* CONFIG_VIDEO_HDMI */
+#endif /* CONFIG_VIDEO_HDMI || CONFIG_VIDEO_COMPOSITE */
+
+#ifdef CONFIG_VIDEO_HDMI
+
@ -1438,16 +1731,101 @@ index 0000000..db376d9
+
+#endif /* CONFIG_VIDEO_HDMI */
+
+#ifdef CONFIG_VIDEO_COMPOSITE
+
+static void sunxi_tvencoder_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;
+
+ /* 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);
+
+ switch (sunxi_display.monitor) {
+ 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(0x2a098acb, &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, &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 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);
+ break;
+ case sunxi_monitor_none:
+ case sunxi_monitor_dvi:
+ case sunxi_monitor_hdmi:
+ break;
+ }
+}
+
+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_COMPOSITE */
+
+static void sunxi_engines_init(void)
+{
+#if defined(CONFIG_MACH_SUN50I_H5) || defined(CONFIG_MACH_SUN8I_H3)
+ int mux = sunxi_is_hdmi() ? 0 : 1;
+#else
+ int mux = sunxi_is_hdmi() ? 1 : 0;
+#endif
+ sunxi_composer_init();
+ sunxi_lcdc_init();
+ sunxi_lcdc_init(mux);
+}
+
+static void sunxi_mode_set(const struct ctfb_res_modes *mode,
+ unsigned int address)
+{
+ int __maybe_unused clk_div;
+ int __maybe_unused mux;
+
+ switch (sunxi_display.monitor) {
+ case sunxi_monitor_none:
@ -1455,23 +1833,41 @@ index 0000000..db376d9
+ case sunxi_monitor_dvi:
+ case sunxi_monitor_hdmi:
+#ifdef CONFIG_VIDEO_HDMI
+ sunxi_composer_mode_set(mode, address);
+ sunxi_lcdc_tcon1_mode_set(mode, &clk_div);
+#if defined(CONFIG_MACH_SUN50I_H5) || defined(CONFIG_MACH_SUN8I_H3)
+ mux = 0;
+#else
+ mux = 1;
+#endif
+ sunxi_composer_mode_set(mux, mode, address);
+ sunxi_lcdc_tcon1_mode_set(mux, mode, &clk_div);
+ sunxi_hdmi_mode_set(mode, clk_div);
+ sunxi_composer_enable();
+ sunxi_lcdc_enable();
+ sunxi_composer_enable(mux);
+ sunxi_lcdc_enable(mux);
+ sunxi_hdmi_enable();
+#endif
+ break;
+ case sunxi_monitor_composite_pal:
+ case sunxi_monitor_composite_ntsc:
+#ifdef CONFIG_VIDEO_COMPOSITE
+ sunxi_composer_mode_set(1, mode, address);
+ sunxi_lcdc_tcon1_mode_set(1, mode, &clk_div);
+ sunxi_tvencoder_mode_set();
+ sunxi_composer_enable(1);
+ sunxi_lcdc_enable(1);
+ sunxi_tvencoder_enable();
+#endif
+ break;
+ }
+}
+
+static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
+{
+ switch (monitor) {
+ case sunxi_monitor_none: return "none";
+ case sunxi_monitor_dvi: return "dvi";
+ case sunxi_monitor_hdmi: return "hdmi";
+ case sunxi_monitor_none: return "none";
+ case sunxi_monitor_dvi: return "dvi";
+ case sunxi_monitor_hdmi: return "hdmi";
+ case sunxi_monitor_composite_pal: return "composite-pal";
+ case sunxi_monitor_composite_ntsc: return "composite-ntsc";
+ }
+ return NULL; /* never reached */
+}
@ -1490,10 +1886,21 @@ index 0000000..db376d9
+#endif
+}
+
+static bool sunxi_has_composite(void)
+{
+#ifdef CONFIG_VIDEO_COMPOSITE
+ return true;
+#else
+ return false;
+#endif
+}
+
+static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
+{
+ if (allow_hdmi && sunxi_has_hdmi())
+ return sunxi_monitor_dvi;
+ else if (sunxi_has_composite())
+ return sunxi_monitor_composite_pal;
+ else
+ return sunxi_monitor_none;
+}
@ -1563,12 +1970,26 @@ index 0000000..db376d9
+ return NULL;
+ }
+ break;
+ case sunxi_monitor_composite_pal:
+ case sunxi_monitor_composite_ntsc:
+ if (!sunxi_has_composite()) {
+ printf("Composite video not supported on this board\n");
+ sunxi_display.monitor = sunxi_monitor_none;
+ return NULL;
+ }
+ if (sunxi_display.monitor == sunxi_monitor_composite_pal)
+ mode = &composite_video_modes[0];
+ else
+ mode = &composite_video_modes[1];
+ sunxi_display.depth = 24;
+ break;
+ }
+
+ /* Yes these defaults are quite high, overscan on composite sucks... */
+ if (overscan_x == -1)
+ overscan_x = 0;
+ overscan_x = sunxi_is_composite() ? 32 : 0;
+ if (overscan_y == -1)
+ overscan_y = 0;
+ overscan_y = sunxi_is_composite() ? 20 : 0;
+
+ sunxi_display.fb_size =
+ (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff;
@ -1637,6 +2058,10 @@ index 0000000..db376d9
+ case sunxi_monitor_hdmi:
+ pipeline = "de0-lcd0-hdmi";
+ break;
+ case sunxi_monitor_composite_pal:
+ case sunxi_monitor_composite_ntsc:
+ pipeline = "de0-lcd1-tve0";
+ break;
+ }
+
+ /* Find a prefilled simpefb node, matching out pipeline config */
@ -1679,16 +2104,16 @@ index 0000000..db376d9
+}
+#endif /* CONFIG_OF_BOARD_SETUP && CONFIG_VIDEO_DT_SIMPLEFB */
diff --git a/u-boot/include/configs/sunxi-common.h b/u-boot/include/configs/sunxi-common.h
index ebb099b..7a01dde 100644
index d48bdac..5919a4f 100644
--- a/u-boot/include/configs/sunxi-common.h
+++ b/u-boot/include/configs/sunxi-common.h
@@ -270,16 +270,23 @@ extern int soft_i2c_gpio_scl;
@@ -274,16 +274,23 @@ extern int soft_i2c_gpio_scl;
#define CONFIG_SUNXI_GPIO
#ifdef CONFIG_VIDEO
+/* Do we want to initialize a simple FB? */
+#define CONFIG_VIDEO_DT_SIMPLEFB
+#if defined CONFIG_MACH_SUN8I_H3 || defined CONFIG_MACH_SUN50I_H5
+#if defined(CONFIG_MACH_SUN8I_H3) || defined(CONFIG_MACH_SUN50I)
+#define CONFIG_VIDEO_SUNXI2
+#else
+#define CONFIG_VIDEO_SUNXI
@ -1711,11 +2136,24 @@ index ebb099b..7a01dde 100644
#define CONFIG_VIDEO_LOGO
#define CONFIG_VIDEO_STD_TIMINGS
diff --git a/u-boot/include/video_fb.h b/u-boot/include/video_fb.h
index b008853..4a4fd5f 100644
--- a/u-boot/include/video_fb.h
+++ b/u-boot/include/video_fb.h
@@ -38,7 +38,7 @@ typedef struct graphic_device {
unsigned int dprBase;
unsigned int vprBase;
unsigned int cprBase;
- unsigned int frameAdrs;
+ unsigned long frameAdrs;
unsigned int memSize;
unsigned int mode;
unsigned int gdfIndex;
diff --git a/u-boot/scripts/config_whitelist.txt b/u-boot/scripts/config_whitelist.txt
index 8814841..fdee9d9 100644
index 826d031..b952c88 100644
--- a/u-boot/scripts/config_whitelist.txt
+++ b/u-boot/scripts/config_whitelist.txt
@@ -8165,6 +8165,7 @@ CONFIG_VIDEO_SM501_8BPP
@@ -6850,6 +6850,7 @@ CONFIG_VIDEO_SM501_8BPP
CONFIG_VIDEO_SM501_PCI
CONFIG_VIDEO_STD_TIMINGS
CONFIG_VIDEO_SUNXI