common/lcd_console: move single static variables into common (static) structure
[oweals/u-boot.git] / common / lcd_console.c
1 /*
2  * (C) Copyright 2001-2014
3  * DENX Software Engineering -- wd@denx.de
4  * Compulab Ltd - http://compulab.co.il/
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <lcd.h>
11 #include <video_font.h>         /* Get font data, width and height */
12
13 #define CONSOLE_ROW_SIZE        (VIDEO_FONT_HEIGHT * lcd_line_length)
14 #define CONSOLE_ROW_FIRST       cons.lcd_address
15 #define CONSOLE_SIZE            (CONSOLE_ROW_SIZE * cons.rows)
16
17 struct console_t {
18         short curr_col, curr_row;
19         short cols, rows;
20         void *lcd_address;
21 };
22 static struct console_t cons;
23
24 void lcd_init_console(void *address, int rows, int cols)
25 {
26         memset(&cons, 0, sizeof(cons));
27         cons.cols = cols;
28         cons.rows = rows;
29         cons.lcd_address = address;
30
31 }
32
33 void lcd_set_col(short col)
34 {
35         cons.curr_col = col;
36 }
37
38 void lcd_set_row(short row)
39 {
40         cons.curr_row = row;
41 }
42
43 void lcd_position_cursor(unsigned col, unsigned row)
44 {
45         cons.curr_col = min_t(short, col, cons.cols - 1);
46         cons.curr_row = min_t(short, row, cons.rows - 1);
47 }
48
49 int lcd_get_screen_rows(void)
50 {
51         return cons.rows;
52 }
53
54 int lcd_get_screen_columns(void)
55 {
56         return cons.cols;
57 }
58
59 static void lcd_putc_xy(ushort x, ushort y, char c)
60 {
61         uchar *dest;
62         ushort row;
63         int fg_color = lcd_getfgcolor();
64         int bg_color = lcd_getbgcolor();
65         int i;
66
67         dest = (uchar *)(cons.lcd_address +
68                          y * lcd_line_length + x * NBITS(LCD_BPP) / 8);
69
70         for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
71 #if LCD_BPP == LCD_COLOR16
72                 ushort *d = (ushort *)dest;
73 #elif LCD_BPP == LCD_COLOR32
74                 u32 *d = (u32 *)dest;
75 #else
76                 uchar *d = dest;
77 #endif
78                 uchar bits;
79                 bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
80
81                 for (i = 0; i < 8; ++i) {
82                         *d++ = (bits & 0x80) ? fg_color : bg_color;
83                         bits <<= 1;
84                 }
85         }
86 }
87
88 static void console_scrollup(void)
89 {
90         const int rows = CONFIG_CONSOLE_SCROLL_LINES;
91         int bg_color = lcd_getbgcolor();
92
93         /* Copy up rows ignoring those that will be overwritten */
94         memcpy(CONSOLE_ROW_FIRST,
95                cons.lcd_address + CONSOLE_ROW_SIZE * rows,
96                CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
97
98         /* Clear the last rows */
99 #if (LCD_BPP != LCD_COLOR32)
100         memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
101                bg_color, CONSOLE_ROW_SIZE * rows);
102 #else
103         u32 *ppix = cons.lcd_address +
104                     CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows;
105         u32 i;
106         for (i = 0;
107             i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix);
108             i++) {
109                 *ppix++ = bg_color;
110         }
111 #endif
112         lcd_sync();
113         cons.curr_row -= rows;
114 }
115
116 static inline void console_back(void)
117 {
118         if (--cons.curr_col < 0) {
119                 cons.curr_col = cons.cols - 1;
120                 if (--cons.curr_row < 0)
121                         cons.curr_row = 0;
122         }
123
124         lcd_putc_xy(cons.curr_col * VIDEO_FONT_WIDTH,
125                     cons.curr_row * VIDEO_FONT_HEIGHT, ' ');
126 }
127
128 static inline void console_newline(void)
129 {
130         cons.curr_col = 0;
131
132         /* Check if we need to scroll the terminal */
133         if (++cons.curr_row >= cons.rows)
134                 console_scrollup();
135         else
136                 lcd_sync();
137 }
138
139 void lcd_putc(const char c)
140 {
141         if (!lcd_is_enabled) {
142                 serial_putc(c);
143
144                 return;
145         }
146
147         switch (c) {
148         case '\r':
149                 cons.curr_col = 0;
150                 return;
151         case '\n':
152                 console_newline();
153
154                 return;
155         case '\t':      /* Tab (8 chars alignment) */
156                 cons.curr_col +=  8;
157                 cons.curr_col &= ~7;
158
159                 if (cons.curr_col >= cons.cols)
160                         console_newline();
161
162                 return;
163         case '\b':
164                 console_back();
165
166                 return;
167         default:
168                 lcd_putc_xy(cons.curr_col * VIDEO_FONT_WIDTH,
169                             cons.curr_row * VIDEO_FONT_HEIGHT, c);
170                 if (++cons.curr_col >= cons.cols)
171                         console_newline();
172         }
173 }
174
175 void lcd_puts(const char *s)
176 {
177         if (!lcd_is_enabled) {
178                 serial_puts(s);
179
180                 return;
181         }
182
183         while (*s)
184                 lcd_putc(*s++);
185
186         lcd_sync();
187 }
188
189 void lcd_printf(const char *fmt, ...)
190 {
191         va_list args;
192         char buf[CONFIG_SYS_PBSIZE];
193
194         va_start(args, fmt);
195         vsprintf(buf, fmt, args);
196         va_end(args);
197
198         lcd_puts(buf);
199 }
200
201 static int do_lcd_setcursor(cmd_tbl_t *cmdtp, int flag, int argc,
202                             char *const argv[])
203 {
204         unsigned int col, row;
205
206         if (argc != 3)
207                 return CMD_RET_USAGE;
208
209         col = simple_strtoul(argv[1], NULL, 10);
210         row = simple_strtoul(argv[2], NULL, 10);
211         lcd_position_cursor(col, row);
212
213         return 0;
214 }
215
216 static int do_lcd_puts(cmd_tbl_t *cmdtp, int flag, int argc,
217                        char *const argv[])
218 {
219         if (argc != 2)
220                 return CMD_RET_USAGE;
221
222         lcd_puts(argv[1]);
223
224         return 0;
225 }
226
227 U_BOOT_CMD(
228         setcurs, 3,     1,      do_lcd_setcursor,
229         "set cursor position within screen",
230         "    <col> <row> in character"
231 );
232
233 U_BOOT_CMD(
234         lcdputs, 2,     1,      do_lcd_puts,
235         "print string on lcd-framebuffer",
236         "    <string>"
237 );
238