diff --git a/patch/u-boot/u-boot-sun50i-dev/h3-add-disp2-video-driver-jernej.patch b/patch/u-boot/u-boot-sun50i-dev/h3-add-disp2-video-driver-jernej.patch index d0989ea78..3e9500d41 100644 --- a/patch/u-boot/u-boot-sun50i-dev/h3-add-disp2-video-driver-jernej.patch +++ b/patch/u-boot/u-boot-sun50i-dev/h3-add-disp2-video-driver-jernej.patch @@ -1,12 +1,35 @@ +commit ff787b168972bc8747ea152b38d4bc9447ba2fbe +Author: Jernej Skrabec +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 + 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