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