Message ID | 1426664243-30998-5-git-send-email-oe5hpm@oevsv.at |
---|---|
State | Superseded |
Delegated to: | Anatolij Gustschin |
Headers | show |
Hi Hannes, On 03/18/15 09:37, Hannes Petermaier wrote: > From: Hannes Petermaier <hannes.petermaier@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@br-automation.com> > Signed-off-by: Hannes Petermaier <oe5hpm@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 > * >
"U-Boot" <u-boot-bounces@lists.denx.de> schrieb am 18.03.2015 13:56:49: > > Hi Hannes, Hi Igor, thanks for response - we come closer to the final solution :-) > > > +} > > + > > +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). I think not so. If the lcd_console_rotation.c is compiled in, the __weak function isn't called anymore. And if user wants to have 0 degree rotation, the init-function from lcd_console_rotation.c doesn't anything. Therefore it is necessary to initialize these pointers here. > > + > > + 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. Will be changed in v3. > > + > > +#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 ... It might be possible to move this into lcd.h, in every case it is necesarry that common.h is included before - from here the information about LCD_BPP is coming. I will have a 2nd look to that to avoid this duplication. > > + > > +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__); > ? Okay, i will change that. Sometime ago, somebody told me on the mailing list that i should prefer the puts function if i don't have to print out some values. If we want to use the printf we can also printout the given rotation pcons->lcdrot. > -- > Regards, > Igor. best regards, Hannes
On 03/18/15 16:59, Hannes Petermaier wrote: > "U-Boot" <u-boot-bounces@lists.denx.de> schrieb am 18.03.2015 13:56:49: > >> >> Hi Hannes, > Hi Igor, > thanks for response - we come closer to the final solution :-) Indeed :-) > >> >>> +} >>> + >>> +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). > I think not so. > If the lcd_console_rotation.c is compiled in, the __weak function isn't > called anymore. > And if user wants to have 0 degree rotation, the init-function from > lcd_console_rotation.c doesn't anything. > Therefore it is necessary to initialize these pointers here. Right. Forgot about the 0 case... > >>> + >>> + 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. > Will be changed in v3. > >>> + >>> +#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 ... > It might be possible to move this into lcd.h, in every case it is > necesarry that common.h > is included before - from here the information about LCD_BPP is coming. > I will have a 2nd look to that to avoid this duplication. > >>> + >>> +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__); >> ? > Okay, i will change that. > Sometime ago, somebody told me on the mailing list that i should prefer > the puts function if i don't have to print out some values. Well, this is no longer true as we have discussed this during the last U-Boot summit. > If we want to use the printf we can also printout the given rotation > pcons->lcdrot. Good.
diff --git a/README b/README index b0124d6..c649de1 100644 --- a/README +++ b/README @@ -1947,6 +1947,28 @@ 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 mounted landscape but rotated by 180degree, + 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. + 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. diff --git a/common/Makefile b/common/Makefile index 7216a13..a1b3c09 100644 --- a/common/Makefile +++ b/common/Makefile @@ -200,6 +200,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 f33942c..d1b4ca7 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -167,7 +167,6 @@ int drv_lcd_init(void) void lcd_clear(void) { - short console_rows, console_cols; int bg_color; char *s; ulong addr; @@ -211,16 +210,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) { 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 @@ -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+ */ @@ -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); + + 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) @@ -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 + +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"); + 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 *