blob: 243b7c5c990465b6dbe5b9b3be0d86a76c06566f [file] [log] [blame]
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +02001/*
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 lcd_console_address
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020015#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * console_rows)
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020016
17static short console_curr_col;
18static short console_curr_row;
19static short console_cols;
20static short console_rows;
21static void *lcd_console_address;
22
23void lcd_init_console(void *address, int rows, int cols)
24{
25 console_curr_col = 0;
26 console_curr_row = 0;
27 console_cols = cols;
28 console_rows = rows;
29 lcd_console_address = address;
30}
31
32void lcd_set_col(short col)
33{
34 console_curr_col = col;
35}
36
37void lcd_set_row(short row)
38{
39 console_curr_row = row;
40}
41
42void lcd_position_cursor(unsigned col, unsigned row)
43{
44 console_curr_col = min_t(short, col, console_cols - 1);
45 console_curr_row = min_t(short, row, console_rows - 1);
46}
47
48int lcd_get_screen_rows(void)
49{
50 return console_rows;
51}
52
53int lcd_get_screen_columns(void)
54{
55 return console_cols;
56}
57
Hannes Petermaiera1654042015-03-27 08:01:35 +010058static void lcd_putc_xy(ushort x, ushort y, char c)
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020059{
60 uchar *dest;
61 ushort row;
62 int fg_color, bg_color;
Hannes Petermaiera1654042015-03-27 08:01:35 +010063 int i;
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020064
65 dest = (uchar *)(lcd_console_address +
66 y * lcd_line_length + x * NBITS(LCD_BPP) / 8);
67
68 for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020069#if LCD_BPP == LCD_COLOR16
70 ushort *d = (ushort *)dest;
71#elif LCD_BPP == LCD_COLOR32
72 u32 *d = (u32 *)dest;
73#else
74 uchar *d = dest;
75#endif
76
77 fg_color = lcd_getfgcolor();
78 bg_color = lcd_getbgcolor();
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020079
Hannes Petermaiera1654042015-03-27 08:01:35 +010080 uchar bits;
81 bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020082
Hannes Petermaiera1654042015-03-27 08:01:35 +010083 for (i = 0; i < 8; ++i) {
84 *d++ = (bits & 0x80) ? fg_color : bg_color;
85 bits <<= 1;
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020086 }
87 }
88}
89
Nikita Kiryanovf6ebf6a2014-12-08 17:14:45 +020090static void console_scrollup(void)
91{
92 const int rows = CONFIG_CONSOLE_SCROLL_LINES;
93 int bg_color = lcd_getbgcolor();
94
95 /* Copy up rows ignoring those that will be overwritten */
96 memcpy(CONSOLE_ROW_FIRST,
97 lcd_console_address + CONSOLE_ROW_SIZE * rows,
98 CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
99
100 /* Clear the last rows */
101#if (LCD_BPP != LCD_COLOR32)
102 memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
103 bg_color, CONSOLE_ROW_SIZE * rows);
104#else
105 u32 *ppix = lcd_console_address +
106 CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows;
107 u32 i;
108 for (i = 0;
109 i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix);
110 i++) {
111 *ppix++ = bg_color;
112 }
113#endif
114 lcd_sync();
115 console_curr_row -= rows;
116}
117
118static inline void console_back(void)
119{
120 if (--console_curr_col < 0) {
121 console_curr_col = console_cols - 1;
122 if (--console_curr_row < 0)
123 console_curr_row = 0;
124 }
125
126 lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH,
127 console_curr_row * VIDEO_FONT_HEIGHT, ' ');
128}
129
130static inline void console_newline(void)
131{
132 console_curr_col = 0;
133
134 /* Check if we need to scroll the terminal */
135 if (++console_curr_row >= console_rows)
136 console_scrollup();
137 else
138 lcd_sync();
139}
140
141void lcd_putc(const char c)
142{
143 if (!lcd_is_enabled) {
144 serial_putc(c);
145
146 return;
147 }
148
149 switch (c) {
150 case '\r':
151 console_curr_col = 0;
152
153 return;
154 case '\n':
155 console_newline();
156
157 return;
158 case '\t': /* Tab (8 chars alignment) */
159 console_curr_col += 8;
160 console_curr_col &= ~7;
161
162 if (console_curr_col >= console_cols)
163 console_newline();
164
165 return;
166 case '\b':
167 console_back();
168
169 return;
170 default:
171 lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH,
172 console_curr_row * VIDEO_FONT_HEIGHT, c);
173 if (++console_curr_col >= console_cols)
174 console_newline();
175 }
176}
177
178void lcd_puts(const char *s)
179{
180 if (!lcd_is_enabled) {
181 serial_puts(s);
182
183 return;
184 }
185
186 while (*s)
187 lcd_putc(*s++);
188
189 lcd_sync();
190}
191
192void lcd_printf(const char *fmt, ...)
193{
194 va_list args;
195 char buf[CONFIG_SYS_PBSIZE];
196
197 va_start(args, fmt);
198 vsprintf(buf, fmt, args);
199 va_end(args);
200
201 lcd_puts(buf);
202}
Hannes Petermaier267c1402015-02-03 13:22:24 +0100203
204static int do_lcd_setcursor(cmd_tbl_t *cmdtp, int flag, int argc,
205 char *const argv[])
206{
207 unsigned int col, row;
208
209 if (argc != 3)
210 return CMD_RET_USAGE;
211
212 col = simple_strtoul(argv[1], NULL, 10);
213 row = simple_strtoul(argv[2], NULL, 10);
214 lcd_position_cursor(col, row);
215
216 return 0;
217}
218
Hannes Petermaier092f2ac2015-02-03 13:22:25 +0100219static int do_lcd_puts(cmd_tbl_t *cmdtp, int flag, int argc,
220 char *const argv[])
221{
222 if (argc != 2)
223 return CMD_RET_USAGE;
224
225 lcd_puts(argv[1]);
226
227 return 0;
228}
229
Hannes Petermaier267c1402015-02-03 13:22:24 +0100230U_BOOT_CMD(
231 setcurs, 3, 1, do_lcd_setcursor,
232 "set cursor position within screen",
233 " <col> <row> in character"
234);
Hannes Petermaier092f2ac2015-02-03 13:22:25 +0100235
236U_BOOT_CMD(
237 lcdputs, 2, 1, do_lcd_puts,
238 "print string on lcd-framebuffer",
239 " <string>"
240);
241