]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
904672ee | 2 | /* |
604c7d4a | 3 | * (C) Copyright 2001-2015 |
904672ee NK |
4 | * DENX Software Engineering -- wd@denx.de |
5 | * Compulab Ltd - http://compulab.co.il/ | |
604c7d4a | 6 | * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com |
904672ee NK |
7 | */ |
8 | ||
9 | #include <common.h> | |
10 | #include <lcd.h> | |
11 | #include <video_font.h> /* Get font data, width and height */ | |
604c7d4a HP |
12 | #if defined(CONFIG_LCD_LOGO) |
13 | #include <bmp_logo.h> | |
14 | #endif | |
904672ee | 15 | |
7471142c | 16 | static struct console_t cons; |
904672ee | 17 | |
904672ee NK |
18 | void lcd_set_col(short col) |
19 | { | |
7471142c | 20 | cons.curr_col = col; |
904672ee NK |
21 | } |
22 | ||
23 | void lcd_set_row(short row) | |
24 | { | |
7471142c | 25 | cons.curr_row = row; |
904672ee NK |
26 | } |
27 | ||
28 | void lcd_position_cursor(unsigned col, unsigned row) | |
29 | { | |
7471142c HP |
30 | cons.curr_col = min_t(short, col, cons.cols - 1); |
31 | cons.curr_row = min_t(short, row, cons.rows - 1); | |
904672ee NK |
32 | } |
33 | ||
34 | int lcd_get_screen_rows(void) | |
35 | { | |
7471142c | 36 | return cons.rows; |
904672ee NK |
37 | } |
38 | ||
39 | int lcd_get_screen_columns(void) | |
40 | { | |
7471142c | 41 | return cons.cols; |
904672ee NK |
42 | } |
43 | ||
604c7d4a | 44 | static void lcd_putc_xy0(struct console_t *pcons, ushort x, ushort y, char c) |
904672ee | 45 | { |
a202c5bd HP |
46 | int fg_color = lcd_getfgcolor(); |
47 | int bg_color = lcd_getbgcolor(); | |
604c7d4a HP |
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; | |
97562c12 | 57 | bits <<= 1; |
904672ee | 58 | } |
604c7d4a | 59 | dst += (pcons->lcdsizex - VIDEO_FONT_WIDTH); |
904672ee NK |
60 | } |
61 | } | |
62 | ||
604c7d4a | 63 | static inline void console_setrow0(struct console_t *pcons, u32 row, int clr) |
904672ee | 64 | { |
604c7d4a HP |
65 | int i; |
66 | fbptr_t *dst = (fbptr_t *)pcons->fbbase + | |
67 | row * VIDEO_FONT_HEIGHT * | |
68 | pcons->lcdsizex; | |
904672ee | 69 | |
604c7d4a HP |
70 | for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++) |
71 | *dst++ = clr; | |
72 | } | |
904672ee | 73 | |
604c7d4a HP |
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++; | |
904672ee NK |
88 | } |
89 | ||
90 | static inline void console_back(void) | |
91 | { | |
7471142c HP |
92 | if (--cons.curr_col < 0) { |
93 | cons.curr_col = cons.cols - 1; | |
94 | if (--cons.curr_row < 0) | |
95 | cons.curr_row = 0; | |
904672ee NK |
96 | } |
97 | ||
604c7d4a HP |
98 | cons.fp_putc_xy(&cons, |
99 | cons.curr_col * VIDEO_FONT_WIDTH, | |
100 | cons.curr_row * VIDEO_FONT_HEIGHT, ' '); | |
904672ee NK |
101 | } |
102 | ||
103 | static inline void console_newline(void) | |
104 | { | |
604c7d4a HP |
105 | const int rows = CONFIG_CONSOLE_SCROLL_LINES; |
106 | int bg_color = lcd_getbgcolor(); | |
107 | int i; | |
108 | ||
7471142c | 109 | cons.curr_col = 0; |
904672ee NK |
110 | |
111 | /* Check if we need to scroll the terminal */ | |
604c7d4a HP |
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); | |
904672ee NK |
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': | |
7471142c | 168 | cons.curr_col = 0; |
904672ee NK |
169 | return; |
170 | case '\n': | |
171 | console_newline(); | |
172 | ||
173 | return; | |
174 | case '\t': /* Tab (8 chars alignment) */ | |
7471142c HP |
175 | cons.curr_col += 8; |
176 | cons.curr_col &= ~7; | |
904672ee | 177 | |
7471142c | 178 | if (cons.curr_col >= cons.cols) |
904672ee NK |
179 | console_newline(); |
180 | ||
181 | return; | |
182 | case '\b': | |
183 | console_back(); | |
184 | ||
185 | return; | |
186 | default: | |
604c7d4a HP |
187 | cons.fp_putc_xy(&cons, |
188 | cons.curr_col * VIDEO_FONT_WIDTH, | |
189 | cons.curr_row * VIDEO_FONT_HEIGHT, c); | |
7471142c | 190 | if (++cons.curr_col >= cons.cols) |
904672ee NK |
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 | } | |
d38d0c6a HP |
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 | ||
1b7caf11 HP |
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 | ||
d38d0c6a HP |
247 | U_BOOT_CMD( |
248 | setcurs, 3, 1, do_lcd_setcursor, | |
249 | "set cursor position within screen", | |
250 | " <col> <row> in character" | |
251 | ); | |
1b7caf11 HP |
252 | |
253 | U_BOOT_CMD( | |
254 | lcdputs, 2, 1, do_lcd_puts, | |
255 | "print string on lcd-framebuffer", | |
256 | " <string>" | |
257 | ); | |
258 |