[U-Boot] [PATCH 1/3] video: Update MXS LCDIF driver for mx6sx

Add a new interface "mxs_lcd_panel_setup" to setup fb parameters and specifies the LCDIF controller for multiple controllers of iMX6SX. Pass fb parameters via "videomode" env remains work if the new interface is not called before video initialization.
Modify LCDIF clock interface "mxs_set_lcdclk" to support multiple LCDIF controllers on iMX6SX.
Signed-off-by: Ye.Li B37916@freescale.com --- arch/arm/cpu/arm926ejs/mxs/clock.c | 4 +- arch/arm/include/asm/arch-mxs/clock.h | 2 +- drivers/video/mxsfb.c | 57 +++++++++++++++++++++++++++------ include/mxsfb.h | 15 +++++++++ 4 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 include/mxsfb.h
diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c b/arch/arm/cpu/arm926ejs/mxs/clock.c index e9d8800..ca020ca 100644 --- a/arch/arm/cpu/arm926ejs/mxs/clock.c +++ b/arch/arm/cpu/arm926ejs/mxs/clock.c @@ -5,7 +5,7 @@ * on behalf of DENX Software Engineering GmbH * * Based on code from LTIB: - * Copyright (C) 2010 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. * * SPDX-License-Identifier: GPL-2.0+ */ @@ -309,7 +309,7 @@ void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq) bus, tgtclk, freq); }
-void mxs_set_lcdclk(uint32_t freq) +void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq) { struct mxs_clkctrl_regs *clkctrl_regs = (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; diff --git a/arch/arm/include/asm/arch-mxs/clock.h b/arch/arm/include/asm/arch-mxs/clock.h index fc9d75b..8840335 100644 --- a/arch/arm/include/asm/arch-mxs/clock.h +++ b/arch/arm/include/asm/arch-mxs/clock.h @@ -46,7 +46,7 @@ uint32_t mxc_get_clock(enum mxc_clock clk); void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq); void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal); void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq); -void mxs_set_lcdclk(uint32_t freq); +void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq);
/* Compatibility with the FEC Ethernet driver */ #define imx_get_fecclk() mxc_get_clock(MXC_AHB_CLK) diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 03b0f88..2653862 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -18,6 +18,10 @@ #include <asm/imx-common/dma.h>
#include "videomodes.h" +#include <linux/string.h> +#include <linux/list.h> +#include <linux/fb.h> +
#define PS2KHZ(ps) (1000000000UL / (ps))
@@ -35,6 +39,22 @@ __weak void mxsfb_system_setup(void) { }
+static int setup; +static struct fb_videomode fbmode; +static int depth; + +int mxs_lcd_panel_setup(struct fb_videomode mode, int bpp, + uint32_t base_addr) +{ + fbmode = mode; + depth = bpp; + panel.isaBase = base_addr; + + setup = 1; + + return 0; +} + /* * DENX M28EVK: * setenv videomode @@ -50,15 +70,15 @@ __weak void mxsfb_system_setup(void) static void mxs_lcd_init(GraphicDevice *panel, struct ctfb_res_modes *mode, int bpp) { - struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE; + struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(panel->isaBase); uint32_t word_len = 0, bus_width = 0; uint8_t valid_data = 0;
/* Kick in the LCDIF clock */ - mxs_set_lcdclk(PS2KHZ(mode->pixclock)); + mxs_set_lcdclk(panel->isaBase, PS2KHZ(mode->pixclock));
/* Restart the LCDIF block */ - mxs_reset_block(®s->hw_lcdif_ctrl_reg); + mxs_reset_block((struct mxs_register_32 *)®s->hw_lcdif_ctrl);
switch (bpp) { case 24: @@ -140,15 +160,32 @@ void *video_hw_init(void)
puts("Video: ");
- /* Suck display configuration from "videomode" variable */ - penv = getenv("videomode"); - if (!penv) { - puts("MXSFB: 'videomode' variable not set!\n"); - return NULL; + if (!setup) { + + /* Suck display configuration from "videomode" variable */ + penv = getenv("videomode"); + if (!penv) { + printf("MXSFB: 'videomode' variable not set!\n"); + return NULL; + } + + bpp = video_get_params(&mode, penv); + panel.isaBase = MXS_LCDIF_BASE; + } else { + mode.xres = fbmode.xres; + mode.yres = fbmode.yres; + mode.pixclock = fbmode.pixclock; + mode.left_margin = fbmode.left_margin; + mode.right_margin = fbmode.right_margin; + mode.upper_margin = fbmode.upper_margin; + mode.lower_margin = fbmode.lower_margin; + mode.hsync_len = fbmode.hsync_len; + mode.vsync_len = fbmode.vsync_len; + mode.sync = fbmode.sync; + mode.vmode = fbmode.vmode; + bpp = depth; }
- bpp = video_get_params(&mode, penv); - /* fill in Graphic device struct */ sprintf(panel.modeIdent, "%dx%dx%d", mode.xres, mode.yres, bpp); diff --git a/include/mxsfb.h b/include/mxsfb.h new file mode 100644 index 0000000..a4e27a8 --- /dev/null +++ b/include/mxsfb.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __MXSFB_H__ +#define __MXSFB_H__ + +#ifdef CONFIG_VIDEO_MXS +int mxs_lcd_panel_setup(struct fb_videomode mode, int bpp, + uint32_t base_addr); +#endif + +#endif /* __MXSFB_H__ */

Add clock functions and relevant registers to enable/set LCDIF clock and LVDS clock.
Signed-off-by: Ye.Li B37916@freescale.com --- arch/arm/cpu/armv7/mx6/clock.c | 238 +++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 5 + arch/arm/include/asm/arch-mx6/crm_regs.h | 53 ++++++- arch/arm/include/asm/arch-mx6/imx-regs.h | 242 ++++++++++++++++++++++++++++++ 4 files changed, 533 insertions(+), 5 deletions(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index b6983e6..24b9b95 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -545,6 +545,244 @@ u32 imx_get_fecclk(void) return mxc_get_clock(MXC_IPG_CLK); }
+#ifdef CONFIG_MX6SX +static void enable_lcdif_clock(uint32_t base_addr) +{ + u32 reg = 0; + + /* Enable the LCDIF pix clock, axi clock, disp axi clock */ + reg = readl(&imx_ccm->CCGR3); + if (base_addr == LCDIF1_BASE_ADDR) + reg |= (MXC_CCM_CCGR3_LCDIF1_PIX_MASK | MXC_CCM_CCGR3_DISP_AXI_MASK); + else + reg |= (MXC_CCM_CCGR3_LCDIF2_PIX_MASK | MXC_CCM_CCGR3_DISP_AXI_MASK); + writel(reg, &imx_ccm->CCGR3); + + reg = readl(&imx_ccm->CCGR2); + reg |= (MXC_CCM_CCGR2_LCD_MASK); + writel(reg, &imx_ccm->CCGR2); +} + +static void disable_lcdif_clock(uint32_t base_addr) +{ + u32 reg = 0; + + /* Disable the LCDIF pix clock, axi clock, disp axi clock */ + reg = readl(&imx_ccm->CCGR3); + if (base_addr == LCDIF1_BASE_ADDR) + reg &= ~(MXC_CCM_CCGR3_LCDIF1_PIX_MASK | MXC_CCM_CCGR3_DISP_AXI_MASK); + else + reg &= ~(MXC_CCM_CCGR3_LCDIF2_PIX_MASK | MXC_CCM_CCGR3_DISP_AXI_MASK); + writel(reg, &imx_ccm->CCGR3); + + reg = readl(&imx_ccm->CCGR2); + reg &= ~(MXC_CCM_CCGR2_LCD_MASK); + writel(reg, &imx_ccm->CCGR2); +} + + +void setup_lvds_clock(uint32_t lcdif_base) +{ + u32 reg = 0; + struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR; + + disable_lcdif_clock(lcdif_base); + + /* Turn off LDB DI0 clocks */ + reg = readl(&imx_ccm->CCGR3); + reg &= ~MXC_CCM_CCGR3_LDB_DI0_MASK; + writel(reg, &imx_ccm->CCGR3); + + /* set LDB DI0 clk select to 011 PLL2 PFD3 200M*/ + reg = readl(&imx_ccm->cs2cdr); + reg &= ~MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK; + reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET); + writel(reg, &imx_ccm->cs2cdr); + + reg = readl(&imx_ccm->cscmr2); + reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV; + writel(reg, &imx_ccm->cscmr2); + + /* set LDB DI0 clock for LCDIF PIX clock */ + reg = readl(&imx_ccm->cscdr2); + if (lcdif_base == LCDIF1_BASE_ADDR) { + reg &= ~MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK; + reg |= (0x3 << MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_OFFSET); + } else { + reg &= ~MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK; + reg |= (0x3 << MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_OFFSET); + } + writel(reg, &imx_ccm->cscdr2); + + reg = IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW + | IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG + | IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT + | IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0; + writel(reg, &iomux->gpr[6]); + + reg = readl(&iomux->gpr[5]); + if (lcdif_base == LCDIF1_BASE_ADDR) + reg &= ~0x8; /* MUX LVDS to LCDIF1 */ + else + reg |= 0x8; /* MUX LVDS to LCDIF2 */ + writel(reg, &iomux->gpr[5]); + + /* Turn on LDB DI0 clocks */ + reg = readl(&imx_ccm->CCGR3); + reg |= MXC_CCM_CCGR3_LDB_DI0_MASK; + writel(reg, &imx_ccm->CCGR3); + + enable_lcdif_clock(lcdif_base); +} + +void setup_lcdif_clock(uint32_t base_addr) +{ + u32 reg = 0; + + /* Disable the lcdif clocks, the driver will enable the lcdif clock */ + disable_lcdif_clock(base_addr); + + /* Set to pre-mux clock at default */ + reg = readl(&imx_ccm->cscdr2); + if (base_addr == LCDIF1_BASE_ADDR) + reg &= ~MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK; + else + reg &= ~MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK; + writel(reg, &imx_ccm->cscdr2); +} + +static int enable_pll_video(u32 pll_div, u32 pll_num, u32 pll_denom) +{ + u32 reg = 0; + ulong start; + + debug("pll5 div = %d, num = %d, denom = %d\n", + pll_div, pll_num, pll_denom); + + /* Power up PLL5 video */ + writel(BM_ANADIG_PLL_VIDEO_POWERDOWN | BM_ANADIG_PLL_VIDEO_BYPASS | + BM_ANADIG_PLL_VIDEO_DIV_SELECT | BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT, + &imx_ccm->analog_pll_video_clr); + + /* Set div, num and denom */ + writel(BF_ANADIG_PLL_VIDEO_DIV_SELECT(pll_div) | + BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(0x2), + &imx_ccm->analog_pll_video_set); + + writel(BF_ANADIG_PLL_VIDEO_NUM_A(pll_num), + &imx_ccm->analog_pll_video_num); + + writel(BF_ANADIG_PLL_VIDEO_DENOM_B(pll_denom), + &imx_ccm->analog_pll_video_denom); + + /* Wait PLL5 lock */ + start = get_timer(0); /* Get current timestamp */ + + do { + reg = readl(&imx_ccm->analog_pll_video); + if (reg & BM_ANADIG_PLL_VIDEO_LOCK) { + /* Enable PLL out */ + writel(BM_ANADIG_PLL_VIDEO_ENABLE, + &imx_ccm->analog_pll_video_set); + return 0; + } + } while (get_timer(0) < (start + 10)); /* Wait 10ms */ + + printf("Lock PLL5 timeout\n"); + return 1; + +} + +void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq) +{ + u32 reg = 0; + u32 hck = MXC_HCLK/1000; + u32 min = hck * 27; + u32 max = hck * 54; + u32 temp, best = 0; + u32 i, j, pred = 1, postd = 1; + u32 pll_div, pll_num, pll_denom; + + debug("mxs_set_lcdclk, freq = %d\n", freq); + + if (base_addr == LCDIF1_BASE_ADDR) { + reg = readl(&imx_ccm->cscdr2); + if ((reg & MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK) != 0) + return; /*Can't change clocks when clock not from pre-mux */ + } else { + reg = readl(&imx_ccm->cscdr2); + if ((reg & MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK) != 0) + return; /*Can't change clocks when clock not from pre-mux */ + } + + for (i = 1; i <= 8; i++) { + for (j = 1; j <= 8; j++) { + temp = freq * i * j; + if (temp > max || temp < min) + continue; + + if (best == 0 || temp < best) { + best = temp; + pred = i; + postd = j; + } + } + } + + if (best == 0) { + printf("Fail to set rate to %dkhz", freq); + return; + } + + debug("best %d, pred = %d, postd = %d\n", best, pred, postd); + + pll_div = best / hck; + pll_denom = 1000000; + pll_num = (best - hck * pll_div) * pll_denom / hck; + + if (enable_pll_video(pll_div, pll_num, pll_denom)) + return; + + /* Disable the lcdif clocks first */ + disable_lcdif_clock(base_addr); + + if (base_addr == LCDIF1_BASE_ADDR) { + /* Select pre-lcd clock to PLL5 */ + reg = readl(&imx_ccm->cscdr2); + reg &= ~MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_MASK; + reg |= (0x2 << MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_OFFSET); + /* Set the pre divider */ + reg &= ~MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_MASK; + reg |= ((pred - 1) << MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_OFFSET); + writel(reg, &imx_ccm->cscdr2); + + /* Set the post divider */ + reg = readl(&imx_ccm->cbcmr); + reg &= ~MXC_CCM_CBCMR_LCDIF1_PODF_MASK; + reg |= ((postd - 1) << MXC_CCM_CBCMR_LCDIF1_PODF_OFFSET); + writel(reg, &imx_ccm->cbcmr); + } else { + /* Select pre-lcd clock to PLL5 */ + reg = readl(&imx_ccm->cscdr2); + reg &= ~MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_MASK; + reg |= (0x2 << MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_OFFSET); + /* Set the pre divider */ + reg &= ~MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_MASK; + reg |= ((pred - 1) << MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_OFFSET); + writel(reg, &imx_ccm->cscdr2); + + /* Set the post divider */ + reg = readl(&imx_ccm->cscmr1); + reg &= ~MXC_CCM_CSCMR1_LCDIF2_PODF_MASK; + reg |= ((postd - 1) << MXC_CCM_CSCMR1_LCDIF2_PODF_OFFSET); + writel(reg, &imx_ccm->cscmr1); + } + + /* Enable the lcdif clocks */ + enable_lcdif_clock(base_addr); +} +#endif + static int enable_enet_pll(uint32_t en) { struct mxc_ccm_reg *const imx_ccm diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 226a4cd..5698906 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -68,4 +68,9 @@ void enable_ipu_clock(void); int enable_fec_anatop_clock(enum enet_freq freq); void enable_enet_clk(unsigned char enable); void enable_thermal_clk(void); +#if (defined(CONFIG_MX6SX)) +void setup_lvds_clock(uint32_t lcdif_base); +void setup_lcdif_clock(uint32_t base_addr); +void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq); +#endif #endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/include/asm/arch-mx6/crm_regs.h b/arch/arm/include/asm/arch-mx6/crm_regs.h index 39f3c07..99431a6 100644 --- a/arch/arm/include/asm/arch-mx6/crm_regs.h +++ b/arch/arm/include/asm/arch-mx6/crm_regs.h @@ -168,6 +168,26 @@ struct mxc_ccm_reg { #define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_OFFSET 0
/* Define the bits in register CBCMR */ +#ifdef CONFIG_MX6SX +#define MXC_CCM_CBCMR_GPU_CORE_PODF_MASK (0x7 << 29) +#define MXC_CCM_CBCMR_GPU_CORE_PODF_OFFSET 29 +#define MXC_CCM_CBCMR_GPU_AXI_PODF_MASK (0x7 << 26) +#define MXC_CCM_CBCMR_GPU_AXI_PODF_OFFSET 26 +#define MXC_CCM_CBCMR_LCDIF1_PODF_MASK (0x7 << 23) +#define MXC_CCM_CBCMR_LCDIF1_PODF_OFFSET 23 +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK (0x3 << 21) +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET 21 +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL (1 << 20) +#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << 18) +#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET 18 +#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << 12) +#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET 12 +#define MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL (1 << 10) +#define MXC_CCM_CBCMR_GPU_AXI_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CBCMR_GPU_AXI_CLK_SEL_OFFSET 8 +#define MXC_CCM_CBCMR_GPU_CORE_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CBCMR_GPU_CORE_CLK_SEL_OFFSET 4 +#else #define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK (0x7 << 29) #define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET 29 #define MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK (0x7 << 26) @@ -179,23 +199,18 @@ struct mxc_ccm_reg { #define MXC_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL (1 << 20) #define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << 18) #define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET 18 -#ifndef CONFIG_MX6SX #define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 16) #define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET 16 #define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) #define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET 14 -#endif #define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << 12) #define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET 12 -#ifndef CONFIG_MX6SX #define MXC_CCM_CBCMR_VDOAXI_CLK_SEL (1 << 11) -#endif #define MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL (1 << 10) #define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK (0x3 << 8) #define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET 8 #define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK (0x3 << 4) #define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET 4 -#ifndef CONFIG_MX6SX #define MXC_CCM_CBCMR_GPU3D_AXI_CLK_SEL (1 << 1) #define MXC_CCM_CBCMR_GPU2D_AXI_CLK_SEL (1 << 0) #endif @@ -212,9 +227,15 @@ struct mxc_ccm_reg { #endif #define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK (0x7 << 23) #define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET 23 + /* ACLK_EMI_PODF is LCFIF2_PODF on MX6SX */ +#ifdef CONFIG_MX6SX +#define MXC_CCM_CSCMR1_LCDIF2_PODF_MASK (0x7 << 20) +#define MXC_CCM_CSCMR1_LCDIF2_PODF_OFFSET 20 +#else #define MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK (0x7 << 20) #define MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET 20 +#endif #define MXC_CCM_CSCMR1_USDHC4_CLK_SEL (1 << 19) #define MXC_CCM_CSCMR1_USDHC3_CLK_SEL (1 << 18) #define MXC_CCM_CSCMR1_USDHC2_CLK_SEL (1 << 17) @@ -384,6 +405,22 @@ struct mxc_ccm_reg { /* Define the bits in register CSCDR2 */ #define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK (0x3F << 19) #define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET 19 + +#ifdef CONFIG_MX6SX +#define MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_MASK (0x7 << 15) +#define MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_OFFSET 15 +#define MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_MASK (0x7 << 12) +#define MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_OFFSET 12 +#define MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK (0x7 << 9) +#define MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_OFFSET 9 +#define MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_MASK (0x7 << 6) +#define MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_OFFSET 6 +#define MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_MASK (0x7 << 3) +#define MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_OFFSET 3 +#define MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK (0x7 << 0) +#define MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_OFFSET 0 +#endif + /* All IPU2_DI1 are LCDIF1 on MX6SX */ #define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_MASK (0x7 << 15) #define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_OFFSET 15 @@ -621,6 +658,12 @@ struct mxc_ccm_reg { #define MXC_CCM_CCGR3_M4_MASK (3 << MXC_CCM_CCGR3_M4_OFFSET) #define MXC_CCM_CCGR3_ENET_OFFSET 4 #define MXC_CCM_CCGR3_ENET_MASK (3 << MXC_CCM_CCGR3_ENET_OFFSET) +#define MXC_CCM_CCGR3_DISP_AXI_OFFSET 6 +#define MXC_CCM_CCGR3_DISP_AXI_MASK (3 << MXC_CCM_CCGR3_DISP_AXI_OFFSET) +#define MXC_CCM_CCGR3_LCDIF2_PIX_OFFSET 8 +#define MXC_CCM_CCGR3_LCDIF2_PIX_MASK (3 << MXC_CCM_CCGR3_LCDIF2_PIX_OFFSET) +#define MXC_CCM_CCGR3_LCDIF1_PIX_OFFSET 10 +#define MXC_CCM_CCGR3_LCDIF1_PIX_MASK (3 << MXC_CCM_CCGR3_LCDIF1_PIX_OFFSET) #define MXC_CCM_CCGR3_QSPI_OFFSET 14 #define MXC_CCM_CCGR3_QSPI_MASK (3 << MXC_CCM_CCGR3_QSPI_OFFSET) #else diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h index 1983f2d..247fb88 100644 --- a/arch/arm/include/asm/arch-mx6/imx-regs.h +++ b/arch/arm/include/asm/arch-mx6/imx-regs.h @@ -850,5 +850,247 @@ struct pwm_regs { u32 pr; u32 cnr; }; + +/* eLCDIF controller registers */ +struct mxs_lcdif_regs { + u32 hw_lcdif_ctrl; /* 0x00 */ + u32 hw_lcdif_ctrl_set; + u32 hw_lcdif_ctrl_clr; + u32 hw_lcdif_ctrl_tog; + u32 hw_lcdif_ctrl1; /* 0x10 */ + u32 hw_lcdif_ctrl1_set; + u32 hw_lcdif_ctrl1_clr; + u32 hw_lcdif_ctrl1_tog; + u32 hw_lcdif_ctrl2; /* 0x20 */ + u32 hw_lcdif_ctrl2_set; + u32 hw_lcdif_ctrl2_clr; + u32 hw_lcdif_ctrl2_tog; + u32 hw_lcdif_transfer_count; /* 0x30 */ + u32 reserved1[3]; + u32 hw_lcdif_cur_buf; /* 0x40 */ + u32 reserved2[3]; + u32 hw_lcdif_next_buf; /* 0x50 */ + u32 reserved3[3]; + u32 hw_lcdif_timing; /* 0x60 */ + u32 reserved4[3]; + u32 hw_lcdif_vdctrl0; /* 0x70 */ + u32 hw_lcdif_vdctrl0_set; + u32 hw_lcdif_vdctrl0_clr; + u32 hw_lcdif_vdctrl0_tog; + u32 hw_lcdif_vdctrl1; /* 0x80 */ + u32 reserved5[3]; + u32 hw_lcdif_vdctrl2; /* 0x90 */ + u32 reserved6[3]; + u32 hw_lcdif_vdctrl3; /* 0xa0 */ + u32 reserved7[3]; + u32 hw_lcdif_vdctrl4; /* 0xb0 */ + u32 reserved8[3]; + u32 hw_lcdif_dvictrl0; /* 0xc0 */ + u32 reserved9[3]; + u32 hw_lcdif_dvictrl1; /* 0xd0 */ + u32 reserved10[3]; + u32 hw_lcdif_dvictrl2; /* 0xe0 */ + u32 reserved11[3]; + u32 hw_lcdif_dvictrl3; /* 0xf0 */ + u32 reserved12[3]; + u32 hw_lcdif_dvictrl4; /* 0x100 */ + u32 reserved13[3]; + u32 hw_lcdif_csc_coeffctrl0; /* 0x110 */ + u32 reserved14[3]; + u32 hw_lcdif_csc_coeffctrl1; /* 0x120 */ + u32 reserved15[3]; + u32 hw_lcdif_csc_coeffctrl2; /* 0x130 */ + u32 reserved16[3]; + u32 hw_lcdif_csc_coeffctrl3; /* 0x140 */ + u32 reserved17[3]; + u32 hw_lcdif_csc_coeffctrl4; /* 0x150 */ + u32 reserved18[3]; + u32 hw_lcdif_csc_offset; /* 0x160 */ + u32 reserved19[3]; + u32 hw_lcdif_csc_limit; /* 0x170 */ + u32 reserved20[3]; + u32 hw_lcdif_data; /* 0x180 */ + u32 reserved21[3]; + u32 hw_lcdif_bm_error_stat; /* 0x190 */ + u32 reserved22[3]; + u32 hw_lcdif_crc_stat; /* 0x1a0 */ + u32 reserved23[3]; + u32 hw_lcdif_lcdif_stat; /* 0x1b0 */ + u32 reserved24[3]; + u32 hw_lcdif_version; /* 0x1c0 */ + u32 reserved25[3]; + u32 hw_lcdif_debug0; /* 0x1d0 */ + u32 reserved26[3]; + u32 hw_lcdif_debug1; /* 0x1e0 */ + u32 reserved27[3]; + u32 hw_lcdif_debug2; /* 0x1f0 */ + u32 reserved28[3]; + u32 hw_lcdif_thres; /* 0x200 */ + u32 reserved29[3]; + u32 hw_lcdif_as_ctrl; /* 0x210 */ + u32 reserved30[3]; + u32 hw_lcdif_as_buf; /* 0x220 */ + u32 reserved31[3]; + u32 hw_lcdif_as_next_buf; /* 0x230 */ + u32 reserved32[3]; + u32 hw_lcdif_as_clrkeylow; /* 0x240 */ + u32 reserved33[3]; + u32 hw_lcdif_as_clrkeyhigh; /* 0x250 */ + u32 reserved34[3]; + u32 hw_lcdif_as_sync_delay; /* 0x260 */ + u32 reserved35[3]; + u32 hw_lcdif_as_debug3; /* 0x270 */ + u32 reserved36[3]; + u32 hw_lcdif_as_debug4; /* 0x280 */ + u32 reserved37[3]; + u32 hw_lcdif_as_debug5; /* 0x290 */ +}; + +#define MXS_LCDIF_BASE LCDIF2_BASE_ADDR + +#define LCDIF_CTRL_SFTRST (1 << 31) +#define LCDIF_CTRL_CLKGATE (1 << 30) +#define LCDIF_CTRL_YCBCR422_INPUT (1 << 29) +#define LCDIF_CTRL_READ_WRITEB (1 << 28) +#define LCDIF_CTRL_WAIT_FOR_VSYNC_EDGE (1 << 27) +#define LCDIF_CTRL_DATA_SHIFT_DIR (1 << 26) +#define LCDIF_CTRL_SHIFT_NUM_BITS_MASK (0x1f << 21) +#define LCDIF_CTRL_SHIFT_NUM_BITS_OFFSET 21 +#define LCDIF_CTRL_DVI_MODE (1 << 20) +#define LCDIF_CTRL_BYPASS_COUNT (1 << 19) +#define LCDIF_CTRL_VSYNC_MODE (1 << 18) +#define LCDIF_CTRL_DOTCLK_MODE (1 << 17) +#define LCDIF_CTRL_DATA_SELECT (1 << 16) +#define LCDIF_CTRL_INPUT_DATA_SWIZZLE_MASK (0x3 << 14) +#define LCDIF_CTRL_INPUT_DATA_SWIZZLE_OFFSET 14 +#define LCDIF_CTRL_CSC_DATA_SWIZZLE_MASK (0x3 << 12) +#define LCDIF_CTRL_CSC_DATA_SWIZZLE_OFFSET 12 +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK (0x3 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_OFFSET 10 +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT (0 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT (1 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT (2 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT (3 << 10) +#define LCDIF_CTRL_WORD_LENGTH_MASK (0x3 << 8) +#define LCDIF_CTRL_WORD_LENGTH_OFFSET 8 +#define LCDIF_CTRL_WORD_LENGTH_16BIT (0 << 8) +#define LCDIF_CTRL_WORD_LENGTH_8BIT (1 << 8) +#define LCDIF_CTRL_WORD_LENGTH_18BIT (2 << 8) +#define LCDIF_CTRL_WORD_LENGTH_24BIT (3 << 8) +#define LCDIF_CTRL_RGB_TO_YCBCR422_CSC (1 << 7) +#define LCDIF_CTRL_LCDIF_MASTER (1 << 5) +#define LCDIF_CTRL_DATA_FORMAT_16_BIT (1 << 3) +#define LCDIF_CTRL_DATA_FORMAT_18_BIT (1 << 2) +#define LCDIF_CTRL_DATA_FORMAT_24_BIT (1 << 1) +#define LCDIF_CTRL_RUN (1 << 0) + +#define LCDIF_CTRL1_COMBINE_MPU_WR_STRB (1 << 27) +#define LCDIF_CTRL1_BM_ERROR_IRQ_EN (1 << 26) +#define LCDIF_CTRL1_BM_ERROR_IRQ (1 << 25) +#define LCDIF_CTRL1_RECOVER_ON_UNDERFLOW (1 << 24) +#define LCDIF_CTRL1_INTERLACE_FIELDS (1 << 23) +#define LCDIF_CTRL1_START_INTERLACE_FROM_SECOND_FIELD (1 << 22) +#define LCDIF_CTRL1_FIFO_CLEAR (1 << 21) +#define LCDIF_CTRL1_IRQ_ON_ALTERNATE_FIELDS (1 << 20) +#define LCDIF_CTRL1_BYTE_PACKING_FORMAT_MASK (0xf << 16) +#define LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET 16 +#define LCDIF_CTRL1_OVERFLOW_IRQ_EN (1 << 15) +#define LCDIF_CTRL1_UNDERFLOW_IRQ_EN (1 << 14) +#define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13) +#define LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12) +#define LCDIF_CTRL1_OVERFLOW_IRQ (1 << 11) +#define LCDIF_CTRL1_UNDERFLOW_IRQ (1 << 10) +#define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ (1 << 9) +#define LCDIF_CTRL1_VSYNC_EDGE_IRQ (1 << 8) +#define LCDIF_CTRL1_BUSY_ENABLE (1 << 2) +#define LCDIF_CTRL1_MODE86 (1 << 1) +#define LCDIF_CTRL1_RESET (1 << 0) + +#define LCDIF_CTRL2_OUTSTANDING_REQS_MASK (0x7 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_OFFSET 21 +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_1 (0x0 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_2 (0x1 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_4 (0x2 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_8 (0x3 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_16 (0x4 << 21) +#define LCDIF_CTRL2_BURST_LEN_8 (1 << 20) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_MASK (0x7 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_OFFSET 16 +#define LCDIF_CTRL2_ODD_LINE_PATTERN_RGB (0x0 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_RBG (0x1 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_GBR (0x2 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_GRB (0x3 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_BRG (0x4 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_BGR (0x5 << 16) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_MASK (0x7 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_OFFSET 12 +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_RGB (0x0 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_RBG (0x1 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_GBR (0x2 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_GRB (0x3 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_BRG (0x4 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_BGR (0x5 << 12) +#define LCDIF_CTRL2_READ_PACK_DIR (1 << 10) +#define LCDIF_CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT (1 << 9) +#define LCDIF_CTRL2_READ_MODE_6_BIT_INPUT (1 << 8) +#define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK (0x7 << 4) +#define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET 4 +#define LCDIF_CTRL2_INITIAL_DUMMY_READ_MASK (0x7 << 1) +#define LCDIF_CTRL2_INITIAL_DUMMY_READ_OFFSET 1 + +#define LCDIF_TRANSFER_COUNT_V_COUNT_MASK (0xffff << 16) +#define LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET 16 +#define LCDIF_TRANSFER_COUNT_H_COUNT_MASK (0xffff << 0) +#define LCDIF_TRANSFER_COUNT_H_COUNT_OFFSET 0 + +#define LCDIF_CUR_BUF_ADDR_MASK 0xffffffff +#define LCDIF_CUR_BUF_ADDR_OFFSET 0 + +#define LCDIF_NEXT_BUF_ADDR_MASK 0xffffffff +#define LCDIF_NEXT_BUF_ADDR_OFFSET 0 + +#define LCDIF_TIMING_CMD_HOLD_MASK (0xff << 24) +#define LCDIF_TIMING_CMD_HOLD_OFFSET 24 +#define LCDIF_TIMING_CMD_SETUP_MASK (0xff << 16) +#define LCDIF_TIMING_CMD_SETUP_OFFSET 16 +#define LCDIF_TIMING_DATA_HOLD_MASK (0xff << 8) +#define LCDIF_TIMING_DATA_HOLD_OFFSET 8 +#define LCDIF_TIMING_DATA_SETUP_MASK (0xff << 0) +#define LCDIF_TIMING_DATA_SETUP_OFFSET 0 + +#define LCDIF_VDCTRL0_VSYNC_OEB (1 << 29) +#define LCDIF_VDCTRL0_ENABLE_PRESENT (1 << 28) +#define LCDIF_VDCTRL0_VSYNC_POL (1 << 27) +#define LCDIF_VDCTRL0_HSYNC_POL (1 << 26) +#define LCDIF_VDCTRL0_DOTCLK_POL (1 << 25) +#define LCDIF_VDCTRL0_ENABLE_POL (1 << 24) +#define LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) +#define LCDIF_VDCTRL0_HALF_LINE (1 << 19) +#define LCDIF_VDCTRL0_HALF_LINE_MODE (1 << 18) +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_MASK 0x3ffff +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_OFFSET 0 + +#define LCDIF_VDCTRL1_VSYNC_PERIOD_MASK 0xffffffff +#define LCDIF_VDCTRL1_VSYNC_PERIOD_OFFSET 0 + +#define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0x3fff << 18) +#define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 18 +#define LCDIF_VDCTRL2_HSYNC_PERIOD_MASK 0x3ffff +#define LCDIF_VDCTRL2_HSYNC_PERIOD_OFFSET 0 + +#define LCDIF_VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) +#define LCDIF_VDCTRL3_VSYNC_ONLY (1 << 28) +#define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_MASK (0xfff << 16) +#define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET 16 +#define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_MASK (0xffff << 0) +#define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_OFFSET 0 + +#define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_MASK (0x7 << 29) +#define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET 29 +#define LCDIF_VDCTRL4_SYNC_SIGNALS_ON (1 << 18) +#define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_MASK 0x3ffff +#define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_OFFSET 0 + #endif /* __ASSEMBLER__*/ #endif /* __ASM_ARCH_MX6_IMX_REGS_H__ */

Hi,
On 14/01/2015 10:19, Ye.Li wrote:
Add clock functions and relevant registers to enable/set LCDIF clock and LVDS clock.
Signed-off-by: Ye.Li B37916@freescale.com
arch/arm/cpu/armv7/mx6/clock.c | 238 +++++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx6/clock.h | 5 + arch/arm/include/asm/arch-mx6/crm_regs.h | 53 ++++++- arch/arm/include/asm/arch-mx6/imx-regs.h | 242 ++++++++++++++++++++++++++++++ 4 files changed, 533 insertions(+), 5 deletions(-)
diff --git a/arch/arm/cpu/armv7/mx6/clock.c b/arch/arm/cpu/armv7/mx6/clock.c index b6983e6..24b9b95 100644 --- a/arch/arm/cpu/armv7/mx6/clock.c +++ b/arch/arm/cpu/armv7/mx6/clock.c @@ -545,6 +545,244 @@ u32 imx_get_fecclk(void) return mxc_get_clock(MXC_IPG_CLK); }
+#ifdef CONFIG_MX6SX +static void enable_lcdif_clock(uint32_t base_addr) +{
I always find tricky to select a source with the physical address. Really, you are selecting which LCDIF, and it would make sense to have something enable_lcdif_clock(uint32_t index), with index [0..1].
- u32 reg = 0;
- /* Enable the LCDIF pix clock, axi clock, disp axi clock */
- reg = readl(&imx_ccm->CCGR3);
- if (base_addr == LCDIF1_BASE_ADDR)
reg |= (MXC_CCM_CCGR3_LCDIF1_PIX_MASK | MXC_CCM_CCGR3_DISP_AXI_MASK);
- else
reg |= (MXC_CCM_CCGR3_LCDIF2_PIX_MASK | MXC_CCM_CCGR3_DISP_AXI_MASK);
- writel(reg, &imx_ccm->CCGR3);
- reg = readl(&imx_ccm->CCGR2);
- reg |= (MXC_CCM_CCGR2_LCD_MASK);
- writel(reg, &imx_ccm->CCGR2);
+}
+static void disable_lcdif_clock(uint32_t base_addr) +{
Same here and in the rest of the patch.
- u32 reg = 0;
- /* Disable the LCDIF pix clock, axi clock, disp axi clock */
- reg = readl(&imx_ccm->CCGR3);
- if (base_addr == LCDIF1_BASE_ADDR)
reg &= ~(MXC_CCM_CCGR3_LCDIF1_PIX_MASK | MXC_CCM_CCGR3_DISP_AXI_MASK);
- else
reg &= ~(MXC_CCM_CCGR3_LCDIF2_PIX_MASK | MXC_CCM_CCGR3_DISP_AXI_MASK);
- writel(reg, &imx_ccm->CCGR3);
- reg = readl(&imx_ccm->CCGR2);
- reg &= ~(MXC_CCM_CCGR2_LCD_MASK);
- writel(reg, &imx_ccm->CCGR2);
+}
+void setup_lvds_clock(uint32_t lcdif_base) +{
- u32 reg = 0;
- struct iomuxc *iomux = (struct iomuxc *)IOMUXC_BASE_ADDR;
- disable_lcdif_clock(lcdif_base);
- /* Turn off LDB DI0 clocks */
- reg = readl(&imx_ccm->CCGR3);
- reg &= ~MXC_CCM_CCGR3_LDB_DI0_MASK;
- writel(reg, &imx_ccm->CCGR3);
- /* set LDB DI0 clk select to 011 PLL2 PFD3 200M*/
- reg = readl(&imx_ccm->cs2cdr);
- reg &= ~MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_MASK;
- reg |= (3 << MXC_CCM_CS2CDR_LDB_DI0_CLK_SEL_OFFSET);
- writel(reg, &imx_ccm->cs2cdr);
- reg = readl(&imx_ccm->cscmr2);
- reg |= MXC_CCM_CSCMR2_LDB_DI0_IPU_DIV;
- writel(reg, &imx_ccm->cscmr2);
- /* set LDB DI0 clock for LCDIF PIX clock */
- reg = readl(&imx_ccm->cscdr2);
- if (lcdif_base == LCDIF1_BASE_ADDR) {
reg &= ~MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK;
reg |= (0x3 << MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_OFFSET);
- } else {
reg &= ~MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK;
reg |= (0x3 << MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_OFFSET);
- }
- writel(reg, &imx_ccm->cscdr2);
- reg = IOMUXC_GPR2_DI0_VS_POLARITY_ACTIVE_LOW
| IOMUXC_GPR2_BIT_MAPPING_CH0_SPWG
| IOMUXC_GPR2_DATA_WIDTH_CH0_18BIT
| IOMUXC_GPR2_LVDS_CH0_MODE_ENABLED_DI0;
- writel(reg, &iomux->gpr[6]);
- reg = readl(&iomux->gpr[5]);
- if (lcdif_base == LCDIF1_BASE_ADDR)
reg &= ~0x8; /* MUX LVDS to LCDIF1 */
- else
reg |= 0x8; /* MUX LVDS to LCDIF2 */
- writel(reg, &iomux->gpr[5]);
It is more readable if you write this as:
....common setup
switch (index) { case (LCDIF1): ..do for LCDIF1 break; case (LCDIF2): ..do for LCDIF2 break; }
...finish setup
- /* Turn on LDB DI0 clocks */
- reg = readl(&imx_ccm->CCGR3);
- reg |= MXC_CCM_CCGR3_LDB_DI0_MASK;
- writel(reg, &imx_ccm->CCGR3);
- enable_lcdif_clock(lcdif_base);
+}
+void setup_lcdif_clock(uint32_t base_addr) +{
- u32 reg = 0;
- /* Disable the lcdif clocks, the driver will enable the lcdif clock */
- disable_lcdif_clock(base_addr);
- /* Set to pre-mux clock at default */
- reg = readl(&imx_ccm->cscdr2);
- if (base_addr == LCDIF1_BASE_ADDR)
reg &= ~MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK;
- else
reg &= ~MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK;
- writel(reg, &imx_ccm->cscdr2);
+}
+static int enable_pll_video(u32 pll_div, u32 pll_num, u32 pll_denom) +{
- u32 reg = 0;
- ulong start;
- debug("pll5 div = %d, num = %d, denom = %d\n",
pll_div, pll_num, pll_denom);
- /* Power up PLL5 video */
- writel(BM_ANADIG_PLL_VIDEO_POWERDOWN | BM_ANADIG_PLL_VIDEO_BYPASS |
BM_ANADIG_PLL_VIDEO_DIV_SELECT | BM_ANADIG_PLL_VIDEO_POST_DIV_SELECT,
&imx_ccm->analog_pll_video_clr);
- /* Set div, num and denom */
- writel(BF_ANADIG_PLL_VIDEO_DIV_SELECT(pll_div) |
BF_ANADIG_PLL_VIDEO_POST_DIV_SELECT(0x2),
&imx_ccm->analog_pll_video_set);
- writel(BF_ANADIG_PLL_VIDEO_NUM_A(pll_num),
&imx_ccm->analog_pll_video_num);
- writel(BF_ANADIG_PLL_VIDEO_DENOM_B(pll_denom),
&imx_ccm->analog_pll_video_denom);
- /* Wait PLL5 lock */
- start = get_timer(0); /* Get current timestamp */
- do {
reg = readl(&imx_ccm->analog_pll_video);
if (reg & BM_ANADIG_PLL_VIDEO_LOCK) {
/* Enable PLL out */
writel(BM_ANADIG_PLL_VIDEO_ENABLE,
&imx_ccm->analog_pll_video_set);
return 0;
}
- } while (get_timer(0) < (start + 10)); /* Wait 10ms */
- printf("Lock PLL5 timeout\n");
- return 1;
+}
+void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq) +{
- u32 reg = 0;
- u32 hck = MXC_HCLK/1000;
- u32 min = hck * 27;
- u32 max = hck * 54;
- u32 temp, best = 0;
- u32 i, j, pred = 1, postd = 1;
- u32 pll_div, pll_num, pll_denom;
- debug("mxs_set_lcdclk, freq = %d\n", freq);
- if (base_addr == LCDIF1_BASE_ADDR) {
reg = readl(&imx_ccm->cscdr2);
if ((reg & MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK) != 0)
return; /*Can't change clocks when clock not from pre-mux */
- } else {
reg = readl(&imx_ccm->cscdr2);
if ((reg & MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK) != 0)
return; /*Can't change clocks when clock not from pre-mux */
- }
- for (i = 1; i <= 8; i++) {
for (j = 1; j <= 8; j++) {
temp = freq * i * j;
if (temp > max || temp < min)
continue;
if (best == 0 || temp < best) {
best = temp;
pred = i;
postd = j;
}
}
- }
- if (best == 0) {
printf("Fail to set rate to %dkhz", freq);
return;
- }
- debug("best %d, pred = %d, postd = %d\n", best, pred, postd);
- pll_div = best / hck;
- pll_denom = 1000000;
- pll_num = (best - hck * pll_div) * pll_denom / hck;
- if (enable_pll_video(pll_div, pll_num, pll_denom))
return;
- /* Disable the lcdif clocks first */
- disable_lcdif_clock(base_addr);
- if (base_addr == LCDIF1_BASE_ADDR) {
/* Select pre-lcd clock to PLL5 */
reg = readl(&imx_ccm->cscdr2);
reg &= ~MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_MASK;
reg |= (0x2 << MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_OFFSET);
/* Set the pre divider */
reg &= ~MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_MASK;
reg |= ((pred - 1) << MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_OFFSET);
writel(reg, &imx_ccm->cscdr2);
/* Set the post divider */
reg = readl(&imx_ccm->cbcmr);
reg &= ~MXC_CCM_CBCMR_LCDIF1_PODF_MASK;
reg |= ((postd - 1) << MXC_CCM_CBCMR_LCDIF1_PODF_OFFSET);
writel(reg, &imx_ccm->cbcmr);
- } else {
/* Select pre-lcd clock to PLL5 */
reg = readl(&imx_ccm->cscdr2);
reg &= ~MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_MASK;
reg |= (0x2 << MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_OFFSET);
/* Set the pre divider */
reg &= ~MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_MASK;
reg |= ((pred - 1) << MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_OFFSET);
writel(reg, &imx_ccm->cscdr2);
/* Set the post divider */
reg = readl(&imx_ccm->cscmr1);
reg &= ~MXC_CCM_CSCMR1_LCDIF2_PODF_MASK;
reg |= ((postd - 1) << MXC_CCM_CSCMR1_LCDIF2_PODF_OFFSET);
writel(reg, &imx_ccm->cscmr1);
- }
- /* Enable the lcdif clocks */
- enable_lcdif_clock(base_addr);
+} +#endif
static int enable_enet_pll(uint32_t en) { struct mxc_ccm_reg *const imx_ccm diff --git a/arch/arm/include/asm/arch-mx6/clock.h b/arch/arm/include/asm/arch-mx6/clock.h index 226a4cd..5698906 100644 --- a/arch/arm/include/asm/arch-mx6/clock.h +++ b/arch/arm/include/asm/arch-mx6/clock.h @@ -68,4 +68,9 @@ void enable_ipu_clock(void); int enable_fec_anatop_clock(enum enet_freq freq); void enable_enet_clk(unsigned char enable); void enable_thermal_clk(void); +#if (defined(CONFIG_MX6SX)) +void setup_lvds_clock(uint32_t lcdif_base); +void setup_lcdif_clock(uint32_t base_addr); +void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq); +#endif #endif /* __ASM_ARCH_CLOCK_H */ diff --git a/arch/arm/include/asm/arch-mx6/crm_regs.h b/arch/arm/include/asm/arch-mx6/crm_regs.h index 39f3c07..99431a6 100644 --- a/arch/arm/include/asm/arch-mx6/crm_regs.h +++ b/arch/arm/include/asm/arch-mx6/crm_regs.h @@ -168,6 +168,26 @@ struct mxc_ccm_reg { #define MXC_CCM_CBCDR_PERIPH2_CLK2_PODF_OFFSET 0
/* Define the bits in register CBCMR */ +#ifdef CONFIG_MX6SX +#define MXC_CCM_CBCMR_GPU_CORE_PODF_MASK (0x7 << 29) +#define MXC_CCM_CBCMR_GPU_CORE_PODF_OFFSET 29 +#define MXC_CCM_CBCMR_GPU_AXI_PODF_MASK (0x7 << 26) +#define MXC_CCM_CBCMR_GPU_AXI_PODF_OFFSET 26 +#define MXC_CCM_CBCMR_LCDIF1_PODF_MASK (0x7 << 23) +#define MXC_CCM_CBCMR_LCDIF1_PODF_OFFSET 23 +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_MASK (0x3 << 21) +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK_SEL_OFFSET 21 +#define MXC_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL (1 << 20) +#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << 18) +#define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET 18 +#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << 12) +#define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET 12 +#define MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL (1 << 10) +#define MXC_CCM_CBCMR_GPU_AXI_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CBCMR_GPU_AXI_CLK_SEL_OFFSET 8 +#define MXC_CCM_CBCMR_GPU_CORE_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CBCMR_GPU_CORE_CLK_SEL_OFFSET 4 +#else #define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_MASK (0x7 << 29) #define MXC_CCM_CBCMR_GPU3D_SHADER_PODF_OFFSET 29 #define MXC_CCM_CBCMR_GPU3D_CORE_PODF_MASK (0x7 << 26) @@ -179,23 +199,18 @@ struct mxc_ccm_reg { #define MXC_CCM_CBCMR_PRE_PERIPH2_CLK2_SEL (1 << 20) #define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_MASK (0x3 << 18) #define MXC_CCM_CBCMR_PRE_PERIPH_CLK_SEL_OFFSET 18 -#ifndef CONFIG_MX6SX #define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK (0x3 << 16) #define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET 16 #define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) #define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET 14 -#endif #define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_MASK (0x3 << 12) #define MXC_CCM_CBCMR_PERIPH_CLK2_SEL_OFFSET 12 -#ifndef CONFIG_MX6SX #define MXC_CCM_CBCMR_VDOAXI_CLK_SEL (1 << 11) -#endif #define MXC_CCM_CBCMR_PCIE_AXI_CLK_SEL (1 << 10) #define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_MASK (0x3 << 8) #define MXC_CCM_CBCMR_GPU3D_SHADER_CLK_SEL_OFFSET 8 #define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_MASK (0x3 << 4) #define MXC_CCM_CBCMR_GPU3D_CORE_CLK_SEL_OFFSET 4 -#ifndef CONFIG_MX6SX #define MXC_CCM_CBCMR_GPU3D_AXI_CLK_SEL (1 << 1) #define MXC_CCM_CBCMR_GPU2D_AXI_CLK_SEL (1 << 0) #endif @@ -212,9 +227,15 @@ struct mxc_ccm_reg { #endif #define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_MASK (0x7 << 23) #define MXC_CCM_CSCMR1_ACLK_EMI_SLOW_PODF_OFFSET 23
/* ACLK_EMI_PODF is LCFIF2_PODF on MX6SX */ +#ifdef CONFIG_MX6SX +#define MXC_CCM_CSCMR1_LCDIF2_PODF_MASK (0x7 << 20) +#define MXC_CCM_CSCMR1_LCDIF2_PODF_OFFSET 20 +#else #define MXC_CCM_CSCMR1_ACLK_EMI_PODF_MASK (0x7 << 20) #define MXC_CCM_CSCMR1_ACLK_EMI_PODF_OFFSET 20 +#endif #define MXC_CCM_CSCMR1_USDHC4_CLK_SEL (1 << 19) #define MXC_CCM_CSCMR1_USDHC3_CLK_SEL (1 << 18) #define MXC_CCM_CSCMR1_USDHC2_CLK_SEL (1 << 17) @@ -384,6 +405,22 @@ struct mxc_ccm_reg { /* Define the bits in register CSCDR2 */ #define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_MASK (0x3F << 19) #define MXC_CCM_CSCDR2_ECSPI_CLK_PODF_OFFSET 19
+#ifdef CONFIG_MX6SX +#define MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_MASK (0x7 << 15) +#define MXC_CCM_CSCDR2_LCDIF1_PRED_SEL_OFFSET 15 +#define MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_MASK (0x7 << 12) +#define MXC_CCM_CSCDR2_LCDIF1_PRE_DIV_OFFSET 12 +#define MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_MASK (0x7 << 9) +#define MXC_CCM_CSCDR2_LCDIF1_CLK_SEL_OFFSET 9 +#define MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_MASK (0x7 << 6) +#define MXC_CCM_CSCDR2_LCDIF2_PRED_SEL_OFFSET 6 +#define MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_MASK (0x7 << 3) +#define MXC_CCM_CSCDR2_LCDIF2_PRE_DIV_OFFSET 3 +#define MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_MASK (0x7 << 0) +#define MXC_CCM_CSCDR2_LCDIF2_CLK_SEL_OFFSET 0 +#endif
/* All IPU2_DI1 are LCDIF1 on MX6SX */ #define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_MASK (0x7 << 15) #define MXC_CCM_CHSCCDR_IPU2_DI1_PRE_CLK_SEL_OFFSET 15 @@ -621,6 +658,12 @@ struct mxc_ccm_reg { #define MXC_CCM_CCGR3_M4_MASK (3 << MXC_CCM_CCGR3_M4_OFFSET) #define MXC_CCM_CCGR3_ENET_OFFSET 4 #define MXC_CCM_CCGR3_ENET_MASK (3 << MXC_CCM_CCGR3_ENET_OFFSET) +#define MXC_CCM_CCGR3_DISP_AXI_OFFSET 6 +#define MXC_CCM_CCGR3_DISP_AXI_MASK (3 << MXC_CCM_CCGR3_DISP_AXI_OFFSET) +#define MXC_CCM_CCGR3_LCDIF2_PIX_OFFSET 8 +#define MXC_CCM_CCGR3_LCDIF2_PIX_MASK (3 << MXC_CCM_CCGR3_LCDIF2_PIX_OFFSET) +#define MXC_CCM_CCGR3_LCDIF1_PIX_OFFSET 10 +#define MXC_CCM_CCGR3_LCDIF1_PIX_MASK (3 << MXC_CCM_CCGR3_LCDIF1_PIX_OFFSET) #define MXC_CCM_CCGR3_QSPI_OFFSET 14 #define MXC_CCM_CCGR3_QSPI_MASK (3 << MXC_CCM_CCGR3_QSPI_OFFSET) #else diff --git a/arch/arm/include/asm/arch-mx6/imx-regs.h b/arch/arm/include/asm/arch-mx6/imx-regs.h index 1983f2d..247fb88 100644 --- a/arch/arm/include/asm/arch-mx6/imx-regs.h +++ b/arch/arm/include/asm/arch-mx6/imx-regs.h @@ -850,5 +850,247 @@ struct pwm_regs { u32 pr; u32 cnr; };
+/* eLCDIF controller registers */ +struct mxs_lcdif_regs {
- u32 hw_lcdif_ctrl; /* 0x00 */
- u32 hw_lcdif_ctrl_set;
- u32 hw_lcdif_ctrl_clr;
- u32 hw_lcdif_ctrl_tog;
- u32 hw_lcdif_ctrl1; /* 0x10 */
- u32 hw_lcdif_ctrl1_set;
- u32 hw_lcdif_ctrl1_clr;
- u32 hw_lcdif_ctrl1_tog;
- u32 hw_lcdif_ctrl2; /* 0x20 */
- u32 hw_lcdif_ctrl2_set;
- u32 hw_lcdif_ctrl2_clr;
- u32 hw_lcdif_ctrl2_tog;
- u32 hw_lcdif_transfer_count; /* 0x30 */
- u32 reserved1[3];
- u32 hw_lcdif_cur_buf; /* 0x40 */
- u32 reserved2[3];
- u32 hw_lcdif_next_buf; /* 0x50 */
- u32 reserved3[3];
- u32 hw_lcdif_timing; /* 0x60 */
- u32 reserved4[3];
- u32 hw_lcdif_vdctrl0; /* 0x70 */
- u32 hw_lcdif_vdctrl0_set;
- u32 hw_lcdif_vdctrl0_clr;
- u32 hw_lcdif_vdctrl0_tog;
- u32 hw_lcdif_vdctrl1; /* 0x80 */
- u32 reserved5[3];
- u32 hw_lcdif_vdctrl2; /* 0x90 */
- u32 reserved6[3];
- u32 hw_lcdif_vdctrl3; /* 0xa0 */
- u32 reserved7[3];
- u32 hw_lcdif_vdctrl4; /* 0xb0 */
- u32 reserved8[3];
- u32 hw_lcdif_dvictrl0; /* 0xc0 */
- u32 reserved9[3];
- u32 hw_lcdif_dvictrl1; /* 0xd0 */
- u32 reserved10[3];
- u32 hw_lcdif_dvictrl2; /* 0xe0 */
- u32 reserved11[3];
- u32 hw_lcdif_dvictrl3; /* 0xf0 */
- u32 reserved12[3];
- u32 hw_lcdif_dvictrl4; /* 0x100 */
- u32 reserved13[3];
- u32 hw_lcdif_csc_coeffctrl0; /* 0x110 */
- u32 reserved14[3];
- u32 hw_lcdif_csc_coeffctrl1; /* 0x120 */
- u32 reserved15[3];
- u32 hw_lcdif_csc_coeffctrl2; /* 0x130 */
- u32 reserved16[3];
- u32 hw_lcdif_csc_coeffctrl3; /* 0x140 */
- u32 reserved17[3];
- u32 hw_lcdif_csc_coeffctrl4; /* 0x150 */
- u32 reserved18[3];
- u32 hw_lcdif_csc_offset; /* 0x160 */
- u32 reserved19[3];
- u32 hw_lcdif_csc_limit; /* 0x170 */
- u32 reserved20[3];
- u32 hw_lcdif_data; /* 0x180 */
- u32 reserved21[3];
- u32 hw_lcdif_bm_error_stat; /* 0x190 */
- u32 reserved22[3];
- u32 hw_lcdif_crc_stat; /* 0x1a0 */
- u32 reserved23[3];
- u32 hw_lcdif_lcdif_stat; /* 0x1b0 */
- u32 reserved24[3];
- u32 hw_lcdif_version; /* 0x1c0 */
- u32 reserved25[3];
- u32 hw_lcdif_debug0; /* 0x1d0 */
- u32 reserved26[3];
- u32 hw_lcdif_debug1; /* 0x1e0 */
- u32 reserved27[3];
- u32 hw_lcdif_debug2; /* 0x1f0 */
- u32 reserved28[3];
- u32 hw_lcdif_thres; /* 0x200 */
- u32 reserved29[3];
- u32 hw_lcdif_as_ctrl; /* 0x210 */
- u32 reserved30[3];
- u32 hw_lcdif_as_buf; /* 0x220 */
- u32 reserved31[3];
- u32 hw_lcdif_as_next_buf; /* 0x230 */
- u32 reserved32[3];
- u32 hw_lcdif_as_clrkeylow; /* 0x240 */
- u32 reserved33[3];
- u32 hw_lcdif_as_clrkeyhigh; /* 0x250 */
- u32 reserved34[3];
- u32 hw_lcdif_as_sync_delay; /* 0x260 */
- u32 reserved35[3];
- u32 hw_lcdif_as_debug3; /* 0x270 */
- u32 reserved36[3];
- u32 hw_lcdif_as_debug4; /* 0x280 */
- u32 reserved37[3];
- u32 hw_lcdif_as_debug5; /* 0x290 */
+};
+#define MXS_LCDIF_BASE LCDIF2_BASE_ADDR
+#define LCDIF_CTRL_SFTRST (1 << 31) +#define LCDIF_CTRL_CLKGATE (1 << 30) +#define LCDIF_CTRL_YCBCR422_INPUT (1 << 29) +#define LCDIF_CTRL_READ_WRITEB (1 << 28) +#define LCDIF_CTRL_WAIT_FOR_VSYNC_EDGE (1 << 27) +#define LCDIF_CTRL_DATA_SHIFT_DIR (1 << 26) +#define LCDIF_CTRL_SHIFT_NUM_BITS_MASK (0x1f << 21) +#define LCDIF_CTRL_SHIFT_NUM_BITS_OFFSET 21 +#define LCDIF_CTRL_DVI_MODE (1 << 20) +#define LCDIF_CTRL_BYPASS_COUNT (1 << 19) +#define LCDIF_CTRL_VSYNC_MODE (1 << 18) +#define LCDIF_CTRL_DOTCLK_MODE (1 << 17) +#define LCDIF_CTRL_DATA_SELECT (1 << 16) +#define LCDIF_CTRL_INPUT_DATA_SWIZZLE_MASK (0x3 << 14) +#define LCDIF_CTRL_INPUT_DATA_SWIZZLE_OFFSET 14 +#define LCDIF_CTRL_CSC_DATA_SWIZZLE_MASK (0x3 << 12) +#define LCDIF_CTRL_CSC_DATA_SWIZZLE_OFFSET 12 +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK (0x3 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_OFFSET 10 +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_16BIT (0 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_8BIT (1 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT (2 << 10) +#define LCDIF_CTRL_LCD_DATABUS_WIDTH_24BIT (3 << 10) +#define LCDIF_CTRL_WORD_LENGTH_MASK (0x3 << 8) +#define LCDIF_CTRL_WORD_LENGTH_OFFSET 8 +#define LCDIF_CTRL_WORD_LENGTH_16BIT (0 << 8) +#define LCDIF_CTRL_WORD_LENGTH_8BIT (1 << 8) +#define LCDIF_CTRL_WORD_LENGTH_18BIT (2 << 8) +#define LCDIF_CTRL_WORD_LENGTH_24BIT (3 << 8) +#define LCDIF_CTRL_RGB_TO_YCBCR422_CSC (1 << 7) +#define LCDIF_CTRL_LCDIF_MASTER (1 << 5) +#define LCDIF_CTRL_DATA_FORMAT_16_BIT (1 << 3) +#define LCDIF_CTRL_DATA_FORMAT_18_BIT (1 << 2) +#define LCDIF_CTRL_DATA_FORMAT_24_BIT (1 << 1) +#define LCDIF_CTRL_RUN (1 << 0)
+#define LCDIF_CTRL1_COMBINE_MPU_WR_STRB (1 << 27) +#define LCDIF_CTRL1_BM_ERROR_IRQ_EN (1 << 26) +#define LCDIF_CTRL1_BM_ERROR_IRQ (1 << 25) +#define LCDIF_CTRL1_RECOVER_ON_UNDERFLOW (1 << 24) +#define LCDIF_CTRL1_INTERLACE_FIELDS (1 << 23) +#define LCDIF_CTRL1_START_INTERLACE_FROM_SECOND_FIELD (1 << 22) +#define LCDIF_CTRL1_FIFO_CLEAR (1 << 21) +#define LCDIF_CTRL1_IRQ_ON_ALTERNATE_FIELDS (1 << 20) +#define LCDIF_CTRL1_BYTE_PACKING_FORMAT_MASK (0xf << 16) +#define LCDIF_CTRL1_BYTE_PACKING_FORMAT_OFFSET 16 +#define LCDIF_CTRL1_OVERFLOW_IRQ_EN (1 << 15) +#define LCDIF_CTRL1_UNDERFLOW_IRQ_EN (1 << 14) +#define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ_EN (1 << 13) +#define LCDIF_CTRL1_VSYNC_EDGE_IRQ_EN (1 << 12) +#define LCDIF_CTRL1_OVERFLOW_IRQ (1 << 11) +#define LCDIF_CTRL1_UNDERFLOW_IRQ (1 << 10) +#define LCDIF_CTRL1_CUR_FRAME_DONE_IRQ (1 << 9) +#define LCDIF_CTRL1_VSYNC_EDGE_IRQ (1 << 8) +#define LCDIF_CTRL1_BUSY_ENABLE (1 << 2) +#define LCDIF_CTRL1_MODE86 (1 << 1) +#define LCDIF_CTRL1_RESET (1 << 0)
+#define LCDIF_CTRL2_OUTSTANDING_REQS_MASK (0x7 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_OFFSET 21 +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_1 (0x0 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_2 (0x1 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_4 (0x2 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_8 (0x3 << 21) +#define LCDIF_CTRL2_OUTSTANDING_REQS_REQ_16 (0x4 << 21) +#define LCDIF_CTRL2_BURST_LEN_8 (1 << 20) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_MASK (0x7 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_OFFSET 16 +#define LCDIF_CTRL2_ODD_LINE_PATTERN_RGB (0x0 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_RBG (0x1 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_GBR (0x2 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_GRB (0x3 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_BRG (0x4 << 16) +#define LCDIF_CTRL2_ODD_LINE_PATTERN_BGR (0x5 << 16) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_MASK (0x7 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_OFFSET 12 +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_RGB (0x0 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_RBG (0x1 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_GBR (0x2 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_GRB (0x3 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_BRG (0x4 << 12) +#define LCDIF_CTRL2_EVEN_LINE_PATTERN_BGR (0x5 << 12) +#define LCDIF_CTRL2_READ_PACK_DIR (1 << 10) +#define LCDIF_CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT (1 << 9) +#define LCDIF_CTRL2_READ_MODE_6_BIT_INPUT (1 << 8) +#define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_MASK (0x7 << 4) +#define LCDIF_CTRL2_READ_MODE_NUM_PACKED_SUBWORDS_OFFSET 4 +#define LCDIF_CTRL2_INITIAL_DUMMY_READ_MASK (0x7 << 1) +#define LCDIF_CTRL2_INITIAL_DUMMY_READ_OFFSET 1
+#define LCDIF_TRANSFER_COUNT_V_COUNT_MASK (0xffff << 16) +#define LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET 16 +#define LCDIF_TRANSFER_COUNT_H_COUNT_MASK (0xffff << 0) +#define LCDIF_TRANSFER_COUNT_H_COUNT_OFFSET 0
+#define LCDIF_CUR_BUF_ADDR_MASK 0xffffffff +#define LCDIF_CUR_BUF_ADDR_OFFSET 0
+#define LCDIF_NEXT_BUF_ADDR_MASK 0xffffffff +#define LCDIF_NEXT_BUF_ADDR_OFFSET 0
+#define LCDIF_TIMING_CMD_HOLD_MASK (0xff << 24) +#define LCDIF_TIMING_CMD_HOLD_OFFSET 24 +#define LCDIF_TIMING_CMD_SETUP_MASK (0xff << 16) +#define LCDIF_TIMING_CMD_SETUP_OFFSET 16 +#define LCDIF_TIMING_DATA_HOLD_MASK (0xff << 8) +#define LCDIF_TIMING_DATA_HOLD_OFFSET 8 +#define LCDIF_TIMING_DATA_SETUP_MASK (0xff << 0) +#define LCDIF_TIMING_DATA_SETUP_OFFSET 0
+#define LCDIF_VDCTRL0_VSYNC_OEB (1 << 29) +#define LCDIF_VDCTRL0_ENABLE_PRESENT (1 << 28) +#define LCDIF_VDCTRL0_VSYNC_POL (1 << 27) +#define LCDIF_VDCTRL0_HSYNC_POL (1 << 26) +#define LCDIF_VDCTRL0_DOTCLK_POL (1 << 25) +#define LCDIF_VDCTRL0_ENABLE_POL (1 << 24) +#define LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) +#define LCDIF_VDCTRL0_HALF_LINE (1 << 19) +#define LCDIF_VDCTRL0_HALF_LINE_MODE (1 << 18) +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_MASK 0x3ffff +#define LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_OFFSET 0
+#define LCDIF_VDCTRL1_VSYNC_PERIOD_MASK 0xffffffff +#define LCDIF_VDCTRL1_VSYNC_PERIOD_OFFSET 0
+#define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_MASK (0x3fff << 18) +#define LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET 18 +#define LCDIF_VDCTRL2_HSYNC_PERIOD_MASK 0x3ffff +#define LCDIF_VDCTRL2_HSYNC_PERIOD_OFFSET 0
+#define LCDIF_VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) +#define LCDIF_VDCTRL3_VSYNC_ONLY (1 << 28) +#define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_MASK (0xfff << 16) +#define LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET 16 +#define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_MASK (0xffff << 0) +#define LCDIF_VDCTRL3_VERTICAL_WAIT_CNT_OFFSET 0
+#define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_MASK (0x7 << 29) +#define LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET 29 +#define LCDIF_VDCTRL4_SYNC_SIGNALS_ON (1 << 18) +#define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_MASK 0x3ffff +#define LCDIF_VDCTRL4_DOTCLK_H_VALID_DATA_CNT_OFFSET 0
#endif /* __ASSEMBLER__*/ #endif /* __ASM_ARCH_MX6_IMX_REGS_H__ */
Best regards, Stefano Babic

Enable the video drivers and MXS LCDIF driver to support the splash screen on mx6sxsabresd board. Add BSP codes for video parameters and LCDIF/LVDS initialization.
"panel" env is used for selecting the display panel. Set "panel" env to "Hannstar-XGA" for LVDS display. (default) Set "panel" env to "MCIMX28LCD" for parallel LCD display.
Signed-off-by: Ye.Li B37916@freescale.com --- board/freescale/mx6sxsabresd/mx6sxsabresd.c | 161 +++++++++++++++++++++++++++ include/configs/mx6sxsabresd.h | 27 +++++- 2 files changed, 187 insertions(+), 1 deletions(-)
diff --git a/board/freescale/mx6sxsabresd/mx6sxsabresd.c b/board/freescale/mx6sxsabresd/mx6sxsabresd.c index fd8bc72..e424d0c 100644 --- a/board/freescale/mx6sxsabresd/mx6sxsabresd.c +++ b/board/freescale/mx6sxsabresd/mx6sxsabresd.c @@ -29,6 +29,11 @@ #include <usb.h> #include <usb/ehci-fsl.h>
+#ifdef CONFIG_VIDEO_MXS +#include <linux/fb.h> +#include <mxsfb.h> +#endif + DECLARE_GLOBAL_DATA_PTR;
#define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ @@ -59,6 +64,10 @@ DECLARE_GLOBAL_DATA_PTR; PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ PAD_CTL_ODE)
+#define LCD_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_100K_UP | \ + PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm) + int dram_init(void) { gd->ram_size = PHYS_SDRAM_SIZE; @@ -214,6 +223,158 @@ int power_init_board(void) return 0; }
+#ifdef CONFIG_VIDEO_MXS +static iomux_v3_cfg_t const lvds_ctrl_pads[] = { + /* CABC enable */ + MX6_PAD_QSPI1A_DATA2__GPIO4_IO_18 | MUX_PAD_CTRL(NO_PAD_CTRL), + + /* Use GPIO for Brightness adjustment, duty cycle = period */ + MX6_PAD_SD1_DATA1__GPIO6_IO_3 | MUX_PAD_CTRL(NO_PAD_CTRL), +}; + +static iomux_v3_cfg_t const lcd_pads[] = { + MX6_PAD_LCD1_CLK__LCDIF1_CLK | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_ENABLE__LCDIF1_ENABLE | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_HSYNC__LCDIF1_HSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_VSYNC__LCDIF1_VSYNC | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA00__LCDIF1_DATA_0 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA01__LCDIF1_DATA_1 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA02__LCDIF1_DATA_2 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA03__LCDIF1_DATA_3 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA04__LCDIF1_DATA_4 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA05__LCDIF1_DATA_5 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA06__LCDIF1_DATA_6 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA07__LCDIF1_DATA_7 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA08__LCDIF1_DATA_8 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA09__LCDIF1_DATA_9 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA10__LCDIF1_DATA_10 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA11__LCDIF1_DATA_11 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA12__LCDIF1_DATA_12 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA13__LCDIF1_DATA_13 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA14__LCDIF1_DATA_14 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA15__LCDIF1_DATA_15 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA16__LCDIF1_DATA_16 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA17__LCDIF1_DATA_17 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA18__LCDIF1_DATA_18 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA19__LCDIF1_DATA_19 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA20__LCDIF1_DATA_20 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA21__LCDIF1_DATA_21 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA22__LCDIF1_DATA_22 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_DATA23__LCDIF1_DATA_23 | MUX_PAD_CTRL(LCD_PAD_CTRL), + MX6_PAD_LCD1_RESET__GPIO3_IO_27 | MUX_PAD_CTRL(NO_PAD_CTRL), + + /* Use GPIO for Brightness adjustment, duty cycle = period */ + MX6_PAD_SD1_DATA2__GPIO6_IO_4 | MUX_PAD_CTRL(NO_PAD_CTRL), +}; + + +struct lcd_panel_info_t { + unsigned int lcdif_base_addr; + int depth; + void (*enable)(struct lcd_panel_info_t const *dev); + struct fb_videomode mode; +}; + +void do_enable_lvds(struct lcd_panel_info_t const *dev) +{ + setup_lvds_clock(dev->lcdif_base_addr); + + imx_iomux_v3_setup_multiple_pads(lvds_ctrl_pads, + ARRAY_SIZE(lvds_ctrl_pads)); + + /* Enable CABC */ + gpio_direction_output(IMX_GPIO_NR(4, 18) , 1); + + /* Set Brightness to high */ + gpio_direction_output(IMX_GPIO_NR(6, 3) , 1); +} + +void do_enable_parallel_lcd(struct lcd_panel_info_t const *dev) +{ + setup_lcdif_clock(dev->lcdif_base_addr); + + imx_iomux_v3_setup_multiple_pads(lcd_pads, ARRAY_SIZE(lcd_pads)); + + /* Power up the LCD */ + gpio_direction_output(IMX_GPIO_NR(3, 27) , 1); + + /* Set Brightness to high */ + gpio_direction_output(IMX_GPIO_NR(6, 4) , 1); +} + +static struct lcd_panel_info_t const displays[] = {{ + .lcdif_base_addr = LCDIF2_BASE_ADDR, + .depth = 18, + .enable = do_enable_lvds, + .mode = { + .name = "Hannstar-XGA", + .xres = 1024, + .yres = 768, + .pixclock = 15385, + .left_margin = 220, + .right_margin = 40, + .upper_margin = 21, + .lower_margin = 7, + .hsync_len = 60, + .vsync_len = 10, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED +} }, { + .lcdif_base_addr = LCDIF1_BASE_ADDR, + .depth = 24, + .enable = do_enable_parallel_lcd, + .mode = { + .name = "MCIMX28LCD", + .xres = 800, + .yres = 480, + .pixclock = 29850, + .left_margin = 89, + .right_margin = 164, + .upper_margin = 23, + .lower_margin = 10, + .hsync_len = 10, + .vsync_len = 10, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED +} } }; + +int board_video_skip(void) +{ + int i; + int ret; + char const *panel = getenv("panel"); + if (!panel) { + panel = displays[0].mode.name; + printf("No panel detected: default to %s\n", panel); + i = 0; + } else { + for (i = 0; i < ARRAY_SIZE(displays); i++) { + if (!strcmp(panel, displays[i].mode.name)) + break; + } + } + if (i < ARRAY_SIZE(displays)) { + ret = mxs_lcd_panel_setup(displays[i].mode, displays[i].depth, + displays[i].lcdif_base_addr); + if (!ret) { + if (displays[i].enable) + displays[i].enable(displays+i); + printf("Display: %s (%ux%u)\n", + displays[i].mode.name, + displays[i].mode.xres, + displays[i].mode.yres); + } else + printf("LCD %s cannot be configured: %d\n", + displays[i].mode.name, ret); + } else { + printf("unsupported panel %s\n", panel); + return -EINVAL; + } + + return 0; +} +#endif + #ifdef CONFIG_USB_EHCI_MX6 #define USB_OTHERREGS_OFFSET 0x800 #define UCTRL_PWR_POL (1 << 9) diff --git a/include/configs/mx6sxsabresd.h b/include/configs/mx6sxsabresd.h index 61a7a7a..27774f3 100644 --- a/include/configs/mx6sxsabresd.h +++ b/include/configs/mx6sxsabresd.h @@ -25,7 +25,7 @@ #define CONFIG_SYS_GENERIC_BOARD
/* Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (3 * SZ_1M) +#define CONFIG_SYS_MALLOC_LEN (10 * SZ_1M)
#define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_BOARD_LATE_INIT @@ -39,6 +39,9 @@ #define CONFIG_CONS_INDEX 1 #define CONFIG_BAUDRATE 115200
+/* VIDEO */ +#define CONFIG_VIDEO + /* Command definition */ #include <config_cmd_default.h>
@@ -49,7 +52,15 @@ #define CONFIG_LOADADDR 0x80800000 #define CONFIG_SYS_TEXT_BASE 0x87800000
+#ifdef CONFIG_VIDEO +#define CONFIG_VIDEO_MODE \ + "panel=Hannstar-XGA\0" +#else +#define CONFIG_VIDEO_MODE "" +#endif + #define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_VIDEO_MODE \ "script=boot.scr\0" \ "image=zImage\0" \ "console=ttymxc0\0" \ @@ -198,6 +209,20 @@ #define CONFIG_PHYLIB #define CONFIG_PHY_ATHEROS
+#ifdef CONFIG_VIDEO +#define CONFIG_CFB_CONSOLE +#define CONFIG_VIDEO_MXS +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_SW_CURSOR +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_SPLASH_SCREEN +#define CONFIG_SPLASH_SCREEN_ALIGN +#define CONFIG_CMD_BMP +#define CONFIG_BMP_16BPP +#define CONFIG_VIDEO_BMP_RLE8 +#define CONFIG_VIDEO_BMP_LOGO +#endif
#define CONFIG_CMD_USB #ifdef CONFIG_CMD_USB

Hi,
On 14/01/2015 10:19, Ye.Li wrote:
Add a new interface "mxs_lcd_panel_setup" to setup fb parameters and specifies the LCDIF controller for multiple controllers of iMX6SX. Pass fb parameters via "videomode" env remains work if the new interface is not called before video initialization.
Modify LCDIF clock interface "mxs_set_lcdclk" to support multiple LCDIF controllers on iMX6SX.
Signed-off-by: Ye.Li B37916@freescale.com
arch/arm/cpu/arm926ejs/mxs/clock.c | 4 +- arch/arm/include/asm/arch-mxs/clock.h | 2 +- drivers/video/mxsfb.c | 57 +++++++++++++++++++++++++++------ include/mxsfb.h | 15 +++++++++ 4 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 include/mxsfb.h
diff --git a/arch/arm/cpu/arm926ejs/mxs/clock.c b/arch/arm/cpu/arm926ejs/mxs/clock.c index e9d8800..ca020ca 100644 --- a/arch/arm/cpu/arm926ejs/mxs/clock.c +++ b/arch/arm/cpu/arm926ejs/mxs/clock.c @@ -5,7 +5,7 @@
- on behalf of DENX Software Engineering GmbH
- Based on code from LTIB:
- Copyright (C) 2010 Freescale Semiconductor, Inc.
- Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
We have already discussed that there could be problems changing the Copyright. If changes are done only by Freescale, fine. But as in this case the file is changed by other authors, it is not correct.
- SPDX-License-Identifier: GPL-2.0+
*/ @@ -309,7 +309,7 @@ void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq) bus, tgtclk, freq); }
-void mxs_set_lcdclk(uint32_t freq) +void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq) { struct mxs_clkctrl_regs *clkctrl_regs = (struct mxs_clkctrl_regs *)MXS_CLKCTRL_BASE; diff --git a/arch/arm/include/asm/arch-mxs/clock.h b/arch/arm/include/asm/arch-mxs/clock.h index fc9d75b..8840335 100644 --- a/arch/arm/include/asm/arch-mxs/clock.h +++ b/arch/arm/include/asm/arch-mxs/clock.h @@ -46,7 +46,7 @@ uint32_t mxc_get_clock(enum mxc_clock clk); void mxs_set_ioclk(enum mxs_ioclock io, uint32_t freq); void mxs_set_sspclk(enum mxs_sspclock ssp, uint32_t freq, int xtal); void mxs_set_ssp_busclock(unsigned int bus, uint32_t freq); -void mxs_set_lcdclk(uint32_t freq); +void mxs_set_lcdclk(uint32_t base_addr, uint32_t freq);
/* Compatibility with the FEC Ethernet driver */ #define imx_get_fecclk() mxc_get_clock(MXC_AHB_CLK) diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 03b0f88..2653862 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -18,6 +18,10 @@ #include <asm/imx-common/dma.h>
#include "videomodes.h" +#include <linux/string.h> +#include <linux/list.h> +#include <linux/fb.h>
#define PS2KHZ(ps) (1000000000UL / (ps))
@@ -35,6 +39,22 @@ __weak void mxsfb_system_setup(void) { }
+static int setup; +static struct fb_videomode fbmode; +static int depth;
+int mxs_lcd_panel_setup(struct fb_videomode mode, int bpp,
- uint32_t base_addr)
+{
- fbmode = mode;
- depth = bpp;
- panel.isaBase = base_addr;
- setup = 1;
- return 0;
+}
/*
- DENX M28EVK:
- setenv videomode
@@ -50,15 +70,15 @@ __weak void mxsfb_system_setup(void) static void mxs_lcd_init(GraphicDevice *panel, struct ctfb_res_modes *mode, int bpp) {
- struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)(panel->isaBase); uint32_t word_len = 0, bus_width = 0; uint8_t valid_data = 0;
/* Kick in the LCDIF clock */
- mxs_set_lcdclk(PS2KHZ(mode->pixclock));
mxs_set_lcdclk(panel->isaBase, PS2KHZ(mode->pixclock));
/* Restart the LCDIF block */
- mxs_reset_block(®s->hw_lcdif_ctrl_reg);
mxs_reset_block((struct mxs_register_32 *)®s->hw_lcdif_ctrl);
switch (bpp) { case 24:
@@ -140,15 +160,32 @@ void *video_hw_init(void)
puts("Video: ");
- /* Suck display configuration from "videomode" variable */
- penv = getenv("videomode");
- if (!penv) {
puts("MXSFB: 'videomode' variable not set!\n");
return NULL;
- if (!setup) {
/* Suck display configuration from "videomode" variable */
Suck ??
penv = getenv("videomode");
if (!penv) {
printf("MXSFB: 'videomode' variable not set!\n");
return NULL;
}
bpp = video_get_params(&mode, penv);
panel.isaBase = MXS_LCDIF_BASE;
- } else {
mode.xres = fbmode.xres;
mode.yres = fbmode.yres;
mode.pixclock = fbmode.pixclock;
mode.left_margin = fbmode.left_margin;
mode.right_margin = fbmode.right_margin;
mode.upper_margin = fbmode.upper_margin;
mode.lower_margin = fbmode.lower_margin;
mode.hsync_len = fbmode.hsync_len;
mode.vsync_len = fbmode.vsync_len;
mode.sync = fbmode.sync;
mode.vmode = fbmode.vmode;
}bpp = depth;
Ok, you want a fix setup, too. But anyway, is it not possible to get it with a CONFIG_SYS_DEFAULT_VIDEO_MODE ? This avoid the dirty trick with the static setup variable.
- bpp = video_get_params(&mode, penv);
- /* fill in Graphic device struct */ sprintf(panel.modeIdent, "%dx%dx%d", mode.xres, mode.yres, bpp);
diff --git a/include/mxsfb.h b/include/mxsfb.h new file mode 100644 index 0000000..a4e27a8 --- /dev/null +++ b/include/mxsfb.h @@ -0,0 +1,15 @@ +/*
- Copyright (C) 2014 Freescale Semiconductor, Inc.
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef __MXSFB_H__ +#define __MXSFB_H__
+#ifdef CONFIG_VIDEO_MXS +int mxs_lcd_panel_setup(struct fb_videomode mode, int bpp,
- uint32_t base_addr);
+#endif
+#endif /* __MXSFB_H__ */
Best regards, Stefano Babic
participants (2)
-
Stefano Babic
-
Ye.Li