diff --git a/README b/README index caba460..fc1fd52 100644 --- a/README +++ b/README @@ -1947,6 +1947,26 @@ CBFS (Coreboot Filesystem) support the console jump but can help speed up operation when scrolling is slow. + CONFIG_LCD_ROTATION + + Sometimes, for example if the display is mounted in portrait + mode or even if it's mounted landscape but rotated by 180degree, + we need to rotate our content of the display relative to the + framebuffer, so that user can read the messages which are + printed out. + Once CONFIG_LCD_ROTATION is defined, the lcd_console will be + initialized with a given rotation from "vl_rot" out of + "vidinfo_t" which is provided by the board specific code. + The value for vl_rot is coded as following (matching to + fbcon=rotate: linux-kernel commandline): + 0 = no rotation respectively 0 degree + 1 = 90 degree rotation + 2 = 180 degree rotation + 3 = 270 degree rotation + + If CONFIG_LCD_ROTATION is not defined, the console will be + initialized with 0degree rotation. + CONFIG_LCD_BMP_RLE8 Support drawing of RLE8-compressed bitmaps on the LCD. diff --git a/arch/arm/include/asm/imx-common/video.h b/arch/arm/include/asm/imx-common/video.h index 1a907d4..cad5f86 100644 --- a/arch/arm/include/asm/imx-common/video.h +++ b/arch/arm/include/asm/imx-common/video.h @@ -26,4 +26,5 @@ extern struct display_info_t const displays[]; extern size_t display_count; #endif +int ipu_set_ldb_clock(int rate); #endif diff --git a/common/Makefile b/common/Makefile index 978c33b..fba3830 100644 --- a/common/Makefile +++ b/common/Makefile @@ -201,6 +201,7 @@ obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-y += splash.o obj-$(CONFIG_SPLASH_SOURCE) += splash_source.o obj-$(CONFIG_LCD) += lcd.o lcd_console.o +obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o obj-$(CONFIG_LYNXKDI) += lynxkdi.o obj-$(CONFIG_MENU) += menu.o diff --git a/common/lcd.c b/common/lcd.c index 6982759..055c366 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -168,7 +168,6 @@ int drv_lcd_init(void) void lcd_clear(void) { - short console_rows, console_cols; int bg_color; char *s; ulong addr; @@ -212,16 +211,14 @@ void lcd_clear(void) } #endif #endif + /* setup text-console */ + debug("[LCD] setting up console...\n"); + lcd_init_console(lcd_base, + panel_info.vl_col, + panel_info.vl_row, + panel_info.vl_rot); /* Paint the logo and retrieve LCD base address */ debug("[LCD] Drawing the logo...\n"); -#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO) - console_rows = (panel_info.vl_row - BMP_LOGO_HEIGHT); - console_rows /= VIDEO_FONT_HEIGHT; -#else - console_rows = panel_info.vl_row / VIDEO_FONT_HEIGHT; -#endif - console_cols = panel_info.vl_col / VIDEO_FONT_WIDTH; - lcd_init_console(lcd_base, console_rows, console_cols); if (do_splash) { s = getenv("splashimage"); if (s) { @@ -237,7 +234,8 @@ void lcd_clear(void) lcd_logo(); #if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO) addr = (ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length; - lcd_init_console((void *)addr, console_rows, console_cols); + lcd_init_console((void *)addr, panel_info.vl_row, + panel_info.vl_col, panel_info.vl_rot); #endif lcd_sync(); } diff --git a/common/lcd_console.c b/common/lcd_console.c index 8bf83b9..bb0d7c5 100644 --- a/common/lcd_console.c +++ b/common/lcd_console.c @@ -1,7 +1,8 @@ /* - * (C) Copyright 2001-2014 + * (C) Copyright 2001-2015 * DENX Software Engineering -- wd@denx.de * Compulab Ltd - http://compulab.co.il/ + * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com * * SPDX-License-Identifier: GPL-2.0+ */ @@ -9,142 +10,150 @@ #include #include #include /* Get font data, width and height */ +#if defined(CONFIG_LCD_LOGO) +#include +#endif -#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * lcd_line_length) -#define CONSOLE_ROW_FIRST lcd_console_address -#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * console_rows) - -static short console_curr_col; -static short console_curr_row; -static short console_cols; -static short console_rows; -static void *lcd_console_address; - -void lcd_init_console(void *address, int rows, int cols) -{ - console_curr_col = 0; - console_curr_row = 0; - console_cols = cols; - console_rows = rows; - lcd_console_address = address; -} +static struct console_t cons; void lcd_set_col(short col) { - console_curr_col = col; + cons.curr_col = col; } void lcd_set_row(short row) { - console_curr_row = row; + cons.curr_row = row; } void lcd_position_cursor(unsigned col, unsigned row) { - console_curr_col = min_t(short, col, console_cols - 1); - console_curr_row = min_t(short, row, console_rows - 1); + cons.curr_col = min_t(short, col, cons.cols - 1); + cons.curr_row = min_t(short, row, cons.rows - 1); } int lcd_get_screen_rows(void) { - return console_rows; + return cons.rows; } int lcd_get_screen_columns(void) { - return console_cols; + return cons.cols; } -static void lcd_drawchars(ushort x, ushort y, uchar *str, int count) +static void lcd_putc_xy0(struct console_t *pcons, ushort x, ushort y, char c) { - uchar *dest; - ushort row; - int fg_color, bg_color; + int fg_color = lcd_getfgcolor(); + int bg_color = lcd_getbgcolor(); + int i, row; + 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]; + for (i = 0; i < VIDEO_FONT_WIDTH; ++i) { + *dst++ = (bits & 0x80) ? fg_color : bg_color; + bits <<= 1; + } + dst += (pcons->lcdsizex - VIDEO_FONT_WIDTH); + } +} - dest = (uchar *)(lcd_console_address + - y * lcd_line_length + x * NBITS(LCD_BPP) / 8); +static inline void console_setrow0(struct console_t *pcons, u32 row, int clr) +{ + int i; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + row * VIDEO_FONT_HEIGHT * + pcons->lcdsizex; - for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) { - uchar *s = str; - int i; -#if LCD_BPP == LCD_COLOR16 - ushort *d = (ushort *)dest; -#elif LCD_BPP == LCD_COLOR32 - u32 *d = (u32 *)dest; -#else - uchar *d = dest; -#endif + for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++) + *dst++ = clr; +} - fg_color = lcd_getfgcolor(); - bg_color = lcd_getbgcolor(); - for (i = 0; i < count; ++i) { - uchar c, bits; +static inline void console_moverow0(struct console_t *pcons, + u32 rowdst, u32 rowsrc) +{ + int i; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + rowdst * VIDEO_FONT_HEIGHT * + pcons->lcdsizex; - c = *s++; - bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row]; + fbptr_t *src = (fbptr_t *)pcons->fbbase + + rowsrc * VIDEO_FONT_HEIGHT * + pcons->lcdsizex; - for (c = 0; c < 8; ++c) { - *d++ = (bits & 0x80) ? fg_color : bg_color; - bits <<= 1; - } - } - } + for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++) + *dst++ = *src++; } -static inline void lcd_putc_xy(ushort x, ushort y, uchar c) +static inline void console_back(void) { - lcd_drawchars(x, y, &c, 1); + if (--cons.curr_col < 0) { + cons.curr_col = cons.cols - 1; + if (--cons.curr_row < 0) + cons.curr_row = 0; + } + + cons.fp_putc_xy(&cons, + cons.curr_col * VIDEO_FONT_WIDTH, + cons.curr_row * VIDEO_FONT_HEIGHT, ' '); } -static void console_scrollup(void) +static inline void console_newline(void) { const int rows = CONFIG_CONSOLE_SCROLL_LINES; int bg_color = lcd_getbgcolor(); + int i; - /* Copy up rows ignoring those that will be overwritten */ - memcpy(CONSOLE_ROW_FIRST, - lcd_console_address + CONSOLE_ROW_SIZE * rows, - CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows); + cons.curr_col = 0; - /* Clear the last rows */ -#if (LCD_BPP != LCD_COLOR32) - memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows, - bg_color, CONSOLE_ROW_SIZE * rows); -#else - u32 *ppix = lcd_console_address + - CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows; - u32 i; - for (i = 0; - i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix); - i++) { - *ppix++ = bg_color; + /* Check if we need to scroll the terminal */ + if (++cons.curr_row >= cons.rows) { + 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.curr_row -= rows; } -#endif lcd_sync(); - console_curr_row -= rows; } -static inline void console_back(void) +void console_calc_rowcol(struct console_t *pcons, u32 sizex, u32 sizey) { - if (--console_curr_col < 0) { - console_curr_col = console_cols - 1; - if (--console_curr_row < 0) - console_curr_row = 0; - } + pcons->cols = sizex / VIDEO_FONT_WIDTH; +#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO) + pcons->rows = (pcons->lcdsizey - BMP_LOGO_HEIGHT); + pcons->rows /= VIDEO_FONT_HEIGHT; +#else + pcons->rows = sizey / VIDEO_FONT_HEIGHT; +#endif +} - lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH, - console_curr_row * VIDEO_FONT_HEIGHT, ' '); +void __weak lcd_init_console_rot(struct console_t *pcons) +{ + return; } -static inline void console_newline(void) +void lcd_init_console(void *address, int vl_cols, int vl_rows, int vl_rot) { - console_curr_col = 0; + memset(&cons, 0, sizeof(cons)); + cons.fbbase = address; - /* Check if we need to scroll the terminal */ - if (++console_curr_row >= console_rows) - console_scrollup(); - else - lcd_sync(); + cons.lcdsizex = vl_cols; + cons.lcdsizey = vl_rows; + cons.lcdrot = vl_rot; + + cons.fp_putc_xy = &lcd_putc_xy0; + cons.fp_console_moverow = &console_moverow0; + cons.fp_console_setrow = &console_setrow0; + console_calc_rowcol(&cons, cons.lcdsizex, cons.lcdsizey); + + lcd_init_console_rot(&cons); + + debug("lcd_console: have %d/%d col/rws on scr %dx%d (%d deg rotated)\n", + cons.cols, cons.rows, cons.lcdsizex, cons.lcdsizey, vl_rot); } void lcd_putc(const char c) @@ -157,18 +166,17 @@ void lcd_putc(const char c) switch (c) { case '\r': - console_curr_col = 0; - + cons.curr_col = 0; return; case '\n': console_newline(); return; case '\t': /* Tab (8 chars alignment) */ - console_curr_col += 8; - console_curr_col &= ~7; + cons.curr_col += 8; + cons.curr_col &= ~7; - if (console_curr_col >= console_cols) + if (cons.curr_col >= cons.cols) console_newline(); return; @@ -177,9 +185,10 @@ void lcd_putc(const char c) return; default: - lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH, - console_curr_row * VIDEO_FONT_HEIGHT, c); - if (++console_curr_col >= console_cols) + cons.fp_putc_xy(&cons, + cons.curr_col * VIDEO_FONT_WIDTH, + cons.curr_row * VIDEO_FONT_HEIGHT, c); + if (++cons.curr_col >= cons.cols) console_newline(); } } diff --git a/common/lcd_console_rotation.c b/common/lcd_console_rotation.c new file mode 100644 index 0000000..7aac521 --- /dev/null +++ b/common/lcd_console_rotation.c @@ -0,0 +1,195 @@ +/* + * (C) Copyright 2015 + * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include /* Get font data, width and height */ + +static void lcd_putc_xy90(struct console_t *pcons, ushort x, ushort y, char c) +{ + int fg_color = lcd_getfgcolor(); + int bg_color = lcd_getbgcolor(); + int col, i; + + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + (x+1) * pcons->lcdsizex - + y; + + uchar msk = 0x80; + uchar *pfont = video_fontdata + c * VIDEO_FONT_HEIGHT; + for (col = 0; col < VIDEO_FONT_WIDTH; ++col) { + for (i = 0; i < VIDEO_FONT_HEIGHT; ++i) + *dst-- = (*(pfont + i) & msk) ? fg_color : bg_color; + msk >>= 1; + dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT); + } +} + +static inline void console_setrow90(struct console_t *pcons, u32 row, int clr) +{ + int i, j; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + pcons->lcdsizex - + row*VIDEO_FONT_HEIGHT+1; + + for (j = 0; j < pcons->lcdsizey; j++) { + for (i = 0; i < VIDEO_FONT_HEIGHT; i++) + *dst-- = clr; + dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT); + } +} + +static inline void console_moverow90(struct console_t *pcons, + u32 rowdst, u32 rowsrc) +{ + int i, j; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + pcons->lcdsizex - + (rowdst*VIDEO_FONT_HEIGHT+1); + + fbptr_t *src = (fbptr_t *)pcons->fbbase + + pcons->lcdsizex - + (rowsrc*VIDEO_FONT_HEIGHT+1); + + for (j = 0; j < pcons->lcdsizey; j++) { + for (i = 0; i < VIDEO_FONT_HEIGHT; i++) + *dst-- = *src--; + src += (pcons->lcdsizex + VIDEO_FONT_HEIGHT); + dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT); + } +} +static void lcd_putc_xy180(struct console_t *pcons, ushort x, ushort y, char c) +{ + int fg_color = lcd_getfgcolor(); + int bg_color = lcd_getbgcolor(); + int i, row; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + pcons->lcdsizex + + pcons->lcdsizey * pcons->lcdsizex - + y * pcons->lcdsizex - + (x+1); + + for (row = 0; row < VIDEO_FONT_HEIGHT; row++) { + uchar bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row]; + + for (i = 0; i < VIDEO_FONT_WIDTH; ++i) { + *dst-- = (bits & 0x80) ? fg_color : bg_color; + bits <<= 1; + } + dst -= (pcons->lcdsizex - VIDEO_FONT_WIDTH); + } +} + +static inline void console_setrow180(struct console_t *pcons, u32 row, int clr) +{ + int i; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + (pcons->rows-row-1) * VIDEO_FONT_HEIGHT * + pcons->lcdsizex; + + for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++) + *dst++ = clr; +} + +static inline void console_moverow180(struct console_t *pcons, + u32 rowdst, u32 rowsrc) +{ + int i; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + (pcons->rows-rowdst-1) * VIDEO_FONT_HEIGHT * + pcons->lcdsizex; + + fbptr_t *src = (fbptr_t *)pcons->fbbase + + (pcons->rows-rowsrc-1) * VIDEO_FONT_HEIGHT * + pcons->lcdsizex; + + for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++) + *dst++ = *src++; +} + +static void lcd_putc_xy270(struct console_t *pcons, ushort x, ushort y, char c) +{ + int fg_color = lcd_getfgcolor(); + int bg_color = lcd_getbgcolor(); + int i, col; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + pcons->lcdsizey * pcons->lcdsizex - + (x+1) * pcons->lcdsizex + + y; + + uchar msk = 0x80; + uchar *pfont = video_fontdata + c * VIDEO_FONT_HEIGHT; + for (col = 0; col < VIDEO_FONT_WIDTH; ++col) { + for (i = 0; i < VIDEO_FONT_HEIGHT; ++i) + *dst++ = (*(pfont + i) & msk) ? fg_color : bg_color; + msk >>= 1; + dst -= (pcons->lcdsizex + VIDEO_FONT_HEIGHT); + } +} + +static inline void console_setrow270(struct console_t *pcons, u32 row, int clr) +{ + int i, j; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + row*VIDEO_FONT_HEIGHT; + + for (j = 0; j < pcons->lcdsizey; j++) { + for (i = 0; i < VIDEO_FONT_HEIGHT; i++) + *dst++ = clr; + dst += (pcons->lcdsizex - VIDEO_FONT_HEIGHT); + } +} + +static inline void console_moverow270(struct console_t *pcons, + u32 rowdst, u32 rowsrc) +{ + int i, j; + fbptr_t *dst = (fbptr_t *)pcons->fbbase + + rowdst*VIDEO_FONT_HEIGHT; + + fbptr_t *src = (fbptr_t *)pcons->fbbase + + rowsrc*VIDEO_FONT_HEIGHT; + + for (j = 0; j < pcons->lcdsizey; j++) { + for (i = 0; i < VIDEO_FONT_HEIGHT; i++) + *dst++ = *src++; + src += (pcons->lcdsizex - VIDEO_FONT_HEIGHT); + dst += (pcons->lcdsizex - VIDEO_FONT_HEIGHT); + } +} + +static void console_calc_rowcol_rot(struct console_t *pcons) +{ + if (pcons->lcdrot == 1 || pcons->lcdrot == 3) + console_calc_rowcol(pcons, pcons->lcdsizey, pcons->lcdsizex); + else + console_calc_rowcol(pcons, pcons->lcdsizex, pcons->lcdsizey); +} + +void lcd_init_console_rot(struct console_t *pcons) +{ + if (pcons->lcdrot == 0) { + return; + } else if (pcons->lcdrot == 1) { + pcons->fp_putc_xy = &lcd_putc_xy90; + pcons->fp_console_moverow = &console_moverow90; + pcons->fp_console_setrow = &console_setrow90; + } else if (pcons->lcdrot == 2) { + pcons->fp_putc_xy = &lcd_putc_xy180; + pcons->fp_console_moverow = &console_moverow180; + pcons->fp_console_setrow = &console_setrow180; + } else if (pcons->lcdrot == 3) { + pcons->fp_putc_xy = &lcd_putc_xy270; + pcons->fp_console_moverow = &console_moverow270; + pcons->fp_console_setrow = &console_setrow270; + } else { + printf("%s: invalid framebuffer rotation (%d)!\n", + __func__, pcons->lcdrot); + return; + } + console_calc_rowcol_rot(pcons); +} diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 22a316b..f64918e 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -45,5 +45,6 @@ obj-$(CONFIG_VIDEO_TEGRA) += tegra.o obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o obj-$(CONFIG_VIDEO_VESA) += vesa_fb.o obj-$(CONFIG_FORMIKE) += formike.o +obj-$(CONFIG_LG4573) += lg4573.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-$(CONFIG_VIDEO_PARADE) += parade.o diff --git a/drivers/video/ipu.h b/drivers/video/ipu.h index 091b58f..348be58 100644 --- a/drivers/video/ipu.h +++ b/drivers/video/ipu.h @@ -265,5 +265,4 @@ int ipu_dp_init(ipu_channel_t channel, uint32_t in_pixel_fmt, void ipu_dp_uninit(ipu_channel_t channel); void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap); ipu_color_space_t format_to_colorspace(uint32_t fmt); - #endif diff --git a/drivers/video/ipu_common.c b/drivers/video/ipu_common.c index 5873531..9f85102 100644 --- a/drivers/video/ipu_common.c +++ b/drivers/video/ipu_common.c @@ -210,9 +210,13 @@ static struct clk ipu_clk = { .usecount = 0, }; +#if !defined CONFIG_SYS_LDB_CLOCK +#define CONFIG_SYS_LDB_CLOCK 65000000 +#endif + static struct clk ldb_clk = { .name = "ldb_clk", - .rate = 65000000, + .rate = CONFIG_SYS_LDB_CLOCK, .usecount = 0, }; @@ -1194,3 +1198,11 @@ ipu_color_space_t format_to_colorspace(uint32_t fmt) } return RGB; } + +/* should be removed when clk framework is availiable */ +int ipu_set_ldb_clock(int rate) +{ + ldb_clk.rate = rate; + + return 0; +} diff --git a/drivers/video/lg4573.c b/drivers/video/lg4573.c new file mode 100644 index 0000000..43670fc --- /dev/null +++ b/drivers/video/lg4573.c @@ -0,0 +1,231 @@ +/* + * LCD: LG4573, TFT 4.3", 480x800, RGB24 + * LCD initialization via SPI + * + * SPDX-License-Identifier: GPL-2.0 + * + */ +#include +#include +#include + +#define PWR_ON_DELAY_MSECS 120 + +static int lb043wv_spi_write_u16(struct spi_slave *spi, u16 val) +{ + unsigned long flags = SPI_XFER_BEGIN; + unsigned short buf16 = htons(val); + int ret = 0; + + flags |= SPI_XFER_END; + + ret = spi_xfer(spi, 16, &buf16, NULL, flags); + if (ret) + debug("%s: Failed to send: %d\n", __func__, ret); + + return ret; +} + +static void lb043wv_spi_write_u16_array(struct spi_slave *spi, u16 *buff, + int size) +{ + int i; + + for (i = 0; i < size; i++) + lb043wv_spi_write_u16(spi, buff[i]); +} + +static void lb043wv_display_mode_settings(struct spi_slave *spi) +{ + static u16 display_mode_settings[] = { + 0x703A, + 0x7270, + 0x70B1, + 0x7208, + 0x723B, + 0x720F, + 0x70B2, + 0x7200, + 0x72C8, + 0x70B3, + 0x7200, + 0x70B4, + 0x7200, + 0x70B5, + 0x7242, + 0x7210, + 0x7210, + 0x7200, + 0x7220, + 0x70B6, + 0x720B, + 0x720F, + 0x723C, + 0x7213, + 0x7213, + 0x72E8, + 0x70B7, + 0x7246, + 0x7206, + 0x720C, + 0x7200, + 0x7200, + }; + + debug("transfer display mode settings\n"); + lb043wv_spi_write_u16_array(spi, display_mode_settings, + ARRAY_SIZE(display_mode_settings)); +} + +static void lb043wv_power_settings(struct spi_slave *spi) +{ + static u16 power_settings[] = { + 0x70C0, + 0x7201, + 0x7211, + 0x70C3, + 0x7207, + 0x7203, + 0x7204, + 0x7204, + 0x7204, + 0x70C4, + 0x7212, + 0x7224, + 0x7218, + 0x7218, + 0x7202, + 0x7249, + 0x70C5, + 0x726F, + 0x70C6, + 0x7241, + 0x7263, + }; + + debug("transfer power settings\n"); + lb043wv_spi_write_u16_array(spi, power_settings, + ARRAY_SIZE(power_settings)); +} + +static void lb043wv_gamma_settings(struct spi_slave *spi) +{ + static u16 gamma_settings[] = { + 0x70D0, + 0x7203, + 0x7207, + 0x7273, + 0x7235, + 0x7200, + 0x7201, + 0x7220, + 0x7200, + 0x7203, + 0x70D1, + 0x7203, + 0x7207, + 0x7273, + 0x7235, + 0x7200, + 0x7201, + 0x7220, + 0x7200, + 0x7203, + 0x70D2, + 0x7203, + 0x7207, + 0x7273, + 0x7235, + 0x7200, + 0x7201, + 0x7220, + 0x7200, + 0x7203, + 0x70D3, + 0x7203, + 0x7207, + 0x7273, + 0x7235, + 0x7200, + 0x7201, + 0x7220, + 0x7200, + 0x7203, + 0x70D4, + 0x7203, + 0x7207, + 0x7273, + 0x7235, + 0x7200, + 0x7201, + 0x7220, + 0x7200, + 0x7203, + 0x70D5, + 0x7203, + 0x7207, + 0x7273, + 0x7235, + 0x7200, + 0x7201, + 0x7220, + 0x7200, + 0x7203, + }; + + debug("transfer gamma settings\n"); + lb043wv_spi_write_u16_array(spi, gamma_settings, + ARRAY_SIZE(gamma_settings)); +} + +static void lb043wv_display_on(struct spi_slave *spi) +{ + static u16 sleep_out = 0x7011; + static u16 display_on = 0x7029; + + lb043wv_spi_write_u16(spi, sleep_out); + mdelay(PWR_ON_DELAY_MSECS); + lb043wv_spi_write_u16(spi, display_on); +} + +int lg4573_spi_startup(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int spi_mode) +{ + struct spi_slave *spi; + int ret; + + spi = spi_setup_slave(bus, cs, max_hz, spi_mode); + if (!spi) { + debug("%s: Failed to set up slave\n", __func__); + return -1; + } + + ret = spi_claim_bus(spi); + if (ret) { + debug("%s: Failed to claim SPI bus: %d\n", __func__, ret); + goto err_claim_bus; + } + + lb043wv_display_mode_settings(spi); + lb043wv_power_settings(spi); + lb043wv_gamma_settings(spi); + + lb043wv_display_on(spi); + return 0; +err_claim_bus: + spi_free_slave(spi); + return -1; +} + +static int do_lgset(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + lg4573_spi_startup(0, 0, 10000000, SPI_MODE_0); + return 0; +} + +U_BOOT_CMD( + lgset, 2, 1, do_lgset, + "set lgdisplay", + "" +); diff --git a/include/atmel_lcd.h b/include/atmel_lcd.h index fa8aa29..6993128 100644 --- a/include/atmel_lcd.h +++ b/include/atmel_lcd.h @@ -13,7 +13,8 @@ typedef struct vidinfo { ushort vl_col; /* Number of columns (i.e. 640) */ ushort vl_row; /* Number of rows (i.e. 480) */ - u_long vl_clk; /* pixel clock in ps */ + ushort vl_rot; /* Rotation of Display (0, 1, 2, 3) */ + u_long vl_clk; /* pixel clock in ps */ /* LCD configuration register */ u_long vl_sync; /* Horizontal / vertical sync */ diff --git a/include/exynos_lcd.h b/include/exynos_lcd.h index cf389da..3969a6a 100644 --- a/include/exynos_lcd.h +++ b/include/exynos_lcd.h @@ -25,6 +25,7 @@ enum exynos_fb_rgb_mode_t { typedef struct vidinfo { ushort vl_col; /* Number of columns (i.e. 640) */ ushort vl_row; /* Number of rows (i.e. 480) */ + ushort vl_rot; /* Rotation of Display (0, 1, 2, 3) */ ushort vl_width; /* Width of display area in millimeters */ ushort vl_height; /* Height of display area in millimeters */ diff --git a/include/lcd.h b/include/lcd.h index f049fd3..59202b7 100644 --- a/include/lcd.h +++ b/include/lcd.h @@ -51,6 +51,7 @@ void lcd_set_flush_dcache(int flush); typedef struct vidinfo { ushort vl_col; /* Number of columns (i.e. 160) */ ushort vl_row; /* Number of rows (i.e. 100) */ + ushort vl_rot; /* Rotation of Display (0, 1, 2, 3) */ u_char vl_bpix; /* Bits per pixel, 0 = 1 */ ushort *cmap; /* Pointer to the colormap */ void *priv; /* Pointer to driver-specific data */ @@ -196,6 +197,14 @@ void lcd_sync(void); #define CONSOLE_COLOR_WHITE 0xffff /* Must remain last / highest */ #endif /* color definitions */ +#if LCD_BPP == LCD_COLOR16 +#define fbptr_t ushort +#elif LCD_BPP == LCD_COLOR32 +#define fbptr_t u32 +#else +#define fbptr_t uchar +#endif + #ifndef PAGE_SIZE #define PAGE_SIZE 4096 #endif diff --git a/include/lcd_console.h b/include/lcd_console.h index 429214d..2e0f56f 100644 --- a/include/lcd_console.h +++ b/include/lcd_console.h @@ -9,6 +9,26 @@ #define CONFIG_CONSOLE_SCROLL_LINES 1 #endif +struct console_t { + short curr_col, curr_row; + short cols, rows; + void *fbbase; + u32 lcdsizex, lcdsizey, lcdrot; + void (*fp_putc_xy)(struct console_t *pcons, ushort x, ushort y, char c); + void (*fp_console_moverow)(struct console_t *pcons, + u32 rowdst, u32 rowsrc); + void (*fp_console_setrow)(struct console_t *pcons, u32 row, int clr); +}; + +/** + * console_calc_rowcol() - calculate available rows / columns wihtin a given + * screen-size based on used VIDEO_FONT. + * + * @pcons: Pointer to struct console_t + * @sizex: size X of the screen in pixel + * @sizey: size Y of the screen in pixel + */ +void console_calc_rowcol(struct console_t *pcons, u32 sizex, u32 sizey); /** * lcd_init_console() - Initialize lcd console parameters * @@ -16,11 +36,11 @@ * console has. * * @address: Console base address - * @rows: Number of rows in the console - * @cols: Number of columns in the console + * @vl_rows: Number of rows in the console + * @vl_cols: Number of columns in the console + * @vl_rot: Rotation of display in degree (0 - 90 - 180 - 270) counterlockwise */ -void lcd_init_console(void *address, int rows, int cols); - +void lcd_init_console(void *address, int vl_cols, int vl_rows, int vl_rot); /** * lcd_set_col() - Set the number of the current lcd console column * diff --git a/include/mpc823_lcd.h b/include/mpc823_lcd.h index 7e210e3..cc72cde 100644 --- a/include/mpc823_lcd.h +++ b/include/mpc823_lcd.h @@ -16,6 +16,7 @@ typedef struct vidinfo { ushort vl_col; /* Number of columns (i.e. 640) */ ushort vl_row; /* Number of rows (i.e. 480) */ + ushort vl_rot; /* Rotation of Display (0, 1, 2, 3) */ ushort vl_width; /* Width of display area in millimeters */ ushort vl_height; /* Height of display area in millimeters */ diff --git a/include/pxa_lcd.h b/include/pxa_lcd.h index 723f6ab..1ea3717 100644 --- a/include/pxa_lcd.h +++ b/include/pxa_lcd.h @@ -48,6 +48,7 @@ struct pxafb_info { typedef struct vidinfo { ushort vl_col; /* Number of columns (i.e. 640) */ ushort vl_row; /* Number of rows (i.e. 480) */ + ushort vl_rot; /* Rotation of Display (0, 1, 2, 3) */ ushort vl_width; /* Width of display area in millimeters */ ushort vl_height; /* Height of display area in millimeters */ diff --git a/include/video.h b/include/video.h index 673aa2e..65e4ec1 100644 --- a/include/video.h +++ b/include/video.h @@ -69,4 +69,8 @@ void video_clear(void); int kwh043st20_f01_spi_startup(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int spi_mode); #endif +#if defined(CONFIG_LG4573) +int lg4573_spi_startup(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int spi_mode); +#endif #endif