diff --git a/arch/arm/cpu/armv7/ls102xa/soc.c b/arch/arm/cpu/armv7/ls102xa/soc.c index 52fb6f8..b84a1a6 100644 --- a/arch/arm/cpu/armv7/ls102xa/soc.c +++ b/arch/arm/cpu/armv7/ls102xa/soc.c @@ -91,7 +91,7 @@ int arch_soc_init(void) out_be32(&scfg->qspi_cfg, SCFG_QSPI_CLKSEL); #endif -#ifdef CONFIG_FSL_DCU_FB +#ifdef CONFIG_VIDEO_FSL_DCU_FB out_be32(&scfg->pixclkcr, SCFG_PIXCLKCR_PXCKEN); #endif diff --git a/arch/arm/include/asm/arch-vf610/crm_regs.h b/arch/arm/include/asm/arch-vf610/crm_regs.h index a46e396..73b1dd2 100644 --- a/arch/arm/include/asm/arch-vf610/crm_regs.h +++ b/arch/arm/include/asm/arch-vf610/crm_regs.h @@ -9,6 +9,8 @@ #ifndef __ASSEMBLY__ +#include + /* Clock Controller Module (CCM) */ struct ccm_reg { u32 ccr; @@ -150,6 +152,9 @@ struct anadig_reg { #define CCM_CACRR_ARM_CLK_DIV_MASK 0x7 #define CCM_CACRR_ARM_CLK_DIV(v) ((v) & 0x7) +#define CCM_CSCMR1_DCU1_CLK_SEL (1 << 29) +#define CCM_CSCMR1_DCU0_CLK_SEL (1 << 28) + #define CCM_CSCMR1_QSPI0_CLK_SEL_OFFSET 22 #define CCM_CSCMR1_QSPI0_CLK_SEL_MASK (0x3 << 22) #define CCM_CSCMR1_QSPI0_CLK_SEL(v) (((v) & 0x3) << 22) @@ -174,6 +179,13 @@ struct anadig_reg { #define CCM_CSCDR2_ESDHC1_CLK_DIV_MASK (0xf << 20) #define CCM_CSCDR2_ESDHC1_CLK_DIV(v) (((v) & 0xf) << 20) +#define CCM_CSCDR3_DCU1_EN (1 << 23) +#define CCM_CSCDR3_DCU1_DIV_MASK (0x7 << 20) +#define CCM_CSCDR3_DCU1_DIV(v) (((v) & 0x7) << 20) +#define CCM_CSCDR3_DCU0_EN (1 << 19) +#define CCM_CSCDR3_DCU0_DIV_MASK (0x7 << 16) +#define CCM_CSCDR3_DCU0_DIV(v) (((v) & 0x7) << 16) + #define CCM_CSCDR3_NFC_PRE_DIV_OFFSET 13 #define CCM_CSCDR3_NFC_PRE_DIV_MASK (0x7 << 13) #define CCM_CSCDR3_NFC_PRE_DIV(v) (((v) & 0x7) << 13) @@ -193,6 +205,7 @@ struct anadig_reg { #define CCM_CCGR0_DSPI1_CTRL_MASK (0x3 << 26) #define CCM_CCGR1_USBC0_CTRL_MASK (0x3 << 8) #define CCM_CCGR1_PIT_CTRL_MASK (0x3 << 14) +#define CCM_CCGR1_TCON0_CTRL_MASK (0x3 << 26) #define CCM_CCGR1_WDOGA5_CTRL_MASK (0x3 << 28) #define CCM_CCGR2_QSPI0_CTRL_MASK (0x3 << 8) #define CCM_CCGR2_IOMUXC_CTRL_MASK (0x3 << 16) @@ -203,6 +216,7 @@ struct anadig_reg { #define CCM_CCGR2_PORTE_CTRL_MASK (0x3 << 26) #define CCM_CCGR3_ANADIG_CTRL_MASK 0x3 #define CCM_CCGR3_SCSC_CTRL_MASK (0x3 << 4) +#define CCM_CCGR3_DCU0_CTRL_MASK (0x3 << 16) #define CCM_CCGR4_WKUP_CTRL_MASK (0x3 << 20) #define CCM_CCGR4_CCM_CTRL_MASK (0x3 << 22) #define CCM_CCGR4_GPC_CTRL_MASK (0x3 << 24) diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h b/arch/arm/include/asm/arch-vf610/imx-regs.h index cac68ef..ca97462 100644 --- a/arch/arm/include/asm/arch-vf610/imx-regs.h +++ b/arch/arm/include/asm/arch-vf610/imx-regs.h @@ -69,6 +69,7 @@ #define USB_PHY0_BASE_ADDR (AIPS0_BASE_ADDR + 0x00050800) #define USB_PHY1_BASE_ADDR (AIPS0_BASE_ADDR + 0x00050C00) #define SCSC_BASE_ADDR (AIPS0_BASE_ADDR + 0x00052000) +#define DCU0_BASE_ADDR (AIPS0_BASE_ADDR + 0x00058000) #define ASRC_BASE_ADDR (AIPS0_BASE_ADDR + 0x00060000) #define SPDIF_BASE_ADDR (AIPS0_BASE_ADDR + 0x00061000) #define ESAI_BASE_ADDR (AIPS0_BASE_ADDR + 0x00062000) @@ -98,6 +99,7 @@ #define USBC1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00034000) #define ENET_BASE_ADDR (AIPS1_BASE_ADDR + 0x00050000) #define ENET1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00051000) +#define DCU1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00058000) #define NFC_BASE_ADDR (AIPS1_BASE_ADDR + 0x00060000) #define QSPI0_AMBA_BASE 0x20000000 diff --git a/arch/arm/include/asm/arch-vf610/iomux-vf610.h b/arch/arm/include/asm/arch-vf610/iomux-vf610.h index a140be0..5af071a 100644 --- a/arch/arm/include/asm/arch-vf610/iomux-vf610.h +++ b/arch/arm/include/asm/arch-vf610/iomux-vf610.h @@ -40,6 +40,8 @@ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH) #define VF610_DSPI_SIN_PAD_CTRL (PAD_CTL_IBE_ENABLE | PAD_CTL_DSE_20ohm | \ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_HIGH) +#define VF610_DCU_PAD_CTRL (PAD_CTL_SPEED_MED | PAD_CTL_SRE | \ + PAD_CTL_DSE_37ohm | PAD_CTL_OBE_ENABLE) enum { VF610_PAD_PTA6__RMII0_CLKIN = IOMUX_PAD(0x0000, 0x0000, 2, __NA_, 0, VF610_ENET_PAD_CTRL), @@ -166,6 +168,35 @@ enum { VF610_PAD_PTC28__NF_CLE = IOMUX_PAD(0x0194, 0x0194, 6, __NA_, 0, VF610_NFC_CN_PAD_CTRL), + VF610_PAD_PTE0__DCU0_HSYNC = IOMUX_PAD(0x01a4, 0x01a4, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE1__DCU0_VSYNC = IOMUX_PAD(0x01a8, 0x01a8, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE2__DCU0_PCLK = IOMUX_PAD(0x01ac, 0x01ac, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE4__DCU0_DE = IOMUX_PAD(0x01b4, 0x01b4, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE5__DCU0_R0 = IOMUX_PAD(0x01b8, 0x01b8, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE6__DCU0_R1 = IOMUX_PAD(0x01bc, 0x01bc, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE7__DCU0_R2 = IOMUX_PAD(0x01c0, 0x01c0, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE8__DCU0_R3 = IOMUX_PAD(0x01c4, 0x01c4, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE9__DCU0_R4 = IOMUX_PAD(0x01c8, 0x01c8, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE10__DCU0_R5 = IOMUX_PAD(0x01cc, 0x01cc, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE11__DCU0_R6 = IOMUX_PAD(0x01d0, 0x01d0, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE12__DCU0_R7 = IOMUX_PAD(0x01d4, 0x01d4, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE13__DCU0_G0 = IOMUX_PAD(0x01d8, 0x01d8, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE14__DCU0_G1 = IOMUX_PAD(0x01dc, 0x01dc, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE15__DCU0_G2 = IOMUX_PAD(0x01e0, 0x01e0, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE16__DCU0_G3 = IOMUX_PAD(0x01e4, 0x01e4, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE17__DCU0_G4 = IOMUX_PAD(0x01e8, 0x01e8, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE18__DCU0_G5 = IOMUX_PAD(0x01ec, 0x01ec, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE19__DCU0_G6 = IOMUX_PAD(0x01f0, 0x01f0, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE20__DCU0_G7 = IOMUX_PAD(0x01f4, 0x01f4, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE21__DCU0_B0 = IOMUX_PAD(0x01f8, 0x01f8, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE22__DCU0_B1 = IOMUX_PAD(0x01fc, 0x01fc, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE23__DCU0_B2 = IOMUX_PAD(0x0200, 0x0200, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE24__DCU0_B3 = IOMUX_PAD(0x0204, 0x0204, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE25__DCU0_B4 = IOMUX_PAD(0x0208, 0x0208, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE26__DCU0_B5 = IOMUX_PAD(0x020c, 0x020c, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE27__DCU0_B6 = IOMUX_PAD(0x0210, 0x0210, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_PTE28__DCU0_B7 = IOMUX_PAD(0x0214, 0x0214, 1, __NA_, 0, VF610_DCU_PAD_CTRL), + VF610_PAD_DDR_RESETB = IOMUX_PAD(0x021c, 0x021c, 0, __NA_, 0, VF610_DDR_PAD_CTRL), VF610_PAD_DDR_A15__DDR_A_15 = IOMUX_PAD(0x0220, 0x0220, 0, __NA_, 0, VF610_DDR_PAD_CTRL), VF610_PAD_DDR_A14__DDR_A_14 = IOMUX_PAD(0x0224, 0x0224, 0, __NA_, 0, VF610_DDR_PAD_CTRL), diff --git a/arch/arm/include/asm/imx-common/iomux-v3.h b/arch/arm/include/asm/imx-common/iomux-v3.h index 7587cbb..ba0ed43 100644 --- a/arch/arm/include/asm/imx-common/iomux-v3.h +++ b/arch/arm/include/asm/imx-common/iomux-v3.h @@ -165,7 +165,10 @@ typedef u64 iomux_v3_cfg_t; #define PAD_CTL_ODE (1 << 10) #define PAD_CTL_DSE_150ohm (1 << 6) +#define PAD_CTL_DSE_75ohm (2 << 6) #define PAD_CTL_DSE_50ohm (3 << 6) +#define PAD_CTL_DSE_37ohm (4 << 6) +#define PAD_CTL_DSE_30ohm (5 << 6) #define PAD_CTL_DSE_25ohm (6 << 6) #define PAD_CTL_DSE_20ohm (7 << 6) diff --git a/board/freescale/ls1021aiot/Makefile b/board/freescale/ls1021aiot/Makefile index 05709e6..6b960aa 100644 --- a/board/freescale/ls1021aiot/Makefile +++ b/board/freescale/ls1021aiot/Makefile @@ -5,5 +5,5 @@ # obj-y += ls1021aiot.o -obj-$(CONFIG_FSL_DCU_FB) += dcu.o +obj-$(CONFIG_VIDEO_FSL_DCU_FB) += dcu.o obj-$(CONFIG_ARMV7_PSCI) += psci.o diff --git a/board/freescale/ls1021aqds/Makefile b/board/freescale/ls1021aqds/Makefile index f0390c1..1e50e46 100644 --- a/board/freescale/ls1021aqds/Makefile +++ b/board/freescale/ls1021aqds/Makefile @@ -7,5 +7,5 @@ obj-y += ls1021aqds.o obj-y += ddr.o obj-y += eth.o -obj-$(CONFIG_FSL_DCU_FB) += dcu.o +obj-$(CONFIG_VIDEO_FSL_DCU_FB) += dcu.o obj-$(CONFIG_ARMV7_PSCI) += psci.o diff --git a/board/freescale/ls1021atwr/Makefile b/board/freescale/ls1021atwr/Makefile index 5238b15..d9a2f52 100644 --- a/board/freescale/ls1021atwr/Makefile +++ b/board/freescale/ls1021atwr/Makefile @@ -5,5 +5,5 @@ # obj-y += ls1021atwr.o -obj-$(CONFIG_FSL_DCU_FB) += dcu.o +obj-$(CONFIG_VIDEO_FSL_DCU_FB) += dcu.o obj-$(CONFIG_ARMV7_PSCI) += psci.o diff --git a/board/toradex/colibri_vf/Makefile b/board/toradex/colibri_vf/Makefile index c7e5134..4d6287f 100644 --- a/board/toradex/colibri_vf/Makefile +++ b/board/toradex/colibri_vf/Makefile @@ -5,3 +5,4 @@ # obj-y := colibri_vf.o +obj-$(CONFIG_VIDEO_FSL_DCU_FB) += dcu.o diff --git a/board/toradex/colibri_vf/colibri_vf.c b/board/toradex/colibri_vf/colibri_vf.c index 7b74eb7..46dd15b 100644 --- a/board/toradex/colibri_vf/colibri_vf.c +++ b/board/toradex/colibri_vf/colibri_vf.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -295,6 +296,49 @@ static void setup_iomux_gpio(void) } #endif +#ifdef CONFIG_VIDEO_FSL_DCU_FB +static void setup_iomux_fsl_dcu(void) +{ + static const iomux_v3_cfg_t dcu0_pads[] = { + VF610_PAD_PTE0__DCU0_HSYNC, + VF610_PAD_PTE1__DCU0_VSYNC, + VF610_PAD_PTE2__DCU0_PCLK, + VF610_PAD_PTE4__DCU0_DE, + VF610_PAD_PTE5__DCU0_R0, + VF610_PAD_PTE6__DCU0_R1, + VF610_PAD_PTE7__DCU0_R2, + VF610_PAD_PTE8__DCU0_R3, + VF610_PAD_PTE9__DCU0_R4, + VF610_PAD_PTE10__DCU0_R5, + VF610_PAD_PTE11__DCU0_R6, + VF610_PAD_PTE12__DCU0_R7, + VF610_PAD_PTE13__DCU0_G0, + VF610_PAD_PTE14__DCU0_G1, + VF610_PAD_PTE15__DCU0_G2, + VF610_PAD_PTE16__DCU0_G3, + VF610_PAD_PTE17__DCU0_G4, + VF610_PAD_PTE18__DCU0_G5, + VF610_PAD_PTE19__DCU0_G6, + VF610_PAD_PTE20__DCU0_G7, + VF610_PAD_PTE21__DCU0_B0, + VF610_PAD_PTE22__DCU0_B1, + VF610_PAD_PTE23__DCU0_B2, + VF610_PAD_PTE24__DCU0_B3, + VF610_PAD_PTE25__DCU0_B4, + VF610_PAD_PTE26__DCU0_B5, + VF610_PAD_PTE27__DCU0_B6, + VF610_PAD_PTE28__DCU0_B7, + }; + + imx_iomux_v3_setup_multiple_pads(dcu0_pads, ARRAY_SIZE(dcu0_pads)); +} + +static void setup_tcon(void) +{ + setbits_le32(TCON0_BASE_ADDR, (1 << 29)); +} +#endif + #ifdef CONFIG_FSL_ESDHC struct fsl_esdhc_cfg esdhc_cfg[1] = { {ESDHC1_BASE_ADDR}, @@ -431,6 +475,11 @@ static void clock_init(void) CCM_CSCDR3_NFC_PRE_DIV(3)); clrsetbits_le32(&ccm->cscmr2, CCM_REG_CTRL_MASK, CCM_CSCMR2_RMII_CLK_SEL(2)); + +#ifdef CONFIG_VIDEO_FSL_DCU_FB + setbits_le32(&ccm->ccgr1, CCM_CCGR1_TCON0_CTRL_MASK); + setbits_le32(&ccm->ccgr3, CCM_CCGR3_DCU0_CTRL_MASK); +#endif } static void mscm_init(void) @@ -470,6 +519,11 @@ int board_early_init_f(void) setup_iomux_dspi(); #endif +#ifdef CONFIG_VIDEO_FSL_DCU_FB + setup_tcon(); + setup_iomux_fsl_dcu(); +#endif + return 0; } @@ -478,22 +532,6 @@ int board_late_init(void) { struct src *src = (struct src *)SRC_BASE_ADDR; - /* Default memory arguments */ - if (!getenv("memargs")) { - switch (gd->ram_size) { - case 0x08000000: - /* 128 MB */ - setenv("memargs", "mem=128M"); - break; - case 0x10000000: - /* 256 MB */ - setenv("memargs", "mem=256M"); - break; - default: - printf("Failed detecting RAM size.\n"); - } - } - if (((src->sbmr2 & SRC_SBMR2_BMOD_MASK) >> SRC_SBMR2_BMOD_SHIFT) == SRC_SBMR2_BMOD_SERIAL) { printf("Serial Downloader recovery mode, disable autoboot\n"); @@ -541,6 +579,7 @@ int checkboard(void) #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) int ft_board_setup(void *blob, bd_t *bd) { + int ret = 0; #ifdef CONFIG_FDT_FIXUP_PARTITIONS static struct node_info nodes[] = { { "fsl,vf610-nfc", MTD_DEV_TYPE_NAND, }, /* NAND flash */ @@ -550,6 +589,11 @@ int ft_board_setup(void *blob, bd_t *bd) puts(" Updating MTD partitions...\n"); fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); #endif +#ifdef CONFIG_VIDEO_FSL_DCU_FB + ret = fsl_dcu_fixedfb_setup(blob); + if (ret) + return ret; +#endif return ft_common_board_setup(blob, bd); } diff --git a/board/toradex/colibri_vf/dcu.c b/board/toradex/colibri_vf/dcu.c new file mode 100644 index 0000000..3fa6a76 --- /dev/null +++ b/board/toradex/colibri_vf/dcu.c @@ -0,0 +1,38 @@ +/* + * Copyright 2017 Toradex AG + * + * FSL DCU platform driver + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include "div64.h" + +DECLARE_GLOBAL_DATA_PTR; + +unsigned int dcu_set_pixel_clock(unsigned int pixclock) +{ + struct ccm_reg *ccm = (struct ccm_reg *)CCM_BASE_ADDR; + unsigned long long div; + + clrbits_le32(&ccm->cscmr1, CCM_CSCMR1_DCU0_CLK_SEL); + clrsetbits_le32(&ccm->cscdr3, + CCM_CSCDR3_DCU0_DIV_MASK | CCM_CSCDR3_DCU0_EN, + CCM_CSCDR3_DCU0_DIV(0) | CCM_CSCDR3_DCU0_EN); + div = (unsigned long long)(PLL1_PFD2_FREQ / 1000); + do_div(div, pixclock); + + return div; +} + +int platform_dcu_init(unsigned int xres, unsigned int yres, + const char *port, + struct fb_videomode *dcu_fb_videomode) +{ + fsl_dcu_init(xres, yres, 32); + + return 0; +} diff --git a/configs/colibri_vf_defconfig b/configs/colibri_vf_defconfig index 0474abc..1f0f929 100644 --- a/configs/colibri_vf_defconfig +++ b/configs/colibri_vf_defconfig @@ -52,3 +52,7 @@ CONFIG_G_DNL_MANUFACTURER="Toradex" CONFIG_G_DNL_VENDOR_NUM=0x1b67 CONFIG_G_DNL_PRODUCT_NUM=0x4000 CONFIG_OF_LIBFDT_OVERLAY=y +CONFIG_VIDEO=y +CONFIG_VIDEO_FSL_DCU_FB=y +CONFIG_SYS_CONSOLE_FG_COL=0x00 +CONFIG_SYS_CONSOLE_BG_COL=0x00 diff --git a/configs/ls1021aqds_ddr4_nor_defconfig b/configs/ls1021aqds_ddr4_nor_defconfig index 8434870..5566053 100644 --- a/configs/ls1021aqds_ddr4_nor_defconfig +++ b/configs/ls1021aqds_ddr4_nor_defconfig @@ -43,3 +43,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021aqds_ddr4_nor_lpuart_defconfig b/configs/ls1021aqds_ddr4_nor_lpuart_defconfig index ece220b..9582662 100644 --- a/configs/ls1021aqds_ddr4_nor_lpuart_defconfig +++ b/configs/ls1021aqds_ddr4_nor_lpuart_defconfig @@ -44,3 +44,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021aqds_nand_defconfig b/configs/ls1021aqds_nand_defconfig index dc547b5..73f2fb0 100644 --- a/configs/ls1021aqds_nand_defconfig +++ b/configs/ls1021aqds_nand_defconfig @@ -57,3 +57,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021aqds_nor_SECURE_BOOT_defconfig b/configs/ls1021aqds_nor_SECURE_BOOT_defconfig index d1760ed..74e1241 100644 --- a/configs/ls1021aqds_nor_SECURE_BOOT_defconfig +++ b/configs/ls1021aqds_nor_SECURE_BOOT_defconfig @@ -43,5 +43,6 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y CONFIG_RSA=y CONFIG_SPL_RSA=y diff --git a/configs/ls1021aqds_nor_defconfig b/configs/ls1021aqds_nor_defconfig index 8de90b0..14a2b7f 100644 --- a/configs/ls1021aqds_nor_defconfig +++ b/configs/ls1021aqds_nor_defconfig @@ -44,3 +44,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021aqds_nor_lpuart_defconfig b/configs/ls1021aqds_nor_lpuart_defconfig index a9efdc5..9ed301c 100644 --- a/configs/ls1021aqds_nor_lpuart_defconfig +++ b/configs/ls1021aqds_nor_lpuart_defconfig @@ -45,3 +45,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021aqds_qspi_defconfig b/configs/ls1021aqds_qspi_defconfig index 735f517..9ec21c5 100644 --- a/configs/ls1021aqds_qspi_defconfig +++ b/configs/ls1021aqds_qspi_defconfig @@ -50,3 +50,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021aqds_sdcard_ifc_defconfig b/configs/ls1021aqds_sdcard_ifc_defconfig index 027d368..492676a 100644 --- a/configs/ls1021aqds_sdcard_ifc_defconfig +++ b/configs/ls1021aqds_sdcard_ifc_defconfig @@ -55,3 +55,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021aqds_sdcard_qspi_defconfig b/configs/ls1021aqds_sdcard_qspi_defconfig index f9ea99b..ed0b17b 100644 --- a/configs/ls1021aqds_sdcard_qspi_defconfig +++ b/configs/ls1021aqds_sdcard_qspi_defconfig @@ -61,3 +61,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021atwr_nor_SECURE_BOOT_defconfig b/configs/ls1021atwr_nor_SECURE_BOOT_defconfig index 5b6ca22..6af8dbd 100644 --- a/configs/ls1021atwr_nor_SECURE_BOOT_defconfig +++ b/configs/ls1021atwr_nor_SECURE_BOOT_defconfig @@ -42,5 +42,6 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y CONFIG_RSA=y CONFIG_SPL_RSA=y diff --git a/configs/ls1021atwr_nor_defconfig b/configs/ls1021atwr_nor_defconfig index 3fb507f..93b6467 100644 --- a/configs/ls1021atwr_nor_defconfig +++ b/configs/ls1021atwr_nor_defconfig @@ -42,3 +42,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021atwr_nor_lpuart_defconfig b/configs/ls1021atwr_nor_lpuart_defconfig index 725720d..c176e83 100644 --- a/configs/ls1021atwr_nor_lpuart_defconfig +++ b/configs/ls1021atwr_nor_lpuart_defconfig @@ -43,3 +43,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021atwr_qspi_defconfig b/configs/ls1021atwr_qspi_defconfig index 46f7e26..548d574 100644 --- a/configs/ls1021atwr_qspi_defconfig +++ b/configs/ls1021atwr_qspi_defconfig @@ -50,3 +50,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021atwr_sdcard_ifc_SECURE_BOOT_defconfig b/configs/ls1021atwr_sdcard_ifc_SECURE_BOOT_defconfig index 783787a..bd00170 100644 --- a/configs/ls1021atwr_sdcard_ifc_SECURE_BOOT_defconfig +++ b/configs/ls1021atwr_sdcard_ifc_SECURE_BOOT_defconfig @@ -57,5 +57,6 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y CONFIG_RSA=y CONFIG_SPL_RSA=y diff --git a/configs/ls1021atwr_sdcard_ifc_defconfig b/configs/ls1021atwr_sdcard_ifc_defconfig index b558e83..1070111 100644 --- a/configs/ls1021atwr_sdcard_ifc_defconfig +++ b/configs/ls1021atwr_sdcard_ifc_defconfig @@ -54,3 +54,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/configs/ls1021atwr_sdcard_qspi_defconfig b/configs/ls1021atwr_sdcard_qspi_defconfig index ef07375..5eddabd 100644 --- a/configs/ls1021atwr_sdcard_qspi_defconfig +++ b/configs/ls1021atwr_sdcard_qspi_defconfig @@ -61,3 +61,4 @@ CONFIG_USB_XHCI_HCD=y CONFIG_USB_XHCI_DWC3=y CONFIG_USB_STORAGE=y # CONFIG_VIDEO_SW_CURSOR is not set +CONFIG_VIDEO_FSL_DCU_FB=y diff --git a/doc/device-tree-bindings/video/atmel-hlcdc.txt b/doc/device-tree-bindings/video/atmel-hlcdc.txt new file mode 100644 index 0000000..b378cbf --- /dev/null +++ b/doc/device-tree-bindings/video/atmel-hlcdc.txt @@ -0,0 +1,42 @@ +Atmel HLCDC Framebuffer +----------------------------------------------------- +Required properties: +- compatible : + "atmel,sama5d2-hlcdc", "atmel,at91sam9x5-hlcdc". +- reg: physical base address of the controller and length of memory mapped + region. +- clocks: phandles to input clocks. +- atmel,vl-bpix: Bits per pixel. +- atmel,output-mode: LCD Controller Output Mode, + The unit is bits per pixel, there are four values, + <12>, <16>, <18>, <24>, the default value is <24>. +- atmel,guard-time: lcd guard time (Delay in frame periods). +- display-timings: please refer the displaymode.txt. + +Example: +hlcdc: hlcdc@f0000000 { + u-boot,dm-pre-reloc; + compatible = "atmel,sama5d2-hlcdc"; + reg = <0xf0000000 0x2000>; + clocks = <&lcdc_clk>; + atmel,vl-bpix = <4>; + atmel,output-mode = <24>; + atmel,guard-time = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_lcd_base &pinctrl_lcd_pwm &pinctrl_lcd_rgb666>; + status = "okay"; + + display-timings { + 480x272 { + clock-frequency = <9000000>; + hactive = <480>; + vactive = <272>; + hsync-len = <41>; + hfront-porch = <2>; + hback-porch = <2>; + vfront-porch = <2>; + vback-porch = <2>; + vsync-len = <11>; + }; + }; +}; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 2069576..19e9745 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -371,6 +371,12 @@ config DISPLAY The devices provide a simple interface to start up the display, read display information and enable it. +config ATMEL_HLCD + bool "Enable ATMEL video support using HLCDC" + depends on DM_VIDEO + help + HLCDC supports video output to an attached LCD panel. + config VIDEO_BROADWELL_IGD bool "Enable Intel Broadwell integrated graphics device" depends on X86 @@ -395,6 +401,21 @@ config VIDEO_IVYBRIDGE_IGD a special tool which configures the VGA ROM, but the graphics resolution can be selected in U-Boot. +config VIDEO_FSL_DCU_FB + bool "Enable Freescale Display Control Unit" + depends on VIDEO + help + This enables support for Freescale Display Control Unit (DCU4) + module found on Freescale Vybrid and QorIQ family of SoCs. + +config VIDEO_FSL_DCU_MAX_FB_SIZE_MB + int "Freescale DCU framebuffer size" + depends on VIDEO_FSL_DCU_FB + default 4194304 + help + Set maximum framebuffer size to be used for Freescale Display + Controller Unit (DCU4). + config VIDEO_ROCKCHIP bool "Enable Rockchip video support" depends on DM_VIDEO diff --git a/drivers/video/Makefile b/drivers/video/Makefile index db34904..7cd6d28 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -27,7 +27,7 @@ obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o obj-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o obj-$(CONFIG_CFB_CONSOLE) += cfb_console.o obj-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o -obj-$(CONFIG_FSL_DCU_FB) += fsl_dcu_fb.o videomodes.o +obj-$(CONFIG_VIDEO_FSL_DCU_FB) += fsl_dcu_fb.o videomodes.o obj-$(CONFIG_L5F31188) += l5f31188.o obj-$(CONFIG_MPC8XX_LCD) += mpc8xx_lcd.o obj-$(CONFIG_PXA_LCD) += pxa_lcd.o diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c index 960b474..59b9c45 100644 --- a/drivers/video/atmel_hlcdfb.c +++ b/drivers/video/atmel_hlcdfb.c @@ -10,13 +10,22 @@ #include #include #include +#include +#include +#include #include +#include +#include #include #if defined(CONFIG_LCD_LOGO) #include #endif +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_DM_VIDEO + /* configurable parameters */ #define ATMEL_LCDC_CVAL_DEFAULT 0xc8 #define ATMEL_LCDC_DMA_BURST_LEN 8 @@ -26,19 +35,16 @@ #define ATMEL_LCDC_FIFO_SIZE 512 -#define lcdc_readl(reg) __raw_readl((reg)) -#define lcdc_writel(reg, val) __raw_writel((val), (reg)) - /* * the CLUT register map as following * RCLUT(24 ~ 16), GCLUT(15 ~ 8), BCLUT(7 ~ 0) */ void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) { - lcdc_writel(((red << LCDC_BASECLUT_RCLUT_Pos) & LCDC_BASECLUT_RCLUT_Msk) - | ((green << LCDC_BASECLUT_GCLUT_Pos) & LCDC_BASECLUT_GCLUT_Msk) - | ((blue << LCDC_BASECLUT_BCLUT_Pos) & LCDC_BASECLUT_BCLUT_Msk), - panel_info.mmio + ATMEL_LCDC_LUT(regno)); + writel(panel_info.mmio + ATMEL_LCDC_LUT(regno), + ((red << LCDC_BASECLUT_RCLUT_Pos) & LCDC_BASECLUT_RCLUT_Msk) + | ((green << LCDC_BASECLUT_GCLUT_Pos) & LCDC_BASECLUT_GCLUT_Msk) + | ((blue << LCDC_BASECLUT_BCLUT_Pos) & LCDC_BASECLUT_BCLUT_Msk)); } ushort *configuration_get_cmap(void) @@ -55,6 +61,7 @@ void lcd_ctrl_init(void *lcdbase) unsigned long value; struct lcd_dma_desc *desc; struct atmel_hlcd_regs *regs; + int ret; if (!has_lcdc()) return; /* No lcdc */ @@ -62,21 +69,29 @@ void lcd_ctrl_init(void *lcdbase) regs = (struct atmel_hlcd_regs *)panel_info.mmio; /* Disable DISP signal */ - lcdc_writel(®s->lcdc_lcddis, LCDC_LCDDIS_DISPDIS); - while ((lcdc_readl(®s->lcdc_lcdsr) & LCDC_LCDSR_DISPSTS)) - udelay(1); + writel(LCDC_LCDDIS_DISPDIS, ®s->lcdc_lcddis); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, + false, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable synchronization */ - lcdc_writel(®s->lcdc_lcddis, LCDC_LCDDIS_SYNCDIS); - while ((lcdc_readl(®s->lcdc_lcdsr) & LCDC_LCDSR_LCDSTS)) - udelay(1); + writel(LCDC_LCDDIS_SYNCDIS, ®s->lcdc_lcddis); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, + false, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable pixel clock */ - lcdc_writel(®s->lcdc_lcddis, LCDC_LCDDIS_CLKDIS); - while ((lcdc_readl(®s->lcdc_lcdsr) & LCDC_LCDSR_CLKSTS)) - udelay(1); + writel(LCDC_LCDDIS_CLKDIS, ®s->lcdc_lcddis); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, + false, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable PWM */ - lcdc_writel(®s->lcdc_lcddis, LCDC_LCDDIS_PWMDIS); - while ((lcdc_readl(®s->lcdc_lcdsr) & LCDC_LCDSR_PWMSTS)) - udelay(1); + writel(LCDC_LCDDIS_PWMDIS, ®s->lcdc_lcddis); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, + false, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Set pixel clock */ value = get_lcdc_clk_rate(0) / panel_info.vl_clk; @@ -85,23 +100,23 @@ void lcd_ctrl_init(void *lcdbase) if (value < 1) { /* Using system clock as pixel clock */ - lcdc_writel(®s->lcdc_lcdcfg0, - LCDC_LCDCFG0_CLKDIV(0) - | LCDC_LCDCFG0_CGDISHCR - | LCDC_LCDCFG0_CGDISHEO - | LCDC_LCDCFG0_CGDISOVR1 - | LCDC_LCDCFG0_CGDISBASE - | panel_info.vl_clk_pol - | LCDC_LCDCFG0_CLKSEL); + writel(LCDC_LCDCFG0_CLKDIV(0) + | LCDC_LCDCFG0_CGDISHCR + | LCDC_LCDCFG0_CGDISHEO + | LCDC_LCDCFG0_CGDISOVR1 + | LCDC_LCDCFG0_CGDISBASE + | panel_info.vl_clk_pol + | LCDC_LCDCFG0_CLKSEL, + ®s->lcdc_lcdcfg0); } else { - lcdc_writel(®s->lcdc_lcdcfg0, - LCDC_LCDCFG0_CLKDIV(value - 2) - | LCDC_LCDCFG0_CGDISHCR - | LCDC_LCDCFG0_CGDISHEO - | LCDC_LCDCFG0_CGDISOVR1 - | LCDC_LCDCFG0_CGDISBASE - | panel_info.vl_clk_pol); + writel(LCDC_LCDCFG0_CLKDIV(value - 2) + | LCDC_LCDCFG0_CGDISHCR + | LCDC_LCDCFG0_CGDISHEO + | LCDC_LCDCFG0_CGDISOVR1 + | LCDC_LCDCFG0_CGDISBASE + | panel_info.vl_clk_pol, + ®s->lcdc_lcdcfg0); } /* Initialize control register 5 */ @@ -134,50 +149,50 @@ void lcd_ctrl_init(void *lcdbase) value |= LCDC_LCDCFG5_GUARDTIME(ATMEL_LCDC_GUARD_TIME); value |= (LCDC_LCDCFG5_DISPDLY | LCDC_LCDCFG5_VSPDLYS); - lcdc_writel(®s->lcdc_lcdcfg5, value); + writel(value, ®s->lcdc_lcdcfg5); /* Vertical & Horizontal Timing */ value = LCDC_LCDCFG1_VSPW(panel_info.vl_vsync_len - 1); value |= LCDC_LCDCFG1_HSPW(panel_info.vl_hsync_len - 1); - lcdc_writel(®s->lcdc_lcdcfg1, value); + writel(value, ®s->lcdc_lcdcfg1); value = LCDC_LCDCFG2_VBPW(panel_info.vl_upper_margin); value |= LCDC_LCDCFG2_VFPW(panel_info.vl_lower_margin - 1); - lcdc_writel(®s->lcdc_lcdcfg2, value); + writel(value, ®s->lcdc_lcdcfg2); value = LCDC_LCDCFG3_HBPW(panel_info.vl_left_margin - 1); value |= LCDC_LCDCFG3_HFPW(panel_info.vl_right_margin - 1); - lcdc_writel(®s->lcdc_lcdcfg3, value); + writel(value, ®s->lcdc_lcdcfg3); /* Display size */ value = LCDC_LCDCFG4_RPF(panel_info.vl_row - 1); value |= LCDC_LCDCFG4_PPL(panel_info.vl_col - 1); - lcdc_writel(®s->lcdc_lcdcfg4, value); + writel(value, ®s->lcdc_lcdcfg4); - lcdc_writel(®s->lcdc_basecfg0, - LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO); + writel(LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO, + ®s->lcdc_basecfg0); switch (NBITS(panel_info.vl_bpix)) { case 16: - lcdc_writel(®s->lcdc_basecfg1, - LCDC_BASECFG1_RGBMODE_16BPP_RGB_565); + writel(LCDC_BASECFG1_RGBMODE_16BPP_RGB_565, + ®s->lcdc_basecfg1); break; case 32: - lcdc_writel(®s->lcdc_basecfg1, - LCDC_BASECFG1_RGBMODE_24BPP_RGB_888); + writel(LCDC_BASECFG1_RGBMODE_24BPP_RGB_888, + ®s->lcdc_basecfg1); break; default: BUG(); break; } - lcdc_writel(®s->lcdc_basecfg2, LCDC_BASECFG2_XSTRIDE(0)); - lcdc_writel(®s->lcdc_basecfg3, 0); - lcdc_writel(®s->lcdc_basecfg4, LCDC_BASECFG4_DMA); + writel(LCDC_BASECFG2_XSTRIDE(0), ®s->lcdc_basecfg2); + writel(0, ®s->lcdc_basecfg3); + writel(LCDC_BASECFG4_DMA, ®s->lcdc_basecfg4); /* Disable all interrupts */ - lcdc_writel(®s->lcdc_lcdidr, ~0UL); - lcdc_writel(®s->lcdc_baseidr, ~0UL); + writel(~0UL, ®s->lcdc_lcdidr); + writel(~0UL, ®s->lcdc_baseidr); /* Setup the DMA descriptor, this descriptor will loop to itself */ desc = (struct lcd_dma_desc *)(lcdbase - 16); @@ -191,30 +206,355 @@ void lcd_ctrl_init(void *lcdbase) /* Flush the DMA descriptor if we enabled dcache */ flush_dcache_range((u32)desc, (u32)desc + sizeof(*desc)); - lcdc_writel(®s->lcdc_baseaddr, desc->address); - lcdc_writel(®s->lcdc_basectrl, desc->control); - lcdc_writel(®s->lcdc_basenext, desc->next); - lcdc_writel(®s->lcdc_basecher, LCDC_BASECHER_CHEN | - LCDC_BASECHER_UPDATEEN); + writel(desc->address, ®s->lcdc_baseaddr); + writel(desc->control, ®s->lcdc_basectrl); + writel(desc->next, ®s->lcdc_basenext); + writel(LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN, + ®s->lcdc_basecher); /* Enable LCD */ - value = lcdc_readl(®s->lcdc_lcden); - lcdc_writel(®s->lcdc_lcden, value | LCDC_LCDEN_CLKEN); - while (!(lcdc_readl(®s->lcdc_lcdsr) & LCDC_LCDSR_CLKSTS)) - udelay(1); - value = lcdc_readl(®s->lcdc_lcden); - lcdc_writel(®s->lcdc_lcden, value | LCDC_LCDEN_SYNCEN); - while (!(lcdc_readl(®s->lcdc_lcdsr) & LCDC_LCDSR_LCDSTS)) - udelay(1); - value = lcdc_readl(®s->lcdc_lcden); - lcdc_writel(®s->lcdc_lcden, value | LCDC_LCDEN_DISPEN); - while (!(lcdc_readl(®s->lcdc_lcdsr) & LCDC_LCDSR_DISPSTS)) - udelay(1); - value = lcdc_readl(®s->lcdc_lcden); - lcdc_writel(®s->lcdc_lcden, value | LCDC_LCDEN_PWMEN); - while (!(lcdc_readl(®s->lcdc_lcdsr) & LCDC_LCDSR_PWMSTS)) - udelay(1); + value = readl(®s->lcdc_lcden); + writel(value | LCDC_LCDEN_CLKEN, ®s->lcdc_lcden); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, + true, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + value = readl(®s->lcdc_lcden); + writel(value | LCDC_LCDEN_SYNCEN, ®s->lcdc_lcden); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, + true, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + value = readl(®s->lcdc_lcden); + writel(value | LCDC_LCDEN_DISPEN, ®s->lcdc_lcden); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, + true, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + value = readl(®s->lcdc_lcden); + writel(value | LCDC_LCDEN_PWMEN, ®s->lcdc_lcden); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, + true, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Enable flushing if we enabled dcache */ lcd_set_flush_dcache(1); } + +#else + +enum { + LCD_MAX_WIDTH = 1024, + LCD_MAX_HEIGHT = 768, + LCD_MAX_LOG2_BPP = VIDEO_BPP16, +}; + +struct atmel_hlcdc_priv { + struct atmel_hlcd_regs *regs; + struct display_timing timing; + unsigned int vl_bpix; + unsigned int output_mode; + unsigned int guard_time; + ulong clk_rate; +}; + +static int at91_hlcdc_enable_clk(struct udevice *dev) +{ + struct atmel_hlcdc_priv *priv = dev_get_priv(dev); + struct clk clk; + ulong clk_rate; + int ret; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return -EINVAL; + + ret = clk_enable(&clk); + if (ret) + return ret; + + clk_rate = clk_get_rate(&clk); + if (!clk_rate) { + clk_disable(&clk); + return -ENODEV; + } + + priv->clk_rate = clk_rate; + + clk_free(&clk); + + return 0; +} + +static void atmel_hlcdc_init(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + struct atmel_hlcdc_priv *priv = dev_get_priv(dev); + struct atmel_hlcd_regs *regs = priv->regs; + struct display_timing *timing = &priv->timing; + struct lcd_dma_desc *desc; + unsigned long value, vl_clk_pol; + int ret; + + /* Disable DISP signal */ + writel(LCDC_LCDDIS_DISPDIS, ®s->lcdc_lcddis); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, + false, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + /* Disable synchronization */ + writel(LCDC_LCDDIS_SYNCDIS, ®s->lcdc_lcddis); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, + false, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + /* Disable pixel clock */ + writel(LCDC_LCDDIS_CLKDIS, ®s->lcdc_lcddis); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, + false, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + /* Disable PWM */ + writel(LCDC_LCDDIS_PWMDIS, ®s->lcdc_lcddis); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, + false, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + + /* Set pixel clock */ + value = priv->clk_rate / timing->pixelclock.typ; + if (priv->clk_rate % timing->pixelclock.typ) + value++; + + vl_clk_pol = 0; + if (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) + vl_clk_pol = LCDC_LCDCFG0_CLKPOL; + + if (value < 1) { + /* Using system clock as pixel clock */ + writel(LCDC_LCDCFG0_CLKDIV(0) + | LCDC_LCDCFG0_CGDISHCR + | LCDC_LCDCFG0_CGDISHEO + | LCDC_LCDCFG0_CGDISOVR1 + | LCDC_LCDCFG0_CGDISBASE + | vl_clk_pol + | LCDC_LCDCFG0_CLKSEL, + ®s->lcdc_lcdcfg0); + + } else { + writel(LCDC_LCDCFG0_CLKDIV(value - 2) + | LCDC_LCDCFG0_CGDISHCR + | LCDC_LCDCFG0_CGDISHEO + | LCDC_LCDCFG0_CGDISOVR1 + | LCDC_LCDCFG0_CGDISBASE + | vl_clk_pol, + ®s->lcdc_lcdcfg0); + } + + /* Initialize control register 5 */ + value = 0; + + if (!(timing->flags & DISPLAY_FLAGS_HSYNC_HIGH)) + value |= LCDC_LCDCFG5_HSPOL; + if (!(timing->flags & DISPLAY_FLAGS_VSYNC_HIGH)) + value |= LCDC_LCDCFG5_VSPOL; + + switch (priv->output_mode) { + case 12: + value |= LCDC_LCDCFG5_MODE_OUTPUT_12BPP; + break; + case 16: + value |= LCDC_LCDCFG5_MODE_OUTPUT_16BPP; + break; + case 18: + value |= LCDC_LCDCFG5_MODE_OUTPUT_18BPP; + break; + case 24: + value |= LCDC_LCDCFG5_MODE_OUTPUT_24BPP; + break; + default: + BUG(); + break; + } + + value |= LCDC_LCDCFG5_GUARDTIME(priv->guard_time); + value |= (LCDC_LCDCFG5_DISPDLY | LCDC_LCDCFG5_VSPDLYS); + writel(value, ®s->lcdc_lcdcfg5); + + /* Vertical & Horizontal Timing */ + value = LCDC_LCDCFG1_VSPW(timing->vsync_len.typ - 1); + value |= LCDC_LCDCFG1_HSPW(timing->hsync_len.typ - 1); + writel(value, ®s->lcdc_lcdcfg1); + + value = LCDC_LCDCFG2_VBPW(timing->vback_porch.typ); + value |= LCDC_LCDCFG2_VFPW(timing->vfront_porch.typ - 1); + writel(value, ®s->lcdc_lcdcfg2); + + value = LCDC_LCDCFG3_HBPW(timing->hback_porch.typ - 1); + value |= LCDC_LCDCFG3_HFPW(timing->hfront_porch.typ - 1); + writel(value, ®s->lcdc_lcdcfg3); + + /* Display size */ + value = LCDC_LCDCFG4_RPF(timing->vactive.typ - 1); + value |= LCDC_LCDCFG4_PPL(timing->hactive.typ - 1); + writel(value, ®s->lcdc_lcdcfg4); + + writel(LCDC_BASECFG0_BLEN_AHB_INCR4 | LCDC_BASECFG0_DLBO, + ®s->lcdc_basecfg0); + + switch (VNBITS(priv->vl_bpix)) { + case 16: + writel(LCDC_BASECFG1_RGBMODE_16BPP_RGB_565, + ®s->lcdc_basecfg1); + break; + case 32: + writel(LCDC_BASECFG1_RGBMODE_24BPP_RGB_888, + ®s->lcdc_basecfg1); + break; + default: + BUG(); + break; + } + + writel(LCDC_BASECFG2_XSTRIDE(0), ®s->lcdc_basecfg2); + writel(0, ®s->lcdc_basecfg3); + writel(LCDC_BASECFG4_DMA, ®s->lcdc_basecfg4); + + /* Disable all interrupts */ + writel(~0UL, ®s->lcdc_lcdidr); + writel(~0UL, ®s->lcdc_baseidr); + + /* Setup the DMA descriptor, this descriptor will loop to itself */ + desc = (struct lcd_dma_desc *)(uc_plat->base - 16); + + desc->address = (u32)uc_plat->base; + + /* Disable DMA transfer interrupt & descriptor loaded interrupt. */ + desc->control = LCDC_BASECTRL_ADDIEN | LCDC_BASECTRL_DSCRIEN + | LCDC_BASECTRL_DMAIEN | LCDC_BASECTRL_DFETCH; + desc->next = (u32)desc; + + /* Flush the DMA descriptor if we enabled dcache */ + flush_dcache_range((u32)desc, (u32)desc + sizeof(*desc)); + + writel(desc->address, ®s->lcdc_baseaddr); + writel(desc->control, ®s->lcdc_basectrl); + writel(desc->next, ®s->lcdc_basenext); + writel(LCDC_BASECHER_CHEN | LCDC_BASECHER_UPDATEEN, + ®s->lcdc_basecher); + + /* Enable LCD */ + value = readl(®s->lcdc_lcden); + writel(value | LCDC_LCDEN_CLKEN, ®s->lcdc_lcden); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, + true, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + value = readl(®s->lcdc_lcden); + writel(value | LCDC_LCDEN_SYNCEN, ®s->lcdc_lcden); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, + true, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + value = readl(®s->lcdc_lcden); + writel(value | LCDC_LCDEN_DISPEN, ®s->lcdc_lcden); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, + true, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); + value = readl(®s->lcdc_lcden); + writel(value | LCDC_LCDEN_PWMEN, ®s->lcdc_lcden); + ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, + true, 1000, false); + if (ret) + printf("%s: %d: Timeout!\n", __func__, __LINE__); +} + +static int atmel_hlcdc_probe(struct udevice *dev) +{ + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct atmel_hlcdc_priv *priv = dev_get_priv(dev); + int ret; + + ret = at91_hlcdc_enable_clk(dev); + if (ret) + return ret; + + atmel_hlcdc_init(dev); + + uc_priv->xsize = priv->timing.hactive.typ; + uc_priv->ysize = priv->timing.vactive.typ; + uc_priv->bpix = priv->vl_bpix; + + /* Enable flushing if we enabled dcache */ + video_set_flush_dcache(dev, true); + + return 0; +} + +static int atmel_hlcdc_ofdata_to_platdata(struct udevice *dev) +{ + struct atmel_hlcdc_priv *priv = dev_get_priv(dev); + const void *blob = gd->fdt_blob; + int node = dev->of_offset; + + priv->regs = (struct atmel_hlcd_regs *)dev_get_addr(dev); + if (!priv->regs) { + debug("%s: No display controller address\n", __func__); + return -EINVAL; + } + + if (fdtdec_decode_display_timing(blob, dev->of_offset, + 0, &priv->timing)) { + debug("%s: Failed to decode display timing\n", __func__); + return -EINVAL; + } + + if (priv->timing.hactive.typ > LCD_MAX_WIDTH) + priv->timing.hactive.typ = LCD_MAX_WIDTH; + + if (priv->timing.vactive.typ > LCD_MAX_HEIGHT) + priv->timing.vactive.typ = LCD_MAX_HEIGHT; + + priv->vl_bpix = fdtdec_get_int(blob, node, "atmel,vl-bpix", 0); + if (!priv->vl_bpix) { + debug("%s: Failed to get bits per pixel\n", __func__); + return -EINVAL; + } + + priv->output_mode = fdtdec_get_int(blob, node, "atmel,output-mode", 24); + priv->guard_time = fdtdec_get_int(blob, node, "atmel,guard-time", 1); + + return 0; +} + +static int atmel_hlcdc_bind(struct udevice *dev) +{ + struct video_uc_platdata *uc_plat = dev_get_uclass_platdata(dev); + + uc_plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * + (1 << LCD_MAX_LOG2_BPP) / 8; + + debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); + + return 0; +} + +static const struct udevice_id atmel_hlcdc_ids[] = { + { .compatible = "atmel,sama5d2-hlcdc" }, + { .compatible = "atmel,at91sam9x5-hlcdc" }, + { } +}; + +U_BOOT_DRIVER(atmel_hlcdfb) = { + .name = "atmel_hlcdfb", + .id = UCLASS_VIDEO, + .of_match = atmel_hlcdc_ids, + .bind = atmel_hlcdc_bind, + .probe = atmel_hlcdc_probe, + .ofdata_to_platdata = atmel_hlcdc_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct atmel_hlcdc_priv), +}; + +#endif diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index 89a55dd..b627d48 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -18,7 +18,7 @@ static int console_normal_set_row(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); void *line; - int pixels = VIDEO_FONT_HEIGHT * vid_priv->line_length; + int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize; int i; line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * vid_priv->line_length; diff --git a/drivers/video/fsl_dcu_fb.c b/drivers/video/fsl_dcu_fb.c index d4cd382..01e4a40 100644 --- a/drivers/video/fsl_dcu_fb.c +++ b/drivers/video/fsl_dcu_fb.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,7 @@ #define DCU_VSYN_PARA_BP(x) ((x) << 22) #define DCU_VSYN_PARA_PW(x) ((x) << 11) #define DCU_VSYN_PARA_FP(x) (x) -#define DCU_SYN_POL_INV_PXCK_FALL (0 << 6) +#define DCU_SYN_POL_INV_PXCK_FALL (1 << 6) #define DCU_SYN_POL_NEG_REMAIN (0 << 5) #define DCU_SYN_POL_INV_VS_LOW (1 << 1) #define DCU_SYN_POL_INV_HS_LOW (1) @@ -79,6 +80,8 @@ #define BPP_24_RGB888 5 #define BPP_32_ARGB8888 6 +DECLARE_GLOBAL_DATA_PTR; + /* * This setting is used for the TWR_LCD_RGB card */ @@ -101,7 +104,7 @@ static struct fb_videomode fsl_dcu_mode_480_272 = { /* * This setting is used for Siliconimage SiI9022A HDMI */ -static struct fb_videomode fsl_dcu_mode_640_480 = { +static struct fb_videomode fsl_dcu_cea_mode_640_480 = { .name = "640x480-60", .refresh = 60, .xres = 640, @@ -117,6 +120,54 @@ static struct fb_videomode fsl_dcu_mode_640_480 = { .vmode = FB_VMODE_NONINTERLACED, }; +static struct fb_videomode fsl_dcu_mode_640_480 = { + .name = "640x480-60", + .refresh = 60, + .xres = 640, + .yres = 480, + .pixclock = 25175, + .left_margin = 40, + .right_margin = 24, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 96, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_videomode fsl_dcu_mode_800_480 = { + .name = "800x480-60", + .refresh = 60, + .xres = 800, + .yres = 480, + .pixclock = 33260, + .left_margin = 216, + .right_margin = 40, + .upper_margin = 35, + .lower_margin = 10, + .hsync_len = 128, + .vsync_len = 2, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_videomode fsl_dcu_mode_1024_600 = { + .name = "1024x600-60", + .refresh = 60, + .xres = 1024, + .yres = 600, + .pixclock = 48000, + .left_margin = 104, + .right_margin = 43, + .upper_margin = 24, + .lower_margin = 20, + .hsync_len = 5, + .vsync_len = 5, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, +}; + /* * DCU register map */ @@ -188,8 +239,6 @@ static void reset_total_layers(void) dcu_write32(®s->ctrldescl[i][9], 0); dcu_write32(®s->ctrldescl[i][10], 0); } - - dcu_write32(®s->update_mode, DCU_UPDATE_MODE_READREG); } static int layer_ctrldesc_init(int index, u32 pixel_format) @@ -243,8 +292,6 @@ static int layer_ctrldesc_init(int index, u32 pixel_format) dcu_write32(®s->ctrldescl[index][7], DCU_CTRLDESCLN_8_FG_FCOLOR(0)); dcu_write32(®s->ctrldescl[index][8], DCU_CTRLDESCLN_9_BG_BCOLOR(0)); - dcu_write32(®s->update_mode, DCU_UPDATE_MODE_READREG); - return 0; } @@ -254,16 +301,22 @@ int fsl_dcu_init(unsigned int xres, unsigned int yres, struct dcu_reg *regs = (struct dcu_reg *)CONFIG_SYS_DCU_ADDR; unsigned int div, mode; - /* Memory allocation for framebuffer */ info.screen_size = info.var.xres * info.var.yres * (info.var.bits_per_pixel / 8); - info.screen_base = (char *)memalign(ARCH_DMA_MINALIGN, - roundup(info.screen_size, ARCH_DMA_MINALIGN)); + + if (info.screen_size > CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB) { + info.screen_size = 0; + return -ENOMEM; + } + + /* Reserve framebuffer at the end of memory */ + gd->fb_base = gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size - info.screen_size; + info.screen_base = (char *)gd->fb_base; + memset(info.screen_base, 0, info.screen_size); reset_total_layers(); - div = dcu_set_pixel_clock(info.var.pixclock); - dcu_write32(®s->div_ratio, (div - 1)); dcu_write32(®s->disp_size, DCU_DISP_SIZE_DELTA_Y(info.var.yres) | @@ -289,7 +342,7 @@ int fsl_dcu_init(unsigned int xres, unsigned int yres, DCU_BGND_R(0) | DCU_BGND_G(0) | DCU_BGND_B(0)); dcu_write32(®s->mode, - DCU_MODE_BLEND_ITER(DCU_LAYER_MAX_NUM) | + DCU_MODE_BLEND_ITER(2) | DCU_MODE_RASTER_EN); dcu_write32(®s->threshold, @@ -302,9 +355,19 @@ int fsl_dcu_init(unsigned int xres, unsigned int yres, layer_ctrldesc_init(0, pixel_format); + div = dcu_set_pixel_clock(info.var.pixclock); + dcu_write32(®s->div_ratio, (div - 1)); + + dcu_write32(®s->update_mode, DCU_UPDATE_MODE_READREG); + return 0; } +ulong board_get_usable_ram_top(ulong total_size) +{ + return gd->ram_top - CONFIG_VIDEO_FSL_DCU_MAX_FB_SIZE_MB; +} + void *video_hw_init(void) { static GraphicDevice ctfb; @@ -327,7 +390,16 @@ void *video_hw_init(void) fsl_dcu_mode_db = &fsl_dcu_mode_480_272; break; case RESOLUTION(640, 480): - fsl_dcu_mode_db = &fsl_dcu_mode_640_480; + if (!strncmp(options, "monitor=hdmi", 12)) + fsl_dcu_mode_db = &fsl_dcu_cea_mode_640_480; + else + fsl_dcu_mode_db = &fsl_dcu_mode_640_480; + break; + case RESOLUTION(800, 480): + fsl_dcu_mode_db = &fsl_dcu_mode_800_480; + break; + case RESOLUTION(1024, 600): + fsl_dcu_mode_db = &fsl_dcu_mode_1024_600; break; default: printf("unsupported resolution %ux%u\n", @@ -363,3 +435,26 @@ void *video_hw_init(void) return &ctfb; } + +#if defined(CONFIG_OF_BOARD_SETUP) +int fsl_dcu_fixedfb_setup(void *blob) +{ + u64 start, size; + int ret; + + start = gd->bd->bi_dram[0].start; + size = gd->bd->bi_dram[0].size - info.screen_size; + + /* + * Align size on section size (1 MiB). + */ + size &= 0xfff00000; + ret = fdt_fixup_memory_banks(blob, &start, &size, 1); + if (ret) { + eprintf("Cannot setup fb: Error reserving memory\n"); + return ret; + } + + return 0; +} +#endif diff --git a/include/configs/colibri_vf.h b/include/configs/colibri_vf.h index 73b43bd..5dc5ed0 100644 --- a/include/configs/colibri_vf.h +++ b/include/configs/colibri_vf.h @@ -25,6 +25,17 @@ #define CONFIG_MXC_OCOTP #endif +#ifdef CONFIG_VIDEO_FSL_DCU_FB +#define CONFIG_CMD_BMP +#define CONFIG_SPLASH_SCREEN_ALIGN +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_BMP_LOGO +#define CONFIG_SYS_FSL_DCU_LE + +#define CONFIG_SYS_DCU_ADDR DCU0_BASE_ADDR +#define DCU_LAYER_MAX_NUM 64 +#endif + /* Size of malloc() pool */ #define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2 * 1024 * 1024) @@ -130,6 +141,8 @@ "setupdate=run setsdupdate || run setusbupdate\0" \ "mtdparts=" MTDPARTS_DEFAULT "\0" \ "dfu_alt_info=" DFU_ALT_NAND_INFO "\0" \ + "video-mode=dcufb:640x480-16@60,monitor=lcd\0" \ + "splashpos=m,m\0" \ SD_BOOTCMD \ NFS_BOOTCMD \ UBI_BOOTCMD diff --git a/include/configs/ls1021aqds.h b/include/configs/ls1021aqds.h index b349b36..97b8127 100644 --- a/include/configs/ls1021aqds.h +++ b/include/configs/ls1021aqds.h @@ -421,9 +421,7 @@ unsigned long get_board_ddr_clk(void); /* * Video */ -#define CONFIG_FSL_DCU_FB - -#ifdef CONFIG_FSL_DCU_FB +#ifdef CONFIG_VIDEO_FSL_DCU_FB #define CONFIG_CMD_BMP #define CONFIG_VIDEO_LOGO #define CONFIG_VIDEO_BMP_LOGO diff --git a/include/configs/ls1021atwr.h b/include/configs/ls1021atwr.h index fcf035b..a60b4b2 100644 --- a/include/configs/ls1021atwr.h +++ b/include/configs/ls1021atwr.h @@ -300,9 +300,7 @@ /* * Video */ -#define CONFIG_FSL_DCU_FB - -#ifdef CONFIG_FSL_DCU_FB +#ifdef CONFIG_VIDEO_FSL_DCU_FB #define CONFIG_CMD_BMP #define CONFIG_VIDEO_LOGO #define CONFIG_VIDEO_BMP_LOGO diff --git a/include/fsl_dcu_fb.h b/include/fsl_dcu_fb.h index 4263298..67e29e7 100644 --- a/include/fsl_dcu_fb.h +++ b/include/fsl_dcu_fb.h @@ -9,6 +9,7 @@ int fsl_dcu_init(unsigned int xres, unsigned int yres, unsigned int pixel_format); +int fsl_dcu_fixedfb_setup(void *blob); /* Prototypes for external board-specific functions */ int platform_dcu_init(unsigned int xres, unsigned int yres, diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 7bc5169..d487be7 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1041,7 +1041,6 @@ CONFIG_FSLDMAFEC CONFIG_FSL_CADMUS CONFIG_FSL_CORENET CONFIG_FSL_CPLD -CONFIG_FSL_DCU_FB CONFIG_FSL_DCU_SII9022A CONFIG_FSL_DDR_BIST CONFIG_FSL_DDR_FIRST_SLOT_QUAD_CAPABLE