Commit 1733259d authored by Tom Rini's avatar Tom Rini
Browse files

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

parents 791a9f67 fc1a79d9
......@@ -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.
......
......@@ -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
......@@ -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
......
......@@ -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();
}
......
/*
* (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();
}
}
......
/*
* (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);
}
......@@ -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
......@@ -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
......@@ -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;
}
/*
* LCD: LG4573, TFT 4.3", 480x800, RGB24
* LCD initialization via SPI
*
* SPDX-License-Identifier: GPL-2.0