[U-Boot] [PATCH v2 4/4] common/lcd_console: introduce display/framebuffer rotation
Igor Grinberg
grinberg at compulab.co.il
Wed Mar 18 13:56:49 CET 2015
Hi Hannes,
On 03/18/15 09:37, Hannes Petermaier wrote:
> From: Hannes Petermaier <hannes.petermaier at br-automation.com>
>
> Sometimes, for example if the display is mounted in portrait mode or even if it
> mounted landscape but rotated by 180 degrees, we need to rotate our content of
> the display respectively the framebuffer, so that user can read the messages
> who are printed out.
>
> For this we introduce the feature called "CONFIG_LCD_ROTATION", this may be
> defined in the board-configuration if needed. After this 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.
>
> If CONFIG_LCD_ROTATION is not defined, the console will be initialized with
> 0 degrees rotation.
>
> Signed-off-by: Hannes Petermaier <hannes.petermaier at br-automation.com>
> Signed-off-by: Hannes Petermaier <oe5hpm at oevsv.at>
[...]
> diff --git a/common/lcd_console.c b/common/lcd_console.c
> index cac77be..14fd890 100644
> --- a/common/lcd_console.c
> +++ b/common/lcd_console.c
[...]
> @@ -10,26 +11,16 @@
> #include <lcd.h>
> #include <video_font.h> /* Get font data, width and height */
>
> -#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * lcd_line_length)
> -#define CONSOLE_ROW_FIRST cons.lcd_address
> -#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * cons.rows)
> +#if LCD_BPP == LCD_COLOR16
> + #define fbptr_t ushort
> +#elif LCD_BPP == LCD_COLOR32
> + #define fbptr_t u32
> +#else
> + #define fbptr_t uchar
> +#endif
>
> -struct console_t {
> - short curr_col, curr_row;
> - short cols, rows;
> - void *lcd_address;
> -};
> static struct console_t cons;
>
> -void lcd_init_console(void *address, int rows, int cols)
> -{
> - memset(&cons, 0, sizeof(cons));
> - cons.cols = cols;
> - cons.rows = rows;
> - cons.lcd_address = address;
> -
> -}
> -
> void lcd_set_col(short col)
> {
> cons.curr_col = col;
> @@ -56,61 +47,50 @@ int lcd_get_screen_columns(void)
> return cons.cols;
> }
>
> -static void lcd_putc_xy(ushort x, ushort y, char c)
> +static void lcd_putc_xy0(struct console_t *pcons, ushort x, ushort y, char c)
> {
> - uchar *dest;
> - ushort row;
> int fg_color = lcd_getfgcolor();
> int bg_color = lcd_getbgcolor();
> - int i;
> -
> - dest = (uchar *)(cons.lcd_address +
> - y * lcd_line_length + x * NBITS(LCD_BPP) / 8);
> -
> - for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
> -#if LCD_BPP == LCD_COLOR16
> - ushort *d = (ushort *)dest;
> -#elif LCD_BPP == LCD_COLOR32
> - u32 *d = (u32 *)dest;
> -#else
> - uchar *d = dest;
> -#endif
> - uchar bits;
> - bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
> -
> - for (i = 0; i < 8; ++i) {
> - *d++ = (bits & 0x80) ? fg_color : bg_color;
> + int i, row;
> + fbptr_t *dst = (fbptr_t *)pcons->lcd_address +
> + 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);
> }
> }
>
> -static void console_scrollup(void)
> +static inline void console_setrow0(struct console_t *pcons, u32 row, int clr)
> {
> - const int rows = CONFIG_CONSOLE_SCROLL_LINES;
> - int bg_color = lcd_getbgcolor();
> + int i;
> + fbptr_t *dst = (fbptr_t *)pcons->lcd_address +
> + row * VIDEO_FONT_HEIGHT *
> + pcons->lcdsizex;
>
> - /* Copy up rows ignoring those that will be overwritten */
> - memcpy(CONSOLE_ROW_FIRST,
> - cons.lcd_address + CONSOLE_ROW_SIZE * rows,
> - CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
> + for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
> + *dst++ = clr;
> +}
>
> - /* 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 = cons.lcd_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;
> - }
> -#endif
> - lcd_sync();
> - cons.curr_row -= rows;
> +static inline void console_moverow0(struct console_t *pcons,
> + u32 rowdst, u32 rowsrc)
> +{
> + int i;
> + fbptr_t *dst = (fbptr_t *)pcons->lcd_address +
> + rowdst * VIDEO_FONT_HEIGHT *
> + pcons->lcdsizex;
> +
> + fbptr_t *src = (fbptr_t *)pcons->lcd_address +
> + rowsrc * VIDEO_FONT_HEIGHT *
> + pcons->lcdsizex;
> +
> + for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
> + *dst++ = *src++;
> }
>
> static inline void console_back(void)
> @@ -121,19 +101,65 @@ static inline void console_back(void)
> cons.curr_row = 0;
> }
>
> - lcd_putc_xy(cons.curr_col * VIDEO_FONT_WIDTH,
> - cons.curr_row * VIDEO_FONT_HEIGHT, ' ');
> + cons.fp_putc_xy(&cons,
> + cons.curr_col * VIDEO_FONT_WIDTH,
> + cons.curr_row * VIDEO_FONT_HEIGHT, ' ');
> }
>
> static inline void console_newline(void)
> {
> + const int rows = CONFIG_CONSOLE_SCROLL_LINES;
> + int bg_color = lcd_getbgcolor();
> + int i;
> +
> cons.curr_col = 0;
>
> /* Check if we need to scroll the terminal */
> - if (++cons.curr_row >= cons.rows)
> - console_scrollup();
> - else
> - lcd_sync();
> + 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;
> + }
> + lcd_sync();
> +}
> +
> +static void console_calc_rowcol(struct console_t *pcons)
> +{
> + pcons->cols = pcons->lcdsizex / 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 = pcons->lcdsizey / VIDEO_FONT_HEIGHT;
> +#endif
> +}
> +
> +void __weak lcd_init_console_rot(struct console_t *pcons)
> +{
> + return;
> +}
> +
> +void lcd_init_console(void *address, int vl_cols, int vl_rows, int vl_rot)
> +{
> + memset(&cons, 0, sizeof(cons));
> + cons.lcd_address = address;
> +
> + 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);
I think the above four lines is exactly what should be placed in the
__weak variant of lcd_init_console_rot() function (the one just above
this one).
> +
> + 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);
> +
no need for the empty line here.
> }
>
> void lcd_putc(const char c)
> @@ -165,8 +191,9 @@ void lcd_putc(const char c)
>
> return;
> default:
> - lcd_putc_xy(cons.curr_col * VIDEO_FONT_WIDTH,
> - cons.curr_row * VIDEO_FONT_HEIGHT, c);
> + 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();
> }
> @@ -235,4 +262,3 @@ U_BOOT_CMD(
> "print string on lcd-framebuffer",
> " <string>"
> );
> -
> diff --git a/common/lcd_console_rotation.c b/common/lcd_console_rotation.c
> new file mode 100644
> index 0000000..3b6bb4f
> --- /dev/null
> +++ b/common/lcd_console_rotation.c
> @@ -0,0 +1,216 @@
> +/*
> + * (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 */
> +
> +#if LCD_BPP == LCD_COLOR16
> + #define fbptr_t ushort
> +#elif LCD_BPP == LCD_COLOR32
> + #define fbptr_t u32
> +#else
> + #define fbptr_t uchar
> +#endif
That is a duplication of the code in lcd_console.c.
If we can get rid of these size games, probably we should have in the lcd.h,
or lcd_console.h, or ...
> +
> +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->lcd_address +
> + (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->lcd_address +
> + 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->lcd_address +
> + pcons->lcdsizex -
> + (rowdst*VIDEO_FONT_HEIGHT+1);
> +
> + fbptr_t *src = (fbptr_t *)pcons->lcd_address +
> + 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->lcd_address +
> + 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->lcd_address +
> + (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->lcd_address +
> + (pcons->rows-rowdst-1) * VIDEO_FONT_HEIGHT *
> + pcons->lcdsizex;
> +
> + fbptr_t *src = (fbptr_t *)pcons->lcd_address +
> + (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->lcd_address +
> + 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->lcd_address +
> + 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->lcd_address +
> + rowdst*VIDEO_FONT_HEIGHT;
> +
> + fbptr_t *src = (fbptr_t *)pcons->lcd_address +
> + 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)
> +{
> + u32 cols, rows;
> +
> + if (pcons->lcdrot == 1 || pcons->lcdrot == 3) {
> + cols = pcons->lcdsizey;
> + rows = pcons->lcdsizex;
> + } else {
> + cols = pcons->lcdsizex;
> + rows = pcons->lcdsizey;
> + }
> +
> + pcons->cols = cols / VIDEO_FONT_WIDTH;
> +#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
> + pcons->rows = (rows - BMP_LOGO_HEIGHT);
> + pcons->rows /= VIDEO_FONT_HEIGHT;
> +#else
> + pcons->rows = rows / VIDEO_FONT_HEIGHT;
> +#endif
> +}
> +
> +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 {
> + puts("lcd_init_console_rot: invalid framebuffer rotation!\n");
How about
printf("%s: invalid framebuffer rotation!\n", __func__);
?
> + puts(" using def. 0 degree rotation.\n");
> + return;
> + }
> + console_calc_rowcol_rot(pcons);
> +}
> diff --git a/include/lcd.h b/include/lcd.h
> index f049fd3..1329280 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 */
> diff --git a/include/lcd_console.h b/include/lcd_console.h
> index 429214d..6612a38 100644
> --- a/include/lcd_console.h
> +++ b/include/lcd_console.h
> @@ -9,6 +9,16 @@
> #define CONFIG_CONSOLE_SCROLL_LINES 1
> #endif
>
> +struct console_t {
> + short curr_col, curr_row;
> + short cols, rows;
> + void *lcd_address;
> + 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);
> +};
> /**
> * lcd_init_console() - Initialize lcd console parameters
> *
> @@ -16,11 +26,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
> *
>
--
Regards,
Igor.
More information about the U-Boot
mailing list