From 237742f73998b35dd896592e19f1e119e72baa71 Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Tue, 23 Feb 2016 10:14:34 +0800 Subject: [PATCH] MLK-12425-2 video: epdc: introduce epdc support Support EPDC. E-Ink feature is supported by i.MX6DL/SL/SLL/ULL and i.MX7D. This driver supports user defined logo file, if there is no logo file, it will draw a black border around a white screen. If need to enable EPDC, a waveform file is required to let all work. Since we need LCD_MONOCHROME mode for EPDC, we introduce LCD_MONOCHROME support. Please refer to Linux Reference Manual for how to flash WAVEFORM file. Signed-off-by: Peng Fan Signed-off-by: Robby Cai Signed-off-by: Nitin Garg Signed-off-by: Ye.Li (cherry picked from commit a7244f279cc3c3994bcd103f5e9a183b1075ae71) (cherry picked from commit 21bf1c38b7d75c31875fb02a972c458f25d9c33a) --- board/freescale/common/Makefile | 1 + board/freescale/common/epdc_setup.c | 218 +++++++++++ common/lcd.c | 21 +- common/lcd_console.c | 21 +- drivers/video/Kconfig | 12 + drivers/video/Makefile | 1 + drivers/video/mxc_epdc_fb.c | 463 +++++++++++++++++++++++ include/common.h | 3 + include/lcd.h | 78 +++- include/mxc_epdc_fb.h | 552 ++++++++++++++++++++++++++++ 10 files changed, 1355 insertions(+), 15 deletions(-) create mode 100644 board/freescale/common/epdc_setup.c create mode 100644 drivers/video/mxc_epdc_fb.c create mode 100644 include/mxc_epdc_fb.h diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile index 7bc0d8b1e9..03ed125fa8 100644 --- a/board/freescale/common/Makefile +++ b/board/freescale/common/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_ZM7300) += zm7300.o obj-$(CONFIG_POWER_PFUZE100) += pfuze.o obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze.o obj-$(CONFIG_POWER_MC34VR500) += mc34vr500.o +obj-$(CONFIG_MXC_EPDC) += epdc_setup.o obj-$(CONFIG_LS102XA_STREAM_ID) += ls102xa_stream_id.o diff --git a/board/freescale/common/epdc_setup.c b/board/freescale/common/epdc_setup.c new file mode 100644 index 0000000000..c1c19480f8 --- /dev/null +++ b/board/freescale/common/epdc_setup.c @@ -0,0 +1,218 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved. + * + * Peng Fan + */ +#include +#include +#include +#include +#include +#include + +#define is_digit(c) ((c) >= '0' && (c) <= '9') +__weak int mmc_get_env_devno(void) +{ + return 0; +} +__weak int check_mmc_autodetect(void) +{ + return 0; +} + +int board_setup_waveform_file(ulong waveform_buf) +{ + char *fs_argv[5]; + char addr[17]; + ulong file_len, mmc_dev; + + if (!check_mmc_autodetect()) + mmc_dev = env_get_ulong("mmcdev", 10, 0); + else + mmc_dev = mmc_get_env_devno(); + + sprintf(addr, "%lx", waveform_buf); + + fs_argv[0] = "fatload"; + fs_argv[1] = "mmc"; + fs_argv[2] = simple_itoa(mmc_dev); + fs_argv[3] = addr; + fs_argv[4] = env_get("epdc_waveform"); + + if (!fs_argv[4]) + fs_argv[4] = "epdc_splash.bin"; + + if (do_fat_fsload(NULL, 0, 5, fs_argv)) { + printf("File %s not found on MMC Device %lu!\n", fs_argv[4], mmc_dev); + return -1; + } + + file_len = env_get_hex("filesize", 0); + if (!file_len) + return -1; + + flush_cache(waveform_buf, file_len); + + return 0; +} + +int board_setup_logo_file(void *display_buf) +{ + int logo_width, logo_height; + char *fs_argv[5]; + char addr[17]; + int array[3]; + ulong file_len, mmc_dev; + char *buf, *s; + int arg = 0, val = 0, pos = 0; + int i, j, max_check_length; + int row, col, row_end, col_end; + + if (!display_buf) + return -EINVAL; + + /* Assume PGM header not exceeds 128 bytes */ + max_check_length = 128; + + if (!check_mmc_autodetect()) + mmc_dev = env_get_ulong("mmcdev", 10, 0); + else + mmc_dev = mmc_get_env_devno(); + + memset(display_buf, 0xFF, panel_info.vl_col * panel_info.vl_row); + + fs_argv[0] = "fatsize"; + fs_argv[1] = "mmc"; + fs_argv[2] = simple_itoa(mmc_dev); + fs_argv[3] = env_get("epdc_logo"); + if (!fs_argv[3]) + fs_argv[3] = "epdc_logo.pgm"; + if (do_fat_size(NULL, 0, 4, fs_argv)) { + debug("File %s not found on MMC Device %lu, use black border\n", fs_argv[3], mmc_dev); + /* Draw black border around framebuffer*/ + memset(display_buf, 0x0, 24 * panel_info.vl_col); + for (i = 24; i < (panel_info.vl_row - 24); i++) { + memset((u8 *)display_buf + i * panel_info.vl_col, + 0x00, 24); + memset((u8 *)display_buf + i * panel_info.vl_col + + panel_info.vl_col - 24, 0x00, 24); + } + memset((u8 *)display_buf + + panel_info.vl_col * (panel_info.vl_row - 24), + 0x00, 24 * panel_info.vl_col); + return 0; + } + + file_len = env_get_hex("filesize", 0); + if (!file_len) + return -EINVAL; + + buf = memalign(ARCH_DMA_MINALIGN, file_len); + if (!buf) + return -ENOMEM; + + sprintf(addr, "%lx", (ulong)buf); + + fs_argv[0] = "fatload"; + fs_argv[1] = "mmc"; + fs_argv[2] = simple_itoa(mmc_dev); + fs_argv[3] = addr; + fs_argv[4] = env_get("epdc_logo"); + + if (!fs_argv[4]) + fs_argv[4] = "epdc_logo.pgm"; + + if (do_fat_fsload(NULL, 0, 5, fs_argv)) { + printf("File %s not found on MMC Device %lu!\n", fs_argv[4], mmc_dev); + free(buf); + return -1; + } + + if (strncmp(buf, "P5", 2)) { + printf("Wrong format for epdc logo, use PGM-P5 format.\n"); + free(buf); + return -EINVAL; + } + /* Skip P5\n */ + pos += 3; + arg = 0; + for (i = 3; i < max_check_length; ) { + /* skip \n \t and space */ + if ((buf[i] == '\n') || (buf[i] == '\t') || (buf[i] == ' ')) { + i++; + continue; + } + /* skip comment */ + if (buf[i] == '#') { + while (buf[i++] != '\n') + ; + continue; + } + + /* HEIGTH, WIDTH, MAX PIXEL VLAUE total 3 args */ + if (arg > 2) + break; + val = 0; + while (is_digit(buf[i])) { + val = val * 10 + buf[i] - '0'; + i++; + } + array[arg++] = val; + + i++; + } + + /* Point to data area */ + pos = i; + + logo_width = array[0]; + logo_height = array[1]; + + if ((logo_width > panel_info.vl_col) || + (logo_height > panel_info.vl_row)) { + printf("Picture: too big\n"); + free(buf); + return -EINVAL; + } + + /* m,m means center of screen */ + row = 0; + col = 0; + s = env_get("splashpos"); + if (s) { + if (s[0] == 'm') + col = (panel_info.vl_col - logo_width) >> 1; + else + col = simple_strtol(s, NULL, 0); + s = strchr(s + 1, ','); + if (s != NULL) { + if (s[1] == 'm') + row = (panel_info.vl_row - logo_height) >> 1; + else + row = simple_strtol(s + 1, NULL, 0); + } + } + if ((col + logo_width > panel_info.vl_col) || + (row + logo_height > panel_info.vl_row)) { + printf("Incorrect pos, use (0, 0)\n"); + row = 0; + col = 0; + } + + /* Draw picture at the center of screen */ + row_end = row + logo_height; + col_end = col + logo_width; + for (i = row; i < row_end; i++) { + for (j = col; j < col_end; j++) { + *((u8 *)display_buf + i * (panel_info.vl_col) + j) = + buf[pos++]; + } + } + + free(buf); + + flush_cache((ulong)display_buf, file_len - pos - 1); + + return 0; +} diff --git a/common/lcd.c b/common/lcd.c index cd630405d4..744d516123 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -34,11 +34,6 @@ #define CONFIG_LCD_ALIGNMENT PAGE_SIZE #endif -#if (LCD_BPP != LCD_COLOR8) && (LCD_BPP != LCD_COLOR16) && \ - (LCD_BPP != LCD_COLOR32) -#error Unsupported LCD BPP. -#endif - DECLARE_GLOBAL_DATA_PTR; static int lcd_init(void *lcdbase); @@ -170,11 +165,14 @@ int drv_lcd_init(void) void lcd_clear(void) { - int bg_color; char *s; ulong addr; static int do_splash = 1; -#if LCD_BPP == LCD_COLOR8 +#if LCD_BPP == LCD_MONOCHROME + /* Setting the palette */ + lcd_initcolregs(); + +#elif LCD_BPP == LCD_COLOR8 /* Setting the palette */ lcd_setcolreg(CONSOLE_COLOR_BLACK, 0, 0, 0); lcd_setcolreg(CONSOLE_COLOR_RED, 0xFF, 0, 0); @@ -190,11 +188,9 @@ void lcd_clear(void) #ifndef CONFIG_SYS_WHITE_ON_BLACK lcd_setfgcolor(CONSOLE_COLOR_BLACK); lcd_setbgcolor(CONSOLE_COLOR_WHITE); - bg_color = CONSOLE_COLOR_WHITE; #else lcd_setfgcolor(CONSOLE_COLOR_WHITE); lcd_setbgcolor(CONSOLE_COLOR_BLACK); - bg_color = CONSOLE_COLOR_BLACK; #endif /* CONFIG_SYS_WHITE_ON_BLACK */ #ifdef LCD_TEST_PATTERN @@ -202,14 +198,15 @@ void lcd_clear(void) #else /* set framebuffer to background color */ #if (LCD_BPP != LCD_COLOR32) - memset((char *)lcd_base, bg_color, lcd_line_length * panel_info.vl_row); + memset((char *)lcd_base, COLOR_MASK(lcd_getbgcolor()), + lcd_line_length * panel_info.vl_row); #else u32 *ppix = lcd_base; u32 i; for (i = 0; i < (lcd_line_length * panel_info.vl_row)/NBYTES(panel_info.vl_bpix); i++) { - *ppix++ = bg_color; + *ppix++ = COLOR_MASK(lcd_getbgcolor()); } #endif #endif @@ -286,7 +283,7 @@ ulong lcd_setmem(ulong addr) ulong size; int line_length; - debug("LCD panel info: %d x %d, %d bit/pix\n", panel_info.vl_col, + debug("LCD panel info: %lu x %lu, %d bit/pix\n", panel_info.vl_col, panel_info.vl_row, NBITS(panel_info.vl_bpix)); size = lcd_get_size(&line_length); diff --git a/common/lcd_console.c b/common/lcd_console.c index 7d1f883013..30085354f5 100644 --- a/common/lcd_console.c +++ b/common/lcd_console.c @@ -45,17 +45,34 @@ static void lcd_putc_xy0(struct console_t *pcons, ushort x, ushort y, char c) { int fg_color = lcd_getfgcolor(); int bg_color = lcd_getbgcolor(); - int i, row; + int row; +#if LCD_BPP == LCD_MONOCHROME + ushort off = x * (1 << LCD_BPP) % 8; +#else + int i; +#endif + fbptr_t *dst = (fbptr_t *)pcons->fbbase + y * pcons->lcdsizex + x; for (row = 0; row < VIDEO_FONT_HEIGHT; row++) { uchar bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row]; +#if LCD_BPP == LCD_MONOCHROME + uchar rest = *dst & -(1 << (8 - off)); + uchar sym; + + sym = (COLOR_MASK(fg_color) & bits) | + (COLOR_MASK(bg_color) & ~bits); + *dst++ = rest | (sym >> off); + rest = sym << (8 - off); + *dst = rest | (*dst & ((1 << (8 - off)) - 1)); +#else /* LCD_BPP == LCD_COLOR8 or LCD_COLOR16 or LCD_COLOR32 */ for (i = 0; i < VIDEO_FONT_WIDTH; ++i) { *dst++ = (bits & 0x80) ? fg_color : bg_color; bits <<= 1; } +#endif dst += (pcons->lcdsizex - VIDEO_FONT_WIDTH); } } @@ -113,7 +130,7 @@ static inline void console_newline(void) for (i = 0; i < cons.rows-rows; i++) cons.fp_console_moverow(&cons, i, i+rows); for (i = 0; i < rows; i++) - cons.fp_console_setrow(&cons, cons.rows-i-1, bg_color); + cons.fp_console_setrow(&cons, cons.rows-i-1, COLOR_MASK(bg_color)); cons.curr_row -= rows; } lcd_sync(); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8a432d94e3..1b728b543f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -584,6 +584,18 @@ config VIDEO_IMX8_HDMI help Support for HDMI i.MX8 processors. +config MXC_EPDC + bool "i.MX EPDC support" + depends on LCD && (MX7 || MX6) + help + This enable the E-ink EPD panel controller support for i.MX processors + +config WAVEFORM_BUF_SIZE + bool "The buffer size allocated for i.MX EPDC waveform file" + depends on MXC_EPDC + help + Set the buffer size for loading waveform file. + config CFB_CONSOLE bool "Enable colour frame buffer console" depends on VIDEO diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 9af0b35da7..de43597ea3 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_VIDEO_SIMPLE) += simplefb.o obj-$(CONFIG_VIDEO_TEGRA20) += tegra.o obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o obj-$(CONFIG_VIDEO_VESA) += vesa.o +obj-$(CONFIG_MXC_EPDC) += mxc_epdc_fb.o obj-y += bridge/ obj-y += sunxi/ diff --git a/drivers/video/mxc_epdc_fb.c b/drivers/video/mxc_epdc_fb.c new file mode 100644 index 0000000000..5d5806a126 --- /dev/null +++ b/drivers/video/mxc_epdc_fb.c @@ -0,0 +1,463 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved. + */ +/* + * Based on STMP378X LCDIF + * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include + +#include + +DECLARE_GLOBAL_DATA_PTR; + +void *lcd_base; /* Start of framebuffer memory */ +void *lcd_console_address; /* Start of console buffer */ + +int lcd_color_fg; +int lcd_color_bg; + +short console_col; +short console_row; + +int rev; + +void lcd_initcolregs(void) +{ +} + +void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) +{ +} + +#define TEMP_USE_DEFAULT 8 + +#define UPDATE_MODE_PARTIAL 0x0 +#define UPDATE_MODE_FULL 0x1 + +#define TRUE 1 +#define FALSE 0 + +#define msleep(a) udelay(a * 1000) + + +/******************************************************** + * Start Low-Level EPDC Functions + ********************************************************/ + +static inline void epdc_set_screen_res(u32 width, u32 height) +{ + u32 val = (height << EPDC_RES_VERTICAL_OFFSET) | width; + + REG_WR(EPDC_BASE, EPDC_RES, val); +} + +static inline void epdc_set_update_coord(u32 x, u32 y) +{ + u32 val = (y << EPDC_UPD_CORD_YCORD_OFFSET) | x; + + REG_WR(EPDC_BASE, EPDC_UPD_CORD, val); +} + +static inline void epdc_set_update_dimensions(u32 width, u32 height) +{ + u32 val = (height << EPDC_UPD_SIZE_HEIGHT_OFFSET) | width; + + REG_WR(EPDC_BASE, EPDC_UPD_SIZE, val); +} + +static void epdc_submit_update(u32 lut_num, u32 waveform_mode, u32 update_mode, + int use_test_mode, u32 np_val) +{ + u32 reg_val = 0; + + if (use_test_mode) { + reg_val |= + ((np_val << EPDC_UPD_FIXED_FIXNP_OFFSET) & + EPDC_UPD_FIXED_FIXNP_MASK) | EPDC_UPD_FIXED_FIXNP_EN; + + REG_WR(EPDC_BASE, EPDC_UPD_FIXED, reg_val); + + reg_val = EPDC_UPD_CTRL_USE_FIXED; + } else { + REG_WR(EPDC_BASE, EPDC_UPD_FIXED, reg_val); + } + + reg_val |= + ((lut_num << EPDC_UPD_CTRL_LUT_SEL_OFFSET) & + EPDC_UPD_CTRL_LUT_SEL_MASK) | + ((waveform_mode << EPDC_UPD_CTRL_WAVEFORM_MODE_OFFSET) & + EPDC_UPD_CTRL_WAVEFORM_MODE_MASK) | + update_mode; + + REG_WR(EPDC_BASE, EPDC_UPD_CTRL, reg_val); +} + +static inline int epdc_is_lut_active(u32 lut_num) +{ + u32 val = REG_RD(EPDC_BASE, EPDC_STATUS_LUTS); + int is_active = val & (1 << lut_num) ? TRUE : FALSE; + + return is_active; +} + +static void epdc_set_horizontal_timing(u32 horiz_start, u32 horiz_end, + u32 hsync_width, u32 hsync_line_length) +{ + u32 reg_val = + ((hsync_width << EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET) & + EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK) + | ((hsync_line_length << EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET) & + EPDC_TCE_HSCAN1_LINE_SYNC_MASK); + REG_WR(EPDC_BASE, EPDC_TCE_HSCAN1, reg_val); + + reg_val = + ((horiz_start << EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET) & + EPDC_TCE_HSCAN2_LINE_BEGIN_MASK) + | ((horiz_end << EPDC_TCE_HSCAN2_LINE_END_OFFSET) & + EPDC_TCE_HSCAN2_LINE_END_MASK); + REG_WR(EPDC_BASE, EPDC_TCE_HSCAN2, reg_val); +} + +static void epdc_set_vertical_timing(u32 vert_start, u32 vert_end, + u32 vsync_width) +{ + u32 reg_val = + ((vert_start << EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET) & + EPDC_TCE_VSCAN_FRAME_BEGIN_MASK) + | ((vert_end << EPDC_TCE_VSCAN_FRAME_END_OFFSET) & + EPDC_TCE_VSCAN_FRAME_END_MASK) + | ((vsync_width << EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET) & + EPDC_TCE_VSCAN_FRAME_SYNC_MASK); + REG_WR(EPDC_BASE, EPDC_TCE_VSCAN, reg_val); +} + +static void epdc_init_settings(void) +{ + u32 reg_val; + int num_ce; + + /* EPDC_CTRL */ + reg_val = REG_RD(EPDC_BASE, EPDC_CTRL); + reg_val &= ~EPDC_CTRL_UPD_DATA_SWIZZLE_MASK; + reg_val |= EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP; + reg_val &= ~EPDC_CTRL_LUT_DATA_SWIZZLE_MASK; + reg_val |= EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP; + REG_SET(EPDC_BASE, EPDC_CTRL, reg_val); + + /* EPDC_FORMAT - 2bit TFT and 4bit Buf pixel format */ + reg_val = EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT + | EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N + | ((0x0 << EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET) & + EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK); + REG_WR(EPDC_BASE, EPDC_FORMAT, reg_val); + + /* EPDC_FIFOCTRL (disabled) */ + reg_val = + ((100 << EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET) & + EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK) + | ((200 << EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET) & + EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK) + | ((100 << EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET) & + EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK); + REG_WR(EPDC_BASE, EPDC_FIFOCTRL, reg_val); + + /* EPDC_TEMP - Use default temperature */ + REG_WR(EPDC_BASE, EPDC_TEMP, TEMP_USE_DEFAULT); + + /* EPDC_RES */ + epdc_set_screen_res(panel_info.vl_col, panel_info.vl_row); + + /* + * EPDC_TCE_CTRL + * VSCAN_HOLDOFF = 4 + * VCOM_MODE = MANUAL + * VCOM_VAL = 0 + * DDR_MODE = DISABLED + * LVDS_MODE_CE = DISABLED + * LVDS_MODE = DISABLED + * DUAL_SCAN = DISABLED + * SDDO_WIDTH = 8bit + * PIXELS_PER_SDCLK = 4 + */ + reg_val = + ((panel_info.epdc_data.epdc_timings.vscan_holdoff << + EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET) & + EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK) + | EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4; + REG_WR(EPDC_BASE, EPDC_TCE_CTRL, reg_val); + + /* EPDC_TCE_HSCAN */ + epdc_set_horizontal_timing(panel_info.vl_left_margin, + panel_info.vl_right_margin, + panel_info.vl_hsync, + panel_info.vl_hsync); + + /* EPDC_TCE_VSCAN */ + epdc_set_vertical_timing(panel_info.vl_upper_margin, + panel_info.vl_lower_margin, + panel_info.vl_vsync); + + /* EPDC_TCE_OE */ + reg_val = + ((panel_info.epdc_data.epdc_timings.sdoed_width << + EPDC_TCE_OE_SDOED_WIDTH_OFFSET) & + EPDC_TCE_OE_SDOED_WIDTH_MASK) + | ((panel_info.epdc_data.epdc_timings.sdoed_delay << + EPDC_TCE_OE_SDOED_DLY_OFFSET) & + EPDC_TCE_OE_SDOED_DLY_MASK) + | ((panel_info.epdc_data.epdc_timings.sdoez_width << + EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET) & + EPDC_TCE_OE_SDOEZ_WIDTH_MASK) + | ((panel_info.epdc_data.epdc_timings.sdoez_delay << + EPDC_TCE_OE_SDOEZ_DLY_OFFSET) & + EPDC_TCE_OE_SDOEZ_DLY_MASK); + REG_WR(EPDC_BASE, EPDC_TCE_OE, reg_val); + + /* EPDC_TCE_TIMING1 */ + REG_WR(EPDC_BASE, EPDC_TCE_TIMING1, 0x0); + + /* EPDC_TCE_TIMING2 */ + reg_val = + ((panel_info.epdc_data.epdc_timings.gdclk_hp_offs << + EPDC_TCE_TIMING2_GDCLK_HP_OFFSET) & + EPDC_TCE_TIMING2_GDCLK_HP_MASK) + | ((panel_info.epdc_data.epdc_timings.gdsp_offs << + EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET) & + EPDC_TCE_TIMING2_GDSP_OFFSET_MASK); + REG_WR(EPDC_BASE, EPDC_TCE_TIMING2, reg_val); + + /* EPDC_TCE_TIMING3 */ + reg_val = + ((panel_info.epdc_data.epdc_timings.gdoe_offs << + EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET) & + EPDC_TCE_TIMING3_GDOE_OFFSET_MASK) + | ((panel_info.epdc_data.epdc_timings.gdclk_offs << + EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET) & + EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK); + REG_WR(EPDC_BASE, EPDC_TCE_TIMING3, reg_val); + + /* + * EPDC_TCE_SDCFG + * SDCLK_HOLD = 1 + * SDSHR = 1 + * NUM_CE = 1 + * SDDO_REFORMAT = FLIP_PIXELS + * SDDO_INVERT = DISABLED + * PIXELS_PER_CE = display horizontal resolution + */ + num_ce = panel_info.epdc_data.epdc_timings.num_ce; + if (num_ce == 0) + num_ce = 1; + reg_val = EPDC_TCE_SDCFG_SDCLK_HOLD | EPDC_TCE_SDCFG_SDSHR + | ((num_ce << EPDC_TCE_SDCFG_NUM_CE_OFFSET) & EPDC_TCE_SDCFG_NUM_CE_MASK) + | EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS + | ((panel_info.vl_col << EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET) & + EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK); + REG_WR(EPDC_BASE, EPDC_TCE_SDCFG, reg_val); + + /* + * EPDC_TCE_GDCFG + * GDRL = 1 + * GDOE_MODE = 0; + * GDSP_MODE = 0; + */ + reg_val = EPDC_TCE_SDCFG_GDRL; + REG_WR(EPDC_BASE, EPDC_TCE_GDCFG, reg_val); + + /* + * EPDC_TCE_POLARITY + * SDCE_POL = ACTIVE LOW + * SDLE_POL = ACTIVE HIGH + * SDOE_POL = ACTIVE HIGH + * GDOE_POL = ACTIVE HIGH + * GDSP_POL = ACTIVE LOW + */ + reg_val = EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH + | EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH + | EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH; + REG_WR(EPDC_BASE, EPDC_TCE_POLARITY, reg_val); + + /* EPDC_IRQ_MASK */ + REG_WR(EPDC_BASE, EPDC_IRQ_MASK, + EPDC_IRQ_TCE_UNDERRUN_IRQ); + + /* + * EPDC_GPIO + * PWRCOM = ? + * PWRCTRL = ? + * BDR = ? + */ + reg_val = ((0 << EPDC_GPIO_PWRCTRL_OFFSET) & EPDC_GPIO_PWRCTRL_MASK) + | ((0 << EPDC_GPIO_BDR_OFFSET) & EPDC_GPIO_BDR_MASK); + REG_WR(EPDC_BASE, EPDC_GPIO, reg_val); +} + +static void draw_mode0(void) +{ + int i; + + /* Program EPDC update to process buffer */ + epdc_set_update_coord(0, 0); + epdc_set_update_dimensions(panel_info.vl_col, panel_info.vl_row); + epdc_submit_update(0, panel_info.epdc_data.wv_modes.mode_init, + UPDATE_MODE_FULL, FALSE, 0); + + debug("Mode0 update - Waiting for LUT to complete...\n"); + + /* Will timeout after ~4-5 seconds */ + + for (i = 0; i < 40; i++) { + if (!epdc_is_lut_active(0)) { + debug("Mode0 init complete\n"); + return; + } + msleep(100); + } + + debug("Mode0 init failed!\n"); + +} + +static void draw_splash_screen(void) +{ + int i; + int lut_num = 0; + + /* Program EPDC update to process buffer */ + epdc_set_update_coord(0, 0); + epdc_set_update_dimensions(panel_info.vl_col, panel_info.vl_row); + epdc_submit_update(lut_num, panel_info.epdc_data.wv_modes.mode_gc16, + UPDATE_MODE_FULL, FALSE, 0); + + for (i = 0; i < 40; i++) { + if (!epdc_is_lut_active(lut_num)) { + debug("Splash screen update complete\n"); + return; + } + msleep(100); + } + debug("Splash screen update failed!\n"); +} + +void lcd_enable(void) +{ + if (board_setup_logo_file(lcd_base)) { + debug("Load logo failed!\n"); + return; + } + + epdc_power_on(); + + flush_cache((ulong)lcd_base, panel_info.vl_col * panel_info.vl_row); + + /* Draw data to display */ + draw_mode0(); + + draw_splash_screen(); +} + +void lcd_disable(void) +{ + debug("lcd_disable\n"); + + /* Disable clocks to EPDC */ + REG_SET(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_CLKGATE); +} + +void lcd_panel_disable(void) +{ + epdc_power_off(); +} + +void lcd_ctrl_init(void *lcdbase) +{ + unsigned int val; + + /* + * We rely on lcdbase being a physical address, i.e., either MMU off, + * or 1-to-1 mapping. Might want to add some virt2phys here. + */ + if (!lcdbase) + return; + + panel_info.epdc_data.working_buf_addr = (u_long)memalign(ARCH_DMA_MINALIGN, + panel_info.vl_col * panel_info.vl_row * 2); + + if (!panel_info.epdc_data.working_buf_addr) { + printf("EPDC: Error allocating working buffer!\n"); + return; + } + + panel_info.epdc_data.waveform_buf_addr = (u_long)memalign(ARCH_DMA_MINALIGN, + CONFIG_WAVEFORM_BUF_SIZE); + + if (!panel_info.epdc_data.waveform_buf_addr) { + printf("EPDC: Error allocating waveform buffer!\n"); + return; + } + + lcd_color_fg = 0xFF; + lcd_color_bg = 0xFF; + + /* Reset */ + REG_SET(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_SFTRST); + while (!(REG_RD(EPDC_BASE, EPDC_CTRL) & EPDC_CTRL_CLKGATE)) + ; + REG_CLR(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_SFTRST); + + /* Enable clock gating (clear to enable) */ + REG_CLR(EPDC_BASE, EPDC_CTRL, EPDC_CTRL_CLKGATE); + while (REG_RD(EPDC_BASE, EPDC_CTRL) & + (EPDC_CTRL_SFTRST | EPDC_CTRL_CLKGATE)) + ; + + debug("resolution %dx%d, bpp %d\n", (int)panel_info.vl_col, + (int)panel_info.vl_row, NBITS(panel_info.vl_bpix)); + + /* Get EPDC version */ + val = REG_RD(EPDC_BASE, EPDC_VERSION); + rev = ((val & EPDC_VERSION_MAJOR_MASK) >> + EPDC_VERSION_MAJOR_OFFSET) * 10 + + ((val & EPDC_VERSION_MINOR_MASK) >> + EPDC_VERSION_MINOR_OFFSET); + + /* Set framebuffer pointer */ + REG_WR(EPDC_BASE, EPDC_UPD_ADDR, (u32)lcdbase); + + /* Set Working Buffer pointer */ + REG_WR(EPDC_BASE, EPDC_WB_ADDR, panel_info.epdc_data.working_buf_addr); + if (rev > 20) + REG_WR(EPDC_BASE, EPDC_WB_ADDR_TCE, panel_info.epdc_data.working_buf_addr); + + /* Get waveform data address and offset */ + if (board_setup_waveform_file(panel_info.epdc_data.waveform_buf_addr)) { + printf("Can't load waveform data!\n"); + return; + } + + /* Set Waveform Buffer pointer */ + REG_WR(EPDC_BASE, EPDC_WVADDR, + panel_info.epdc_data.waveform_buf_addr); + + /* Initialize EPDC, passing pointer to EPDC registers */ + epdc_init_settings(); + + lcd_base = lcdbase; + + return; +} + +ulong calc_fbsize(void) +{ + return panel_info.vl_row * panel_info.vl_col * 2 \ + * NBITS(panel_info.vl_bpix) / 8; +} + diff --git a/include/common.h b/include/common.h index 2c21dee850..c248e575ff 100644 --- a/include/common.h +++ b/include/common.h @@ -139,6 +139,9 @@ extern ulong save_size; /* Default Save Size */ /* common/cmd_net.c */ int do_tftpb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +/* common/cmd_fat.c */ +int do_fat_size(cmd_tbl_t *, int, int, char * const []); + /* common/cmd_fat.c */ int do_fat_fsload(cmd_tbl_t *, int, int, char * const []); diff --git a/include/lcd.h b/include/lcd.h index cb6b6a4d12..e3eb358ff0 100644 --- a/include/lcd.h +++ b/include/lcd.h @@ -30,6 +30,7 @@ extern struct vidinfo panel_info; void lcd_ctrl_init(void *lcdbase); void lcd_enable(void); void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue); +void lcd_initcolregs (void); /** * Set whether we need to flush the dcache when changing the LCD image. This @@ -46,6 +47,64 @@ void lcd_set_flush_dcache(int flush); #include #elif defined(CONFIG_EXYNOS_FB) #include +#elif defined(CONFIG_MXC_EPDC) + +struct waveform_modes { + int mode_init; + int mode_du; + int mode_gc4; + int mode_gc8; + int mode_gc16; + int mode_gc32; +}; + +struct epdc_timing_params { + int vscan_holdoff; + int sdoed_width; + int sdoed_delay; + int sdoez_width; + int sdoez_delay; + int gdclk_hp_offs; + int gdsp_offs; + int gdoe_offs; + int gdclk_offs; + int num_ce; +}; + +struct epdc_data_struct { + /* EPDC buffer pointers */ + u_long working_buf_addr; + u_long waveform_buf_addr; + + /* Waveform mode definitions */ + struct waveform_modes wv_modes; + struct epdc_timing_params epdc_timings; +}; + +typedef struct vidinfo { + u_long vl_refresh; /* Refresh Rate Hz */ + u_long vl_row; /* resolution in x */ + u_long vl_col; /* resolution in y */ + u_long vl_rot; + u_long vl_pixclock; /* pixel clock in picoseconds */ + u_long vl_left_margin; /* Horizontal back porch */ + u_long vl_right_margin; /* Horizontal front porch */ + u_long vl_upper_margin; /* Vertical back porch */ + u_long vl_lower_margin; /* Vertical front porch */ + u_long vl_hsync; /* Horizontal sync pulse length */ + u_long vl_vsync; /* Vertical sync pulse length */ + u_long vl_sync; /* Polarity on data enable */ + u_long vl_mode; /* Video Mode */ + u_long vl_flag; + u_char vl_bpix; + ushort *cmap; + struct epdc_data_struct epdc_data; +} vidinfo_t; + +static __maybe_unused ushort *configuration_get_cmap(void) +{ + return panel_info.cmap; +} #else typedef struct vidinfo { ushort vl_col; /* Number of columns (i.e. 160) */ @@ -162,6 +221,16 @@ void lcd_sync(void); #define LCD_BPP LCD_COLOR8 #endif +#if LCD_BPP == LCD_MONOCHROME +# define COLOR_MASK(c) ((c) | (c) << 1 | (c) << 2 | (c) << 3 | \ + (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7) +#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) || \ + (LCD_BPP == LCD_COLOR32) +# define COLOR_MASK(c) (c) +#else +#error Unsupported LCD BPP. +#endif + #ifndef LCD_DF #define LCD_DF 1 #endif @@ -170,7 +239,14 @@ void lcd_sync(void); #define NBITS(bit_code) (1 << (bit_code)) #define NCOLORS(bit_code) (1 << NBITS(bit_code)) -#if LCD_BPP == LCD_COLOR8 +#if LCD_BPP == LCD_MONOCHROME +/* + * Simple black/white definitions + */ +# define CONSOLE_COLOR_BLACK 0 +# define CONSOLE_COLOR_WHITE 1 /* Must remain last / highest */ + +#elif LCD_BPP == LCD_COLOR8 # define CONSOLE_COLOR_BLACK 0 # define CONSOLE_COLOR_RED 1 # define CONSOLE_COLOR_GREEN 2 diff --git a/include/mxc_epdc_fb.h b/include/mxc_epdc_fb.h new file mode 100644 index 0000000000..9aef8a1729 --- /dev/null +++ b/include/mxc_epdc_fb.h @@ -0,0 +1,552 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved. + * + */ +#ifndef __EPDC_REGS_INCLUDED__ +#define __EPDC_REGS_INCLUDED__ + +#include +#include +#include + +/************************************* + * Register addresses + *************************************/ +#define EPDC_BASE (EPDC_BASE_ADDR) + +#define EPDC_CTRL 0x000 +#define EPDC_CTRL_SET 0x004 +#define EPDC_CTRL_CLR 0x008 +#define EPDC_CTRL_TOG 0x00C +#define EPDC_WVADDR 0x020 +#define EPDC_WB_ADDR 0x030 +#define EPDC_RES 0x040 +#define EPDC_FORMAT 0x050 +#define EPDC_FORMAT_SET 0x054 +#define EPDC_FORMAT_CLR 0x058 +#define EPDC_FORMAT_TOG 0x05C +#define EPDC_WB_FIELD0 0x060 +#define EPDC_WB_FIELD0_SET 0x064 +#define EPDC_WB_FIELD0_CLR 0x068 +#define EPDC_WB_FIELD0_TOG 0x06C +#define EPDC_WB_FIELD1 0x070 +#define EPDC_WB_FIELD1_SET 0x074 +#define EPDC_WB_FIELD1_CLR 0x078 +#define EPDC_WB_FIELD1_TOG 0x07C +#define EPDC_WB_FIELD2 0x080 +#define EPDC_WB_FIELD2_SET 0x084 +#define EPDC_WB_FIELD2_CLR 0x088 +#define EPDC_WB_FIELD2_TOG 0x08C +#define EPDC_WB_FIELD3 0x090 +#define EPDC_WB_FIELD3_SET 0x094 +#define EPDC_WB_FIELD3_CLR 0x098 +#define EPDC_WB_FIELD3_TOG 0x09C +#define EPDC_FIFOCTRL 0x0A0 +#define EPDC_FIFOCTRL_SET 0x0A4 +#define EPDC_FIFOCTRL_CLR 0x0A8 +#define EPDC_FIFOCTRL_TOG 0x0AC +#define EPDC_UPD_ADDR 0x100 +#define EPDC_UPD_STRIDE 0x110 +#define EPDC_UPD_CORD 0x120 +#define EPDC_UPD_SIZE 0x140 +#define EPDC_UPD_CTRL 0x160 +#define EPDC_UPD_FIXED 0x180 +#define EPDC_TEMP 0x1A0 +#define EPDC_AUTOWV_LUT 0x1C0 +#define EPDC_LUT_STANDBY1 0x1E0 +#define EPDC_LUT_STANDBY1_SET 0x1E4 +#define EPDC_LUT_STANDBY1_CLR 0x1E8 +#define EPDC_LUT_STANDBY1_TOG 0x1EC +#define EPDC_LUT_STANDBY2 0x1F0 +#define EPDC_LUT_STANDBY2_SET 0x1F4 +#define EPDC_LUT_STANDBY2_CLR 0x1F8 +#define EPDC_LUT_STANDBY2_TOG 0x1FC +#define EPDC_TCE_CTRL 0x200 +#define EPDC_TCE_SDCFG 0x220 +#define EPDC_TCE_GDCFG 0x240 +#define EPDC_TCE_HSCAN1 0x260 +#define EPDC_TCE_HSCAN2 0x280 +#define EPDC_TCE_VSCAN 0x2A0 +#define EPDC_TCE_OE 0x2C0 +#define EPDC_TCE_POLARITY 0x2E0 +#define EPDC_TCE_TIMING1 0x300 +#define EPDC_TCE_TIMING2 0x310 +#define EPDC_TCE_TIMING3 0x320 +#define EPDC_PIGEON_CTRL0 0x380 +#define EPDC_PIGEON_CTRL1 0x390 +#define EPDC_IRQ_MASK1 0x3C0 +#define EPDC_IRQ_MASK1_SET 0x3C4 +#define EPDC_IRQ_MASK1_CLR 0x3C8 +#define EPDC_IRQ_MASK1_TOG 0x3CC +#define EPDC_IRQ_MASK2 0x3D0 +#define EPDC_IRQ_MASK2_SET 0x3D4 +#define EPDC_IRQ_MASK2_CLR 0x3D8 +#define EPDC_IRQ_MASK2_TOG 0x3DC +#define EPDC_IRQ1 0x3E0 +#define EPDC_IRQ1_SET 0x3E4 +#define EPDC_IRQ1_CLR 0x3E8 +#define EPDC_IRQ1_TOG 0x3EC +#define EPDC_IRQ2 0x3F0 +#define EPDC_IRQ2_SET 0x3F4 +#define EPDC_IRQ2_CLR 0x3F8 +#define EPDC_IRQ2_TOG 0x3FC +#define EPDC_IRQ_MASK 0x400 +#define EPDC_IRQ_MASK_SET 0x404 +#define EPDC_IRQ_MASK_CLR 0x408 +#define EPDC_IRQ_MASK_TOG 0x40C +#define EPDC_IRQ 0x420 +#define EPDC_IRQ_SET 0x424 +#define EPDC_IRQ_CLR 0x428 +#define EPDC_IRQ_TOG 0x42C +#define EPDC_STATUS_LUTS 0x440 +#define EPDC_STATUS_LUTS_SET 0x444 +#define EPDC_STATUS_LUTS_CLR 0x448 +#define EPDC_STATUS_LUTS_TOG 0x44C +#define EPDC_STATUS_LUTS2 0x450 +#define EPDC_STATUS_LUTS2_SET 0x454 +#define EPDC_STATUS_LUTS2_CLR 0x458 +#define EPDC_STATUS_LUTS2_TOG 0x45C +#define EPDC_STATUS_NEXTLUT 0x460 +#define EPDC_STATUS_COL 0x480 +#define EPDC_STATUS_COL2 0x490 +#define EPDC_STATUS 0x4A0 +#define EPDC_STATUS_SET 0x4A4 +#define EPDC_STATUS_CLR 0x4A8 +#define EPDC_STATUS_TOG 0x4AC +#define EPDC_UPD_COL_CORD 0x4C0 +#define EPDC_UPD_COL_SIZE 0x4E0 +#define EPDC_DEBUG 0x500 +#define EPDC_DEBUG_LUT 0x530 +#define EPDC_HIST1_PARAM 0x600 +#define EPDC_HIST2_PARAM 0x610 +#define EPDC_HIST4_PARAM 0x620 +#define EPDC_HIST8_PARAM0 0x630 +#define EPDC_HIST8_PARAM1 0x640 +#define EPDC_HIST16_PARAM0 0x650 +#define EPDC_HIST16_PARAM1 0x660 +#define EPDC_HIST16_PARAM2 0x670 +#define EPDC_HIST16_PARAM3 0x680 +#define EPDC_GPIO 0x700 +#define EPDC_VERSION 0x7F0 +#define EPDC_PIGEON_0_0 0x800 +#define EPDC_PIGEON_0_1 0x810 +#define EPDC_PIGEON_0_2 0x820 +#define EPDC_PIGEON_1_0 0x840 +#define EPDC_PIGEON_1_1 0x850 +#define EPDC_PIGEON_1_2 0x860 +#define EPDC_PIGEON_2_0 0x880 +#define EPDC_PIGEON_2_1 0x890 +#define EPDC_PIGEON_2_2 0x8A0 +#define EPDC_PIGEON_3_0 0x8C0 +#define EPDC_PIGEON_3_1 0x8D0 +#define EPDC_PIGEON_3_2 0x8E0 +#define EPDC_PIGEON_4_0 0x900 +#define EPDC_PIGEON_4_1 0x910 +#define EPDC_PIGEON_4_2 0x920 +#define EPDC_PIGEON_5_0 0x940 +#define EPDC_PIGEON_5_1 0x950 +#define EPDC_PIGEON_5_2 0x960 +#define EPDC_PIGEON_6_0 0x980 +#define EPDC_PIGEON_6_1 0x990 +#define EPDC_PIGEON_6_2 0x9A0 +#define EPDC_PIGEON_7_0 0x9C0 +#define EPDC_PIGEON_7_1 0x9D0 +#define EPDC_PIGEON_7_2 0x9E0 +#define EPDC_PIGEON_8_0 0xA00 +#define EPDC_PIGEON_8_1 0xA10 +#define EPDC_PIGEON_8_2 0xA20 +#define EPDC_PIGEON_9_0 0xA40 +#define EPDC_PIGEON_9_1 0xA50 +#define EPDC_PIGEON_9_2 0xA60 +#define EPDC_PIGEON_10_0 0xA80 +#define EPDC_PIGEON_10_1 0xA90 +#define EPDC_PIGEON_10_2 0xAA0 +#define EPDC_PIGEON_11_0 0xAC0 +#define EPDC_PIGEON_11_1 0xAD0 +#define EPDC_PIGEON_11_2 0xAE0 +#define EPDC_PIGEON_12_0 0xB00 +#define EPDC_PIGEON_12_1 0xB10 +#define EPDC_PIGEON_12_2 0xB20 +#define EPDC_PIGEON_13_0 0xB40 +#define EPDC_PIGEON_13_1 0xB50 +#define EPDC_PIGEON_13_2 0xB60 +#define EPDC_PIGEON_14_0 0xB80 +#define EPDC_PIGEON_14_1 0xB90 +#define EPDC_PIGEON_14_2 0xBA0 +#define EPDC_PIGEON_15_0 0xBC0 +#define EPDC_PIGEON_15_1 0xBD0 +#define EPDC_PIGEON_15_2 0xBE0 +#define EPDC_PIGEON_16_0 0xC00 +#define EPDC_PIGEON_16_1 0xC10 +#define EPDC_PIGEON_16_2 0xC20 +#if defined(CONFIG_MX7) || defined(CONFIG_MX6ULL) || defined(CONFIG_MX6SLL) +#define EPDC_WB_ADDR_TCE 0x010 +#else +#define EPDC_WB_ADDR_TCE 0xC10 +#endif + +#define REG_RD(base, reg) \ + (*(volatile unsigned int *)((base) + (reg))) +#define REG_WR(base, reg, value) \ + ((*(volatile unsigned int *)((base) + (reg))) = (value)) +#define REG_SET(base, reg, value) \ + ((*(volatile unsigned int *)((base) + (reg ## _SET))) = (value)) +#define REG_CLR(base, reg, value) \ + ((*(volatile unsigned int *)((base) + (reg ## _CLR))) = (value)) +#define REG_TOG(base, reg, value) \ + ((*(volatile unsigned int *)((base) + (reg ## _TOG))) = (value)) +/* + * Register field definitions + */ + +enum { +/* EPDC_CTRL field values */ + EPDC_CTRL_SFTRST = 0x80000000, + EPDC_CTRL_CLKGATE = 0x40000000, + EPDC_CTRL_SRAM_POWERDOWN = 0x100, + EPDC_CTRL_UPD_DATA_SWIZZLE_MASK = 0xC0, + EPDC_CTRL_UPD_DATA_SWIZZLE_NO_SWAP = 0, + EPDC_CTRL_UPD_DATA_SWIZZLE_ALL_BYTES_SWAP = 0x40, + EPDC_CTRL_UPD_DATA_SWIZZLE_HWD_SWAP = 0x80, + EPDC_CTRL_UPD_DATA_SWIZZLE_HWD_BYTE_SWAP = 0xC0, + EPDC_CTRL_LUT_DATA_SWIZZLE_MASK = 0x30, + EPDC_CTRL_LUT_DATA_SWIZZLE_NO_SWAP = 0, + EPDC_CTRL_LUT_DATA_SWIZZLE_ALL_BYTES_SWAP = 0x10, + EPDC_CTRL_LUT_DATA_SWIZZLE_HWD_SWAP = 0x20, + EPDC_CTRL_LUT_DATA_SWIZZLE_HWD_BYTE_SWAP = 0x30, + EPDC_CTRL_BURST_LEN_8_8 = 0x1, + EPDC_CTRL_BURST_LEN_8_16 = 0, + +/* EPDC_RES field values */ + EPDC_RES_VERTICAL_MASK = 0x1FFF0000, + EPDC_RES_VERTICAL_OFFSET = 16, + EPDC_RES_HORIZONTAL_MASK = 0x1FFF, + EPDC_RES_HORIZONTAL_OFFSET = 0, + +/* EPDC_FORMAT field values */ + EPDC_FORMAT_BUF_PIXEL_SCALE_ROUND = 0x1000000, + EPDC_FORMAT_DEFAULT_TFT_PIXEL_MASK = 0xFF0000, + EPDC_FORMAT_DEFAULT_TFT_PIXEL_OFFSET = 16, + EPDC_FORMAT_WB_ADDR_NO_COPY = 0x4000, + EPDC_FORMAT_WB_TYPE_MASK = 0x3000, + EPDC_FORMAT_WB_TYPE_OFFSET = 12, + EPDC_FORMAT_WB_TYPE_WB_INTERNAL = 0x0, + EPDC_FORMAT_WB_TYPE_WB_WAVEFORM = 0x1000, + EPDC_FORMAT_WB_TYPE_WB_EXTERNAL16 = 0x2000, + EPDC_FORMAT_WB_TYPE_WB_EXTERNAL32 = 0x3000, + EPDC_FORMAT_WB_COMPRESS = 0x800, + EPDC_FORMAT_BUF_PIXEL_FORMAT_MASK = 0x700, + EPDC_FORMAT_BUF_PIXEL_FORMAT_P2N = 0x200, + EPDC_FORMAT_BUF_PIXEL_FORMAT_P3N = 0x300, + EPDC_FORMAT_BUF_PIXEL_FORMAT_P4N = 0x400, + EPDC_FORMAT_BUF_PIXEL_FORMAT_P5N = 0x500, + EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT = 0x0, + EPDC_FORMAT_TFT_PIXEL_FORMAT_2BIT_VCOM = 0x1, + EPDC_FORMAT_TFT_PIXEL_FORMAT_4BIT = 0x2, + EPDC_FORMAT_TFT_PIXEL_FORMAT_4BIT_VCOM = 0x3, + +/* EPDC_WB_FIELD field values */ + EPDC_WB_FIELD_FIXED_MASK = 0xFF000000, + EPDC_WB_FIELD_FIXED_OFFSET = 24, + EPDC_WB_FIELD_USE_FIXED_MASK = 0x30000, + EPDC_WB_FIELD_USE_FIXED_OFFSET = 16, + EPDC_WB_FIELD_USE_FIXED_NO_FIXED = 0x0, + EPDC_WB_FIELD_USE_FIXED_USE_FIXED = 0x1, + EPDC_WB_FIELD_USE_FIXED_NE_FIXED = 0x2, + EPDC_WB_FIELD_USE_FIXED_EQ_FIXED = 0x3, + EPDC_WB_FIELD_USAGE_MASK = 0xE000, + EPDC_WB_FIELD_USAGE_OFFSET = 13, + EPDC_WB_FIELD_USAGE_NOT_USED = 0x0, + EPDC_WB_FIELD_USAGE_PARTIAL = 0x3, + EPDC_WB_FIELD_USAGE_LUT = 0x4, + EPDC_WB_FIELD_USAGE_CP = 0x5, + EPDC_WB_FIELD_USAGE_NP = 0x6, + EPDC_WB_FIELD_USAGE_PTS = 0x7, + EPDC_WB_FIELD_FROM_MASK = 0x1F00, + EPDC_WB_FIELD_FROM_OFFSET = 8, + EPDC_WB_FIELD_TO_MASK = 0xF0, + EPDC_WB_FIELD_TO_OFFSET = 4, + EPDC_WB_FIELD_LEN_MASK = 0xF, + EPDC_WB_FIELD_LEN_OFFSET = 0, + +/* EPDC_FIFOCTRL field values */ + EPDC_FIFOCTRL_ENABLE_PRIORITY = 0x80000000, + EPDC_FIFOCTRL_FIFO_INIT_LEVEL_MASK = 0xFF0000, + EPDC_FIFOCTRL_FIFO_INIT_LEVEL_OFFSET = 16, + EPDC_FIFOCTRL_FIFO_H_LEVEL_MASK = 0xFF00, + EPDC_FIFOCTRL_FIFO_H_LEVEL_OFFSET = 8, + EPDC_FIFOCTRL_FIFO_L_LEVEL_MASK = 0xFF, + EPDC_FIFOCTRL_FIFO_L_LEVEL_OFFSET = 0, + +/* EPDC_UPD_CORD field values */ + EPDC_UPD_CORD_YCORD_MASK = 0x1FFF0000, + EPDC_UPD_CORD_YCORD_OFFSET = 16, + EPDC_UPD_CORD_XCORD_MASK = 0x1FFF, + EPDC_UPD_CORD_XCORD_OFFSET = 0, + +/* EPDC_UPD_SIZE field values */ + EPDC_UPD_SIZE_HEIGHT_MASK = 0x1FFF0000, + EPDC_UPD_SIZE_HEIGHT_OFFSET = 16, + EPDC_UPD_SIZE_WIDTH_MASK = 0x1FFF, + EPDC_UPD_SIZE_WIDTH_OFFSET = 0, + +/* EPDC_UPD_CTRL field values */ + EPDC_UPD_CTRL_USE_FIXED = 0x80000000, +#if defined(CONFIG_MX7) || defined(CONFIG_MX6ULL) || defined(CONFIG_MX6SLL) + EPDC_UPD_CTRL_LUT_SEL_MASK = 0x3F0000, +#else + EPDC_UPD_CTRL_LUT_SEL_MASK = 0xF0000, +#endif + EPDC_UPD_CTRL_LUT_SEL_OFFSET = 16, + EPDC_UPD_CTRL_WAVEFORM_MODE_MASK = 0xFF00, + EPDC_UPD_CTRL_WAVEFORM_MODE_OFFSET = 8, + EPDC_UPD_CTRL_NO_LUT_CANCEL = 0x10, + EPDC_UPD_CTRL_AUTOWV_PAUSE = 0x8, + EPDC_UPD_CTRL_AUTOWV = 0x4, + EPDC_UPD_CTRL_DRY_RUN = 0x2, + EPDC_UPD_CTRL_UPDATE_MODE_FULL = 0x1, + +/* EPDC_UPD_FIXED field values */ + EPDC_UPD_FIXED_FIXNP_EN = 0x80000000, + EPDC_UPD_FIXED_FIXCP_EN = 0x40000000, + EPDC_UPD_FIXED_FIXNP_MASK = 0xFF00, + EPDC_UPD_FIXED_FIXNP_OFFSET = 8, + EPDC_UPD_FIXED_FIXCP_MASK = 0xFF, + EPDC_UPD_FIXED_FIXCP_OFFSET = 0, + +/* EPDC_AUTOWV_LUT field values */ + EPDC_AUTOWV_LUT_DATA_MASK = 0xFF0000, + EPDC_AUTOWV_LUT_DATA_OFFSET = 16, +#if defined(CONFIG_MX7) || defined(CONFIG_MX6ULL) || defined(CONFIG_MX6SLL) + EPDC_AUTOWV_LUT_ADDR_MASK = 0x7, +#else + EPDC_AUTOWV_LUT_ADDR_MASK = 0xFF, +#endif + EPDC_AUTOWV_LUT_ADDR_OFFSET = 0, + +/* EPDC_TCE_CTRL field values */ + EPDC_TCE_CTRL_VSCAN_HOLDOFF_MASK = 0x1FF0000, + EPDC_TCE_CTRL_VSCAN_HOLDOFF_OFFSET = 16, + EPDC_TCE_CTRL_VCOM_VAL_MASK = 0xC00, + EPDC_TCE_CTRL_VCOM_VAL_OFFSET = 10, + EPDC_TCE_CTRL_VCOM_MODE_AUTO = 0x200, + EPDC_TCE_CTRL_VCOM_MODE_MANUAL = 0x000, + EPDC_TCE_CTRL_DDR_MODE_ENABLE = 0x100, + EPDC_TCE_CTRL_LVDS_MODE_CE_ENABLE = 0x80, + EPDC_TCE_CTRL_LVDS_MODE_ENABLE = 0x40, + EPDC_TCE_CTRL_SCAN_DIR_1_UP = 0x20, + EPDC_TCE_CTRL_SCAN_DIR_0_UP = 0x10, + EPDC_TCE_CTRL_DUAL_SCAN_ENABLE = 0x8, + EPDC_TCE_CTRL_SDDO_WIDTH_16BIT = 0x4, + EPDC_TCE_CTRL_PIXELS_PER_SDCLK_2 = 1, + EPDC_TCE_CTRL_PIXELS_PER_SDCLK_4 = 2, + EPDC_TCE_CTRL_PIXELS_PER_SDCLK_8 = 3, + +/* EPDC_TCE_SDCFG field values */ + EPDC_TCE_SDCFG_SDCLK_HOLD = 0x200000, + EPDC_TCE_SDCFG_SDSHR = 0x100000, + EPDC_TCE_SDCFG_NUM_CE_MASK = 0xF0000, + EPDC_TCE_SDCFG_NUM_CE_OFFSET = 16, + EPDC_TCE_SDCFG_SDDO_REFORMAT_STANDARD = 0, + EPDC_TCE_SDCFG_SDDO_REFORMAT_FLIP_PIXELS = 0x4000, + EPDC_TCE_SDCFG_SDDO_INVERT_ENABLE = 0x2000, + EPDC_TCE_SDCFG_PIXELS_PER_CE_MASK = 0x1FFF, + EPDC_TCE_SDCFG_PIXELS_PER_CE_OFFSET = 0, + +/* EPDC_TCE_GDCFG field values */ + EPDC_TCE_SDCFG_GDRL = 0x10, + EPDC_TCE_SDCFG_GDOE_MODE_DELAYED_GDCLK = 0x2, + EPDC_TCE_SDCFG_GDSP_MODE_FRAME_SYNC = 0x1, + EPDC_TCE_SDCFG_GDSP_MODE_ONE_LINE = 0x0, + +/* EPDC_TCE_HSCAN1 field values */ + EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_MASK = 0xFFF0000, + EPDC_TCE_HSCAN1_LINE_SYNC_WIDTH_OFFSET = 16, + EPDC_TCE_HSCAN1_LINE_SYNC_MASK = 0xFFF, + EPDC_TCE_HSCAN1_LINE_SYNC_OFFSET = 0, + +/* EPDC_TCE_HSCAN2 field values */ + EPDC_TCE_HSCAN2_LINE_END_MASK = 0xFFF0000, + EPDC_TCE_HSCAN2_LINE_END_OFFSET = 16, + EPDC_TCE_HSCAN2_LINE_BEGIN_MASK = 0xFFF, + EPDC_TCE_HSCAN2_LINE_BEGIN_OFFSET = 0, + +/* EPDC_TCE_VSCAN field values */ + EPDC_TCE_VSCAN_FRAME_END_MASK = 0xFF0000, + EPDC_TCE_VSCAN_FRAME_END_OFFSET = 16, + EPDC_TCE_VSCAN_FRAME_BEGIN_MASK = 0xFF00, + EPDC_TCE_VSCAN_FRAME_BEGIN_OFFSET = 8, + EPDC_TCE_VSCAN_FRAME_SYNC_MASK = 0xFF, + EPDC_TCE_VSCAN_FRAME_SYNC_OFFSET = 0, + +/* EPDC_TCE_OE field values */ + EPDC_TCE_OE_SDOED_WIDTH_MASK = 0xFF000000, + EPDC_TCE_OE_SDOED_WIDTH_OFFSET = 24, + EPDC_TCE_OE_SDOED_DLY_MASK = 0xFF0000, + EPDC_TCE_OE_SDOED_DLY_OFFSET = 16, + EPDC_TCE_OE_SDOEZ_WIDTH_MASK = 0xFF00, + EPDC_TCE_OE_SDOEZ_WIDTH_OFFSET = 8, + EPDC_TCE_OE_SDOEZ_DLY_MASK = 0xFF, + EPDC_TCE_OE_SDOEZ_DLY_OFFSET = 0, + +/* EPDC_TCE_POLARITY field values */ + EPDC_TCE_POLARITY_GDSP_POL_ACTIVE_HIGH = 0x10, + EPDC_TCE_POLARITY_GDOE_POL_ACTIVE_HIGH = 0x8, + EPDC_TCE_POLARITY_SDOE_POL_ACTIVE_HIGH = 0x4, + EPDC_TCE_POLARITY_SDLE_POL_ACTIVE_HIGH = 0x2, + EPDC_TCE_POLARITY_SDCE_POL_ACTIVE_HIGH = 0x1, + +/* EPDC_TCE_TIMING1 field values */ + EPDC_TCE_TIMING1_SDLE_SHIFT_NONE = 0x00, + EPDC_TCE_TIMING1_SDLE_SHIFT_1 = 0x10, + EPDC_TCE_TIMING1_SDLE_SHIFT_2 = 0x20, + EPDC_TCE_TIMING1_SDLE_SHIFT_3 = 0x30, + EPDC_TCE_TIMING1_SDCLK_INVERT = 0x8, + EPDC_TCE_TIMING1_SDCLK_SHIFT_NONE = 0, + EPDC_TCE_TIMING1_SDCLK_SHIFT_1CYCLE = 1, + EPDC_TCE_TIMING1_SDCLK_SHIFT_2CYCLES = 2, + EPDC_TCE_TIMING1_SDCLK_SHIFT_3CYCLES = 3, + +/* EPDC_TCE_TIMING2 field values */ + EPDC_TCE_TIMING2_GDCLK_HP_MASK = 0xFFFF0000, + EPDC_TCE_TIMING2_GDCLK_HP_OFFSET = 16, + EPDC_TCE_TIMING2_GDSP_OFFSET_MASK = 0xFFFF, + EPDC_TCE_TIMING2_GDSP_OFFSET_OFFSET = 0, + +/* EPDC_TCE_TIMING3 field values */ + EPDC_TCE_TIMING3_GDOE_OFFSET_MASK = 0xFFFF0000, + EPDC_TCE_TIMING3_GDOE_OFFSET_OFFSET = 16, + EPDC_TCE_TIMING3_GDCLK_OFFSET_MASK = 0xFFFF, + EPDC_TCE_TIMING3_GDCLK_OFFSET_OFFSET = 0, + +/* EPDC EPDC_PIGEON_CTRL0 field values */ + EPDC_PIGEON_CTRL0_LD_PERIOD_MASK = 0xFFF0000, + EPDC_PIGEON_CTRL0_LD_PERIOD_OFFSET = 16, + EPDC_PIGEON_CTRL0_FD_PERIOD_MASK = 0xFFF, + EPDC_PIGEON_CTRL0_FD_PERIOD_OFFSET = 0, + +/* EPDC EPDC_PIGEON_CTRL1 field values */ + EPDC_PIGEON_CTRL1_LD_PERIOD_MASK = 0xFFF0000, + EPDC_PIGEON_CTRL1_LD_PERIOD_OFFSET = 16, + EPDC_PIGEON_CTRL1_FD_PERIOD_MASK = 0xFFF, + EPDC_PIGEON_CTRL1_FD_PERIOD_OFFSET = 0, + +/* EPDC_IRQ_MASK/EPDC_IRQ field values */ + EPDC_IRQ_WB_CMPLT_IRQ = 0x10000, + EPDC_IRQ_LUT_COL_IRQ = 0x20000, + EPDC_IRQ_TCE_UNDERRUN_IRQ = 0x40000, + EPDC_IRQ_FRAME_END_IRQ = 0x80000, + EPDC_IRQ_BUS_ERROR_IRQ = 0x100000, + EPDC_IRQ_TCE_IDLE_IRQ = 0x200000, + EPDC_IRQ_UPD_DONE_IRQ = 0x400000, + EPDC_IRQ_PWR_IRQ = 0x800000, + +/* EPDC_STATUS_NEXTLUT field values */ + EPDC_STATUS_NEXTLUT_NEXT_LUT_VALID = 0x100, + EPDC_STATUS_NEXTLUT_NEXT_LUT_MASK = 0x3F, + EPDC_STATUS_NEXTLUT_NEXT_LUT_OFFSET = 0, + +/* EPDC_STATUS field values */ + EPDC_STATUS_HISTOGRAM_CP_MASK = 0x1F0000, + EPDC_STATUS_HISTOGRAM_CP_OFFSET = 16, + EPDC_STATUS_HISTOGRAM_NP_MASK = 0x1F00, + EPDC_STATUS_HISTOGRAM_NP_OFFSET = 8, + EPDC_STATUS_UPD_VOID = 0x8, + EPDC_STATUS_LUTS_UNDERRUN = 0x4, + EPDC_STATUS_LUTS_BUSY = 0x2, + EPDC_STATUS_WB_BUSY = 0x1, + +/* EPDC_UPD_COL_CORD field values */ + EPDC_UPD_COL_CORD_YCORD_MASK = 0x1FFF0000, + EPDC_UPD_COL_CORD_YCORD_OFFSET = 16, + EPDC_UPD_COL_CORD_XCORD_MASK = 0x1FFF, + EPDC_UPD_COL_CORD_XCORD_OFFSET = 0, + +/* EPDC_UPD_COL_SIZE field values */ + EPDC_UPD_COL_SIZE_HEIGHT_MASK = 0x1FFF0000, + EPDC_UPD_COL_SIZE_HEIGHT_OFFSET = 16, + EPDC_UPD_COL_SIZE_WIDTH_MASK = 0x1FFF, + EPDC_UPD_COL_SIZE_WIDTH_OFFSET = 0, + +/* EPDC_DEBUG field values */ + EPDC_DEBUG_DEBUG_LUT_SEL_MASK = 0x3F00000, + EPDC_DEBUG_DEBUG_LUT_SEL_OFFSET = 24, + EPDC_DEBUG_UBW_BURST_LEN_MASK = 0xF000, + EPDC_DEBUG_UBW_BURST_LEN_OFFSET = 12, + EPDC_DEBUG_UBR_BURST_LEN_MASK = 0xF00, + EPDC_DEBUG_UBR_BURST_LEN = 8, + EPDC_DEBUG_UPD_BURST_LEN_MASK = 0xF0, + EPDC_DEBUG_UPD_BURST_LEN_OFFSET = 4, + EPDC_DEBUG_UPDATE_SAME = 0x4, + EPDC_DEBUG_UNDERRUN_RECOVER = 0x2, + EPDC_DEBUG_COLLISION_OFF = 0x1, + +/* EPDC_DEBUG_LUT field values */ + EPDC_DEBUG_LUT_LUTADDR_MASK = 0x3FF0000, + EPDC_DEBUG_LUT_LUTADDR_OFFSET = 16, + EPDC_DEBUG_LUT_FRAME_MASK = 0x7FE0, + EPDC_DEBUG_LUT_FRAME_OFFSET = 5, + EPDC_DEBUG_LUT_STATEMACHINE_MASK = 0x1F, + EPDC_DEBUG_LUT_STATEMACHINE_OFFSET = 0, + +/* EPDC_HISTx_PARAM field values */ + EPDC_HIST_PARAM_VALUE0_MASK = 0x1F, + EPDC_HIST_PARAM_VALUE0_OFFSET = 0, + EPDC_HIST_PARAM_VALUE1_MASK = 0x1F00, + EPDC_HIST_PARAM_VALUE1_OFFSET = 8, + EPDC_HIST_PARAM_VALUE2_MASK = 0x1F0000, + EPDC_HIST_PARAM_VALUE2_OFFSET = 16, + EPDC_HIST_PARAM_VALUE3_MASK = 0x1F000000, + EPDC_HIST_PARAM_VALUE3_OFFSET = 24, + EPDC_HIST_PARAM_VALUE4_MASK = 0x1F, + EPDC_HIST_PARAM_VALUE4_OFFSET = 0, + EPDC_HIST_PARAM_VALUE5_MASK = 0x1F00, + EPDC_HIST_PARAM_VALUE5_OFFSET = 8, + EPDC_HIST_PARAM_VALUE6_MASK = 0x1F0000, + EPDC_HIST_PARAM_VALUE6_OFFSET = 16, + EPDC_HIST_PARAM_VALUE7_MASK = 0x1F000000, + EPDC_HIST_PARAM_VALUE7_OFFSET = 24, + EPDC_HIST_PARAM_VALUE8_MASK = 0x1F, + EPDC_HIST_PARAM_VALUE8_OFFSET = 0, + EPDC_HIST_PARAM_VALUE9_MASK = 0x1F00, + EPDC_HIST_PARAM_VALUE9_OFFSET = 8, + EPDC_HIST_PARAM_VALUE10_MASK = 0x1F0000, + EPDC_HIST_PARAM_VALUE10_OFFSET = 16, + EPDC_HIST_PARAM_VALUE11_MASK = 0x1F000000, + EPDC_HIST_PARAM_VALUE11_OFFSET = 24, + EPDC_HIST_PARAM_VALUE12_MASK = 0x1F, + EPDC_HIST_PARAM_VALUE12_OFFSET = 0, + EPDC_HIST_PARAM_VALUE13_MASK = 0x1F00, + EPDC_HIST_PARAM_VALUE13_OFFSET = 8, + EPDC_HIST_PARAM_VALUE14_MASK = 0x1F0000, + EPDC_HIST_PARAM_VALUE14_OFFSET = 16, + EPDC_HIST_PARAM_VALUE15_MASK = 0x1F000000, + EPDC_HIST_PARAM_VALUE15_OFFSET = 24, + +/* EPDC_GPIO field values */ + EPDC_GPIO_PWRSTAT = 0x100, + EPDC_GPIO_PWRWAKE = 0x80, + EPDC_GPIO_PWRCOM = 0x40, + EPDC_GPIO_PWRCTRL_MASK = 0x3C, + EPDC_GPIO_PWRCTRL_OFFSET = 2, + EPDC_GPIO_BDR_MASK = 0x3, + EPDC_GPIO_BDR_OFFSET = 0, + +/* EPDC_VERSION field values */ + EPDC_VERSION_MAJOR_MASK = 0xFF000000, + EPDC_VERSION_MAJOR_OFFSET = 24, + EPDC_VERSION_MINOR_MASK = 0xFF0000, + EPDC_VERSION_MINOR_OFFSET = 16, + EPDC_VERSION_STEP_MASK = 0xFFFF, + EPDC_VERSION_STEP_OFFSET = 0, +}; + +int board_setup_waveform_file(ulong waveform_buf); +int board_setup_logo_file(void *display_buf); +void epdc_power_on(void); +void epdc_power_off(void); + +extern void *lcd_base; + +#endif /* __EPDC_REGS_INCLUDED__ */ -- 2.17.1