1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (c) 2015 Google, Inc
4 * (C) Copyright 2015
5 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
6 */
7
8 #include <common.h>
9 #include <dm.h>
10 #include <video.h>
11 #include <video_console.h>
12 #include <video_font.h> /* Get font data, width and height */
13
console_set_row_1(struct udevice * dev,uint row,int clr)14 static int console_set_row_1(struct udevice *dev, uint row, int clr)
15 {
16 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
17 int pbytes = VNBYTES(vid_priv->bpix);
18 void *line;
19 int i, j;
20
21 line = vid_priv->fb + vid_priv->line_length -
22 (row + 1) * VIDEO_FONT_HEIGHT * pbytes;
23 for (j = 0; j < vid_priv->ysize; j++) {
24 switch (vid_priv->bpix) {
25 case VIDEO_BPP8:
26 if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
27 uint8_t *dst = line;
28
29 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
30 *dst++ = clr;
31 break;
32 }
33 case VIDEO_BPP16:
34 if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
35 uint16_t *dst = line;
36
37 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
38 *dst++ = clr;
39 break;
40 }
41 case VIDEO_BPP32:
42 if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
43 uint32_t *dst = line;
44
45 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
46 *dst++ = clr;
47 break;
48 }
49 default:
50 return -ENOSYS;
51 }
52 line += vid_priv->line_length;
53 }
54
55 return 0;
56 }
57
console_move_rows_1(struct udevice * dev,uint rowdst,uint rowsrc,uint count)58 static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
59 uint count)
60 {
61 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
62 void *dst;
63 void *src;
64 int pbytes = VNBYTES(vid_priv->bpix);
65 int j;
66
67 dst = vid_priv->fb + vid_priv->line_length -
68 (rowdst + count) * VIDEO_FONT_HEIGHT * pbytes;
69 src = vid_priv->fb + vid_priv->line_length -
70 (rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes;
71
72 for (j = 0; j < vid_priv->ysize; j++) {
73 memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
74 src += vid_priv->line_length;
75 dst += vid_priv->line_length;
76 }
77
78 return 0;
79 }
80
console_putc_xy_1(struct udevice * dev,uint x_frac,uint y,char ch)81 static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch)
82 {
83 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
84 struct udevice *vid = dev->parent;
85 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
86 int pbytes = VNBYTES(vid_priv->bpix);
87 int i, col;
88 int mask = 0x80;
89 void *line;
90 uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
91
92 line = vid_priv->fb + (VID_TO_PIXEL(x_frac) + 1) *
93 vid_priv->line_length - (y + 1) * pbytes;
94 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
95 return -EAGAIN;
96
97 for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
98 switch (vid_priv->bpix) {
99 case VIDEO_BPP8:
100 if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
101 uint8_t *dst = line;
102
103 for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
104 *dst-- = (pfont[i] & mask) ?
105 vid_priv->colour_fg :
106 vid_priv->colour_bg;
107 }
108 break;
109 }
110 case VIDEO_BPP16:
111 if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
112 uint16_t *dst = line;
113
114 for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
115 *dst-- = (pfont[i] & mask) ?
116 vid_priv->colour_fg :
117 vid_priv->colour_bg;
118 }
119 break;
120 }
121 case VIDEO_BPP32:
122 if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
123 uint32_t *dst = line;
124
125 for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
126 *dst-- = (pfont[i] & mask) ?
127 vid_priv->colour_fg :
128 vid_priv->colour_bg;
129 }
130 break;
131 }
132 default:
133 return -ENOSYS;
134 }
135 line += vid_priv->line_length;
136 mask >>= 1;
137 }
138
139 return VID_TO_POS(VIDEO_FONT_WIDTH);
140 }
141
142
console_set_row_2(struct udevice * dev,uint row,int clr)143 static int console_set_row_2(struct udevice *dev, uint row, int clr)
144 {
145 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
146 void *line;
147 int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
148 int i;
149
150 line = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
151 (row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
152 switch (vid_priv->bpix) {
153 case VIDEO_BPP8:
154 if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
155 uint8_t *dst = line;
156
157 for (i = 0; i < pixels; i++)
158 *dst++ = clr;
159 break;
160 }
161 case VIDEO_BPP16:
162 if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
163 uint16_t *dst = line;
164
165 for (i = 0; i < pixels; i++)
166 *dst++ = clr;
167 break;
168 }
169 case VIDEO_BPP32:
170 if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
171 uint32_t *dst = line;
172
173 for (i = 0; i < pixels; i++)
174 *dst++ = clr;
175 break;
176 }
177 default:
178 return -ENOSYS;
179 }
180
181 return 0;
182 }
183
console_move_rows_2(struct udevice * dev,uint rowdst,uint rowsrc,uint count)184 static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
185 uint count)
186 {
187 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
188 void *dst;
189 void *src;
190 void *end;
191
192 end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
193 dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT *
194 vid_priv->line_length;
195 src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT *
196 vid_priv->line_length;
197 memmove(dst, src, VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
198
199 return 0;
200 }
201
console_putc_xy_2(struct udevice * dev,uint x_frac,uint y,char ch)202 static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
203 {
204 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
205 struct udevice *vid = dev->parent;
206 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
207 int i, row;
208 void *line;
209
210 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
211 return -EAGAIN;
212
213 line = vid_priv->fb + (vid_priv->ysize - y - 1) *
214 vid_priv->line_length +
215 (vid_priv->xsize - VID_TO_PIXEL(x_frac) -
216 VIDEO_FONT_WIDTH - 1) * VNBYTES(vid_priv->bpix);
217
218 for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
219 unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
220 uchar bits = video_fontdata[idx];
221
222 switch (vid_priv->bpix) {
223 case VIDEO_BPP8:
224 if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
225 uint8_t *dst = line;
226
227 for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
228 *dst-- = (bits & 0x80) ?
229 vid_priv->colour_fg :
230 vid_priv->colour_bg;
231 bits <<= 1;
232 }
233 break;
234 }
235 case VIDEO_BPP16:
236 if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
237 uint16_t *dst = line;
238
239 for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
240 *dst-- = (bits & 0x80) ?
241 vid_priv->colour_fg :
242 vid_priv->colour_bg;
243 bits <<= 1;
244 }
245 break;
246 }
247 case VIDEO_BPP32:
248 if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
249 uint32_t *dst = line;
250
251 for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
252 *dst-- = (bits & 0x80) ?
253 vid_priv->colour_fg :
254 vid_priv->colour_bg;
255 bits <<= 1;
256 }
257 break;
258 }
259 default:
260 return -ENOSYS;
261 }
262 line -= vid_priv->line_length;
263 }
264
265 return VID_TO_POS(VIDEO_FONT_WIDTH);
266 }
267
console_set_row_3(struct udevice * dev,uint row,int clr)268 static int console_set_row_3(struct udevice *dev, uint row, int clr)
269 {
270 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
271 int pbytes = VNBYTES(vid_priv->bpix);
272 void *line;
273 int i, j;
274
275 line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
276 for (j = 0; j < vid_priv->ysize; j++) {
277 switch (vid_priv->bpix) {
278 case VIDEO_BPP8:
279 if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
280 uint8_t *dst = line;
281
282 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
283 *dst++ = clr;
284 break;
285 }
286 case VIDEO_BPP16:
287 if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
288 uint16_t *dst = line;
289
290 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
291 *dst++ = clr;
292 break;
293 }
294 case VIDEO_BPP32:
295 if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
296 uint32_t *dst = line;
297
298 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
299 *dst++ = clr;
300 break;
301 }
302 default:
303 return -ENOSYS;
304 }
305 line += vid_priv->line_length;
306 }
307
308 return 0;
309 }
310
console_move_rows_3(struct udevice * dev,uint rowdst,uint rowsrc,uint count)311 static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
312 uint count)
313 {
314 struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
315 void *dst;
316 void *src;
317 int pbytes = VNBYTES(vid_priv->bpix);
318 int j;
319
320 dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
321 src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
322
323 for (j = 0; j < vid_priv->ysize; j++) {
324 memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
325 src += vid_priv->line_length;
326 dst += vid_priv->line_length;
327 }
328
329 return 0;
330 }
331
console_putc_xy_3(struct udevice * dev,uint x_frac,uint y,char ch)332 static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
333 {
334 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
335 struct udevice *vid = dev->parent;
336 struct video_priv *vid_priv = dev_get_uclass_priv(vid);
337 int pbytes = VNBYTES(vid_priv->bpix);
338 int i, col;
339 int mask = 0x80;
340 void *line = vid_priv->fb +
341 (vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1) *
342 vid_priv->line_length + y * pbytes;
343 uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
344
345 if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
346 return -EAGAIN;
347
348 for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
349 switch (vid_priv->bpix) {
350 case VIDEO_BPP8:
351 if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
352 uint8_t *dst = line;
353
354 for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
355 *dst++ = (pfont[i] & mask) ?
356 vid_priv->colour_fg :
357 vid_priv->colour_bg;
358 }
359 break;
360 }
361 case VIDEO_BPP16:
362 if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
363 uint16_t *dst = line;
364
365 for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
366 *dst++ = (pfont[i] & mask) ?
367 vid_priv->colour_fg :
368 vid_priv->colour_bg;
369 }
370 break;
371 }
372 case VIDEO_BPP32:
373 if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
374 uint32_t *dst = line;
375
376 for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
377 *dst++ = (pfont[i] & mask) ?
378 vid_priv->colour_fg :
379 vid_priv->colour_bg;
380 }
381 break;
382 }
383 default:
384 return -ENOSYS;
385 }
386 line -= vid_priv->line_length;
387 mask >>= 1;
388 }
389
390 return VID_TO_POS(VIDEO_FONT_WIDTH);
391 }
392
393
console_probe_2(struct udevice * dev)394 static int console_probe_2(struct udevice *dev)
395 {
396 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
397 struct udevice *vid_dev = dev->parent;
398 struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
399
400 vc_priv->x_charsize = VIDEO_FONT_WIDTH;
401 vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
402 vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
403 vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
404
405 return 0;
406 }
407
console_probe_1_3(struct udevice * dev)408 static int console_probe_1_3(struct udevice *dev)
409 {
410 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
411 struct udevice *vid_dev = dev->parent;
412 struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
413
414 vc_priv->x_charsize = VIDEO_FONT_WIDTH;
415 vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
416 vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
417 vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
418 vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
419
420 return 0;
421 }
422
423 struct vidconsole_ops console_ops_1 = {
424 .putc_xy = console_putc_xy_1,
425 .move_rows = console_move_rows_1,
426 .set_row = console_set_row_1,
427 };
428
429 struct vidconsole_ops console_ops_2 = {
430 .putc_xy = console_putc_xy_2,
431 .move_rows = console_move_rows_2,
432 .set_row = console_set_row_2,
433 };
434
435 struct vidconsole_ops console_ops_3 = {
436 .putc_xy = console_putc_xy_3,
437 .move_rows = console_move_rows_3,
438 .set_row = console_set_row_3,
439 };
440
441 U_BOOT_DRIVER(vidconsole_1) = {
442 .name = "vidconsole1",
443 .id = UCLASS_VIDEO_CONSOLE,
444 .ops = &console_ops_1,
445 .probe = console_probe_1_3,
446 };
447
448 U_BOOT_DRIVER(vidconsole_2) = {
449 .name = "vidconsole2",
450 .id = UCLASS_VIDEO_CONSOLE,
451 .ops = &console_ops_2,
452 .probe = console_probe_2,
453 };
454
455 U_BOOT_DRIVER(vidconsole_3) = {
456 .name = "vidconsole3",
457 .id = UCLASS_VIDEO_CONSOLE,
458 .ops = &console_ops_3,
459 .probe = console_probe_1_3,
460 };
461