diff options
author | Nitin Garg <nitin.garg@freescale.com> | 2014-05-27 13:00:28 -0500 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-05-27 22:18:35 -0500 |
commit | b8ab9b3eabb94bbbc1eea63e7c0e2a87d2d645f4 (patch) | |
tree | 4cf9268347e096288a54a49df79ebed78d09a3ec /board/freescale/mx6sabresd/mx6sabresd.c | |
parent | d0912be964679ada052bcd07a03d4689e84dce2e (diff) | |
download | u-boot-imx-b8ab9b3eabb94bbbc1eea63e7c0e2a87d2d645f4.zip u-boot-imx-b8ab9b3eabb94bbbc1eea63e7c0e2a87d2d645f4.tar.gz u-boot-imx-b8ab9b3eabb94bbbc1eea63e7c0e2a87d2d645f4.tar.bz2 |
ENGR00315499-7 Add EPDC splash screen for MX 6DL SabreSD and 6SL EVK
Add EPDC splash screen feature for MX6SL EVK, and MX6DL SABRESD board.
- Currently, splash screen consists of a simple black border
around a white screen. Done this way to save in memory footprint.
- EPDC splash screen is disabled by default in the config file for MX6DL_SABRESD
and MX6SL_EVK. If left enabled, the U-Boot image will not boot correctly
(hang), since some additional content on the boot device (waveform file) is
required for EPDC splash to work correctly.
Please refer to Linux Reference Manual for how to flash WAVEFORM file.
Signed-off-by: Robby Cai <R63905@freescale.com>
Signed-off-by: Nitin Garg <nitin.garg@freescale.com>
Diffstat (limited to 'board/freescale/mx6sabresd/mx6sabresd.c')
-rw-r--r-- | board/freescale/mx6sabresd/mx6sabresd.c | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/board/freescale/mx6sabresd/mx6sabresd.c b/board/freescale/mx6sabresd/mx6sabresd.c index df7df77..26859ee 100644 --- a/board/freescale/mx6sabresd/mx6sabresd.c +++ b/board/freescale/mx6sabresd/mx6sabresd.c @@ -18,6 +18,11 @@ #include <fsl_esdhc.h> #include <miiphy.h> #include <netdev.h> + +#if defined(CONFIG_MX6DL) && defined(CONFIG_MXC_EPDC) +#include <lcd.h> +#include <mxc_epdc_fb.h> +#endif #include <asm/arch/mxc_hdmi.h> #include <asm/arch/crm_regs.h> #include <linux/fb.h> @@ -44,6 +49,9 @@ DECLARE_GLOBAL_DATA_PTR; #define SPI_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST) +#define EPDC_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_HYS) + int dram_init(void) { gd->ram_size = get_ram_size((void *)PHYS_SDRAM, PHYS_SDRAM_SIZE); @@ -155,6 +163,54 @@ iomux_v3_cfg_t const di0_pads[] = { MX6_PAD_DI0_PIN3__IPU1_DI0_PIN03, /* DISP0_VSYNC */ }; +#if defined(CONFIG_MX6DL) && defined(CONFIG_MXC_EPDC) +static iomux_v3_cfg_t const epdc_enable_pads[] = { + MX6_PAD_EIM_A16__EPDC_SDDO_0 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_DA10__EPDC_SDDO_1 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_DA12__EPDC_SDDO_2 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_DA11__EPDC_SDDO_3 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_LBA__EPDC_SDDO_4 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_EB2__EPDC_SDDO_5 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_CS0__EPDC_SDDO_6 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_RW__EPDC_SDDO_7 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_A21__EPDC_GDCLK | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_A22__EPDC_GDSP | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_A23__EPDC_GDOE | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_A24__EPDC_GDRL | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_D31__EPDC_SDCLK | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_D27__EPDC_SDOE | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_DA1__EPDC_SDLE | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_EB1__EPDC_SDSHR | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_DA2__EPDC_BDR_0 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_DA4__EPDC_SDCE_0 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_DA5__EPDC_SDCE_1 | MUX_PAD_CTRL(EPDC_PAD_CTRL), + MX6_PAD_EIM_DA6__EPDC_SDCE_2 | MUX_PAD_CTRL(EPDC_PAD_CTRL), +}; + +static iomux_v3_cfg_t const epdc_disable_pads[] = { + MX6_PAD_EIM_A16__GPIO_2_22, + MX6_PAD_EIM_DA10__GPIO_3_10, + MX6_PAD_EIM_DA12__GPIO_3_12, + MX6_PAD_EIM_DA11__GPIO_3_11, + MX6_PAD_EIM_LBA__GPIO_2_27, + MX6_PAD_EIM_EB2__GPIO_2_30, + MX6_PAD_EIM_CS0__GPIO_2_23, + MX6_PAD_EIM_RW__GPIO_2_26, + MX6_PAD_EIM_A21__GPIO_2_17, + MX6_PAD_EIM_A22__GPIO_2_16, + MX6_PAD_EIM_A23__GPIO_6_6, + MX6_PAD_EIM_A24__GPIO_5_4, + MX6_PAD_EIM_D31__GPIO_3_31, + MX6_PAD_EIM_D27__GPIO_3_27, + MX6_PAD_EIM_DA1__GPIO_3_1, + MX6_PAD_EIM_EB1__GPIO_2_29, + MX6_PAD_EIM_DA2__GPIO_3_2, + MX6_PAD_EIM_DA4__GPIO_3_4, + MX6_PAD_EIM_DA5__GPIO_3_5, + MX6_PAD_EIM_DA6__GPIO_3_6, +}; +#endif + static void setup_iomux_uart(void) { imx_iomux_v3_setup_multiple_pads(uart1_pads, ARRAY_SIZE(uart1_pads)); @@ -554,6 +610,10 @@ int board_init(void) setup_spi(); #endif +#if defined(CONFIG_MX6DL) && defined(CONFIG_MXC_EPDC) + setup_epdc(); +#endif + return 0; } @@ -583,6 +643,272 @@ int checkboard(void) return 0; } +#if defined(CONFIG_MX6DL) && defined(CONFIG_MXC_EPDC) +#ifdef CONFIG_SPLASH_SCREEN +extern int mmc_get_env_devno(void); +int setup_splash_img(void) +{ +#ifdef CONFIG_SPLASH_IS_IN_MMC + int mmc_dev = mmc_get_env_devno(); + ulong offset = CONFIG_SPLASH_IMG_OFFSET; + ulong size = CONFIG_SPLASH_IMG_SIZE; + ulong addr = 0; + char *s = NULL; + struct mmc *mmc = find_mmc_device(mmc_dev); + uint blk_start, blk_cnt, n; + + s = getenv("splashimage"); + + if (NULL == s) { + puts("env splashimage not found!\n"); + return -1; + } + addr = simple_strtoul(s, NULL, 16); + + if (!mmc) { + printf("MMC Device %d not found\n", mmc_dev); + return -1; + } + + if (mmc_init(mmc)) { + puts("MMC init failed\n"); + return -1; + } + + blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; + blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; + n = mmc->block_dev.block_read(mmc_dev, blk_start, + blk_cnt, (u_char *)addr); + flush_cache((ulong)addr, blk_cnt * mmc->read_bl_len); + + return (n == blk_cnt) ? 0 : -1; +#endif + + return 0; +} +#endif + +vidinfo_t panel_info = { + .vl_refresh = 85, + .vl_col = 800, + .vl_row = 600, + .vl_pixclock = 26666667, + .vl_left_margin = 8, + .vl_right_margin = 100, + .vl_upper_margin = 4, + .vl_lower_margin = 8, + .vl_hsync = 4, + .vl_vsync = 1, + .vl_sync = 0, + .vl_mode = 0, + .vl_flag = 0, + .vl_bpix = 3, + .cmap = 0, +}; + +struct epdc_timing_params panel_timings = { + .vscan_holdoff = 4, + .sdoed_width = 10, + .sdoed_delay = 20, + .sdoez_width = 10, + .sdoez_delay = 20, + .gdclk_hp_offs = 419, + .gdsp_offs = 20, + .gdoe_offs = 0, + .gdclk_offs = 5, + .num_ce = 1, +}; + +static void setup_epdc_power(void) +{ + /* Setup epdc voltage */ + + /* EIM_A17 - GPIO2[21] for PWR_GOOD status */ + imx_iomux_v3_setup_pad(MX6_PAD_EIM_A17__GPIO_2_21 | + MUX_PAD_CTRL(EPDC_PAD_CTRL)); + /* Set as input */ + gpio_direction_input(IMX_GPIO_NR(2, 21)); + + /* EIM_D17 - GPIO3[17] for VCOM control */ + imx_iomux_v3_setup_pad(MX6_PAD_EIM_D17__GPIO_3_17 | + MUX_PAD_CTRL(EPDC_PAD_CTRL)); + + /* Set as output */ + gpio_direction_output(IMX_GPIO_NR(3, 17), 1); + + /* EIM_D20 - GPIO3[20] for EPD PMIC WAKEUP */ + imx_iomux_v3_setup_pad(MX6_PAD_EIM_D20__GPIO_3_20 | + MUX_PAD_CTRL(EPDC_PAD_CTRL)); + /* Set as output */ + gpio_direction_output(IMX_GPIO_NR(3, 20), 1); + + /* EIM_A18 - GPIO2[20] for EPD PWR CTL0 */ + imx_iomux_v3_setup_pad(MX6_PAD_EIM_A18__GPIO_2_20 | + MUX_PAD_CTRL(EPDC_PAD_CTRL)); + /* Set as output */ + gpio_direction_output(IMX_GPIO_NR(2, 20), 1); +} + +int setup_waveform_file(void) +{ +#ifdef CONFIG_WAVEFORM_FILE_IN_MMC + int mmc_dev = mmc_get_env_devno(); + ulong offset = CONFIG_WAVEFORM_FILE_OFFSET; + ulong size = CONFIG_WAVEFORM_FILE_SIZE; + ulong addr = CONFIG_WAVEFORM_BUF_ADDR; + struct mmc *mmc = find_mmc_device(mmc_dev); + uint blk_start, blk_cnt, n; + + if (!mmc) { + printf("MMC Device %d not found\n", mmc_dev); + return -1; + } + + if (mmc_init(mmc)) { + puts("MMC init failed\n"); + return -1; + } + + blk_start = ALIGN(offset, mmc->read_bl_len) / mmc->read_bl_len; + blk_cnt = ALIGN(size, mmc->read_bl_len) / mmc->read_bl_len; + n = mmc->block_dev.block_read(mmc_dev, blk_start, + blk_cnt, (u_char *)addr); + flush_cache((ulong)addr, blk_cnt * mmc->read_bl_len); + + return (n == blk_cnt) ? 0 : -1; +#else + return -1; +#endif +} + +static void epdc_enable_pins(void) +{ + /* epdc iomux settings */ + imx_iomux_v3_setup_multiple_pads(epdc_enable_pads, + ARRAY_SIZE(epdc_enable_pads)); +} + +static void epdc_disable_pins(void) +{ + /* Configure MUX settings for EPDC pins to GPIO */ + imx_iomux_v3_setup_multiple_pads(epdc_disable_pads, + ARRAY_SIZE(epdc_disable_pads)); +} + +static void setup_epdc(void) +{ + unsigned int reg; + + /*** epdc Maxim PMIC settings ***/ + + /* EPDC PWRSTAT - GPIO2[21] for PWR_GOOD status */ + imx_iomux_v3_setup_pad(MX6_PAD_EIM_A17__GPIO_2_21 | + MUX_PAD_CTRL(EPDC_PAD_CTRL)); + + /* EPDC VCOM0 - GPIO3[17] for VCOM control */ + imx_iomux_v3_setup_pad(MX6_PAD_EIM_D17__GPIO_3_17 | + MUX_PAD_CTRL(EPDC_PAD_CTRL)); + + /* UART4 TXD - GPIO3[20] for EPD PMIC WAKEUP */ + imx_iomux_v3_setup_pad(MX6_PAD_EIM_D20__GPIO_3_20 | + MUX_PAD_CTRL(EPDC_PAD_CTRL)); + + /* EIM_A18 - GPIO2[20] for EPD PWR CTL0 */ + imx_iomux_v3_setup_pad(MX6_PAD_EIM_A18__GPIO_2_20 | + MUX_PAD_CTRL(EPDC_PAD_CTRL)); + + /*** Set pixel clock rates for EPDC ***/ + + /* EPDC AXI clk (IPU2_CLK) from PFD_400M, set to 396/2 = 198MHz */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CSCDR3); + reg &= ~0x7C000; + reg |= (1 << 16) | (1 << 14); + writel(reg, CCM_BASE_ADDR + CLKCTL_CSCDR3); + + /* EPDC AXI clk enable */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3); + reg |= 0x00C0; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3); + + /* EPDC PIX clk (IPU2_DI1_CLK) from PLL5, set to 650/4/6 = ~27MHz */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CSCDR2); + reg &= ~0x3FE00; + reg |= (2 << 15) | (5 << 12); + writel(reg, CCM_BASE_ADDR + CLKCTL_CSCDR2); + + /* PLL5 enable (defaults to 650) */ + reg = readl(ANATOP_BASE_ADDR + ANATOP_PLL_VIDEO); + reg &= ~((1 << 16) | (1 << 12)); + reg |= (1 << 13); + writel(reg, ANATOP_BASE_ADDR + ANATOP_PLL_VIDEO); + + /* EPDC PIX clk enable */ + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR3); + reg |= 0x0C00; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR3); + + panel_info.epdc_data.working_buf_addr = CONFIG_WORKING_BUF_ADDR; + panel_info.epdc_data.waveform_buf_addr = CONFIG_WAVEFORM_BUF_ADDR; + + panel_info.epdc_data.wv_modes.mode_init = 0; + panel_info.epdc_data.wv_modes.mode_du = 1; + panel_info.epdc_data.wv_modes.mode_gc4 = 3; + panel_info.epdc_data.wv_modes.mode_gc8 = 2; + panel_info.epdc_data.wv_modes.mode_gc16 = 2; + panel_info.epdc_data.wv_modes.mode_gc32 = 2; + + panel_info.epdc_data.epdc_timings = panel_timings; + + setup_epdc_power(); + + /* Assign fb_base */ + gd->fb_base = CONFIG_FB_BASE; +} + +void epdc_power_on(void) +{ + unsigned int reg; + + /* Set EPD_PWR_CTL0 to high - enable EINK_VDD (3.15) */ + gpio_set_value(IMX_GPIO_NR(2, 20), 1); + udelay(1000); + + /* Enable epdc signal pin */ + epdc_enable_pins(); + + /* Set PMIC Wakeup to high - enable Display power */ + gpio_set_value(IMX_GPIO_NR(3, 20), 1); + + /* Wait for PWRGOOD == 1 */ + while (1) { + reg = readl(GPIO2_BASE_ADDR + GPIO_PSR); + if (!(reg & (1 << 21))) + break; + + udelay(100); + } + + /* Enable VCOM */ + gpio_set_value(IMX_GPIO_NR(3, 17), 1); + + udelay(500); +} + +void epdc_power_off(void) +{ + /* Set PMIC Wakeup to low - disable Display power */ + gpio_set_value(IMX_GPIO_NR(3, 20), 0); + + /* Disable VCOM */ + gpio_set_value(IMX_GPIO_NR(3, 17), 0); + + epdc_disable_pins(); + + /* Set EPD_PWR_CTL0 to low - disable EINK_VDD (3.15) */ + gpio_set_value(IMX_GPIO_NR(2, 20), 0); +} +#endif + #ifdef CONFIG_IMX_UDC iomux_v3_cfg_t const otg_udc_pads[] = { (MX6_PAD_ENET_RX_ER__USB_OTG_ID | MUX_PAD_CTRL(NO_PAD_CTRL)), |