Procházet zdrojové kódy

Merge branch 'master' of git://git.denx.de/u-boot-video

Tom Rini před 9 roky
rodič
revize
1733259d25

+ 20 - 0
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:<n> 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.

+ 1 - 0
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

+ 1 - 0
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

+ 8 - 10
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();
 }

+ 106 - 97
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 <common.h>
 #include <lcd.h>
 #include <video_font.h>		/* Get font data, width and height */
+#if defined(CONFIG_LCD_LOGO)
+#include <bmp_logo.h>
+#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();
 	}
 }

+ 195 - 0
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 <common.h>
+#include <lcd.h>
+#include <video_font.h>		/* 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);
+}

+ 1 - 0
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

+ 0 - 1
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

+ 13 - 1
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;
+}

+ 231 - 0
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 <common.h>
+#include <errno.h>
+#include <spi.h>
+
+#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",
+	""
+);

+ 2 - 1
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 */

+ 1 - 0
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 */
 

+ 9 - 0
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

+ 24 - 4
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
  *

+ 1 - 0
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 */
 

+ 1 - 0
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 */
 

+ 4 - 0
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