Home | History | Annotate | Download | only in common
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2001-2015
      4  * DENX Software Engineering -- wd (at) denx.de
      5  * Compulab Ltd - http://compulab.co.il/
      6  * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
      7  */
      8 
      9 #include <common.h>
     10 #include <lcd.h>
     11 #include <video_font.h>		/* Get font data, width and height */
     12 #if defined(CONFIG_LCD_LOGO)
     13 #include <bmp_logo.h>
     14 #endif
     15 
     16 static struct console_t cons;
     17 
     18 void lcd_set_col(short col)
     19 {
     20 	cons.curr_col = col;
     21 }
     22 
     23 void lcd_set_row(short row)
     24 {
     25 	cons.curr_row = row;
     26 }
     27 
     28 void lcd_position_cursor(unsigned col, unsigned row)
     29 {
     30 	cons.curr_col = min_t(short, col, cons.cols - 1);
     31 	cons.curr_row = min_t(short, row, cons.rows - 1);
     32 }
     33 
     34 int lcd_get_screen_rows(void)
     35 {
     36 	return cons.rows;
     37 }
     38 
     39 int lcd_get_screen_columns(void)
     40 {
     41 	return cons.cols;
     42 }
     43 
     44 static void lcd_putc_xy0(struct console_t *pcons, ushort x, ushort y, char c)
     45 {
     46 	int fg_color = lcd_getfgcolor();
     47 	int bg_color = lcd_getbgcolor();
     48 	int i, row;
     49 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
     50 				  y * pcons->lcdsizex +
     51 				  x;
     52 
     53 	for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
     54 		uchar bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
     55 		for (i = 0; i < VIDEO_FONT_WIDTH; ++i) {
     56 			*dst++ = (bits & 0x80) ? fg_color : bg_color;
     57 			bits <<= 1;
     58 		}
     59 		dst += (pcons->lcdsizex - VIDEO_FONT_WIDTH);
     60 	}
     61 }
     62 
     63 static inline void console_setrow0(struct console_t *pcons, u32 row, int clr)
     64 {
     65 	int i;
     66 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
     67 				  row * VIDEO_FONT_HEIGHT *
     68 				  pcons->lcdsizex;
     69 
     70 	for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
     71 		*dst++ = clr;
     72 }
     73 
     74 static inline void console_moverow0(struct console_t *pcons,
     75 				    u32 rowdst, u32 rowsrc)
     76 {
     77 	int i;
     78 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
     79 				  rowdst * VIDEO_FONT_HEIGHT *
     80 				  pcons->lcdsizex;
     81 
     82 	fbptr_t *src = (fbptr_t *)pcons->fbbase +
     83 				  rowsrc * VIDEO_FONT_HEIGHT *
     84 				  pcons->lcdsizex;
     85 
     86 	for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
     87 		*dst++ = *src++;
     88 }
     89 
     90 static inline void console_back(void)
     91 {
     92 	if (--cons.curr_col < 0) {
     93 		cons.curr_col = cons.cols - 1;
     94 		if (--cons.curr_row < 0)
     95 			cons.curr_row = 0;
     96 	}
     97 
     98 	cons.fp_putc_xy(&cons,
     99 			cons.curr_col * VIDEO_FONT_WIDTH,
    100 			cons.curr_row * VIDEO_FONT_HEIGHT, ' ');
    101 }
    102 
    103 static inline void console_newline(void)
    104 {
    105 	const int rows = CONFIG_CONSOLE_SCROLL_LINES;
    106 	int bg_color = lcd_getbgcolor();
    107 	int i;
    108 
    109 	cons.curr_col = 0;
    110 
    111 	/* Check if we need to scroll the terminal */
    112 	if (++cons.curr_row >= cons.rows) {
    113 		for (i = 0; i < cons.rows-rows; i++)
    114 			cons.fp_console_moverow(&cons, i, i+rows);
    115 		for (i = 0; i < rows; i++)
    116 			cons.fp_console_setrow(&cons, cons.rows-i-1, bg_color);
    117 		cons.curr_row -= rows;
    118 	}
    119 	lcd_sync();
    120 }
    121 
    122 void console_calc_rowcol(struct console_t *pcons, u32 sizex, u32 sizey)
    123 {
    124 	pcons->cols = sizex / VIDEO_FONT_WIDTH;
    125 #if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
    126 	pcons->rows = (pcons->lcdsizey - BMP_LOGO_HEIGHT);
    127 	pcons->rows /= VIDEO_FONT_HEIGHT;
    128 #else
    129 	pcons->rows = sizey / VIDEO_FONT_HEIGHT;
    130 #endif
    131 }
    132 
    133 void __weak lcd_init_console_rot(struct console_t *pcons)
    134 {
    135 	return;
    136 }
    137 
    138 void lcd_init_console(void *address, int vl_cols, int vl_rows, int vl_rot)
    139 {
    140 	memset(&cons, 0, sizeof(cons));
    141 	cons.fbbase = address;
    142 
    143 	cons.lcdsizex = vl_cols;
    144 	cons.lcdsizey = vl_rows;
    145 	cons.lcdrot = vl_rot;
    146 
    147 	cons.fp_putc_xy = &lcd_putc_xy0;
    148 	cons.fp_console_moverow = &console_moverow0;
    149 	cons.fp_console_setrow = &console_setrow0;
    150 	console_calc_rowcol(&cons, cons.lcdsizex, cons.lcdsizey);
    151 
    152 	lcd_init_console_rot(&cons);
    153 
    154 	debug("lcd_console: have %d/%d col/rws on scr %dx%d (%d deg rotated)\n",
    155 	      cons.cols, cons.rows, cons.lcdsizex, cons.lcdsizey, vl_rot);
    156 }
    157 
    158 void lcd_putc(const char c)
    159 {
    160 	if (!lcd_is_enabled) {
    161 		serial_putc(c);
    162 
    163 		return;
    164 	}
    165 
    166 	switch (c) {
    167 	case '\r':
    168 		cons.curr_col = 0;
    169 		return;
    170 	case '\n':
    171 		console_newline();
    172 
    173 		return;
    174 	case '\t':	/* Tab (8 chars alignment) */
    175 		cons.curr_col +=  8;
    176 		cons.curr_col &= ~7;
    177 
    178 		if (cons.curr_col >= cons.cols)
    179 			console_newline();
    180 
    181 		return;
    182 	case '\b':
    183 		console_back();
    184 
    185 		return;
    186 	default:
    187 		cons.fp_putc_xy(&cons,
    188 				cons.curr_col * VIDEO_FONT_WIDTH,
    189 				cons.curr_row * VIDEO_FONT_HEIGHT, c);
    190 		if (++cons.curr_col >= cons.cols)
    191 			console_newline();
    192 	}
    193 }
    194 
    195 void lcd_puts(const char *s)
    196 {
    197 	if (!lcd_is_enabled) {
    198 		serial_puts(s);
    199 
    200 		return;
    201 	}
    202 
    203 	while (*s)
    204 		lcd_putc(*s++);
    205 
    206 	lcd_sync();
    207 }
    208 
    209 void lcd_printf(const char *fmt, ...)
    210 {
    211 	va_list args;
    212 	char buf[CONFIG_SYS_PBSIZE];
    213 
    214 	va_start(args, fmt);
    215 	vsprintf(buf, fmt, args);
    216 	va_end(args);
    217 
    218 	lcd_puts(buf);
    219 }
    220 
    221 static int do_lcd_setcursor(cmd_tbl_t *cmdtp, int flag, int argc,
    222 			    char *const argv[])
    223 {
    224 	unsigned int col, row;
    225 
    226 	if (argc != 3)
    227 		return CMD_RET_USAGE;
    228 
    229 	col = simple_strtoul(argv[1], NULL, 10);
    230 	row = simple_strtoul(argv[2], NULL, 10);
    231 	lcd_position_cursor(col, row);
    232 
    233 	return 0;
    234 }
    235 
    236 static int do_lcd_puts(cmd_tbl_t *cmdtp, int flag, int argc,
    237 		       char *const argv[])
    238 {
    239 	if (argc != 2)
    240 		return CMD_RET_USAGE;
    241 
    242 	lcd_puts(argv[1]);
    243 
    244 	return 0;
    245 }
    246 
    247 U_BOOT_CMD(
    248 	setcurs, 3,	1,	do_lcd_setcursor,
    249 	"set cursor position within screen",
    250 	"    <col> <row> in character"
    251 );
    252 
    253 U_BOOT_CMD(
    254 	lcdputs, 2,	1,	do_lcd_puts,
    255 	"print string on lcd-framebuffer",
    256 	"    <string>"
    257 );
    258 
    259