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