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