Merge tag 'video-for-2019.07-rc1' of git://git.denx.de/u-boot-video
[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 + (u8)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                 unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
226                 uchar bits = video_fontdata[idx];
227
228                 switch (vid_priv->bpix) {
229 #ifdef CONFIG_VIDEO_BPP8
230                 case VIDEO_BPP8: {
231                         uint8_t *dst = line;
232
233                         for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
234                                 *dst-- = (bits & 0x80) ? vid_priv->colour_fg
235                                         : vid_priv->colour_bg;
236                                 bits <<= 1;
237                         }
238                         break;
239                 }
240 #endif
241 #ifdef CONFIG_VIDEO_BPP16
242                 case VIDEO_BPP16: {
243                         uint16_t *dst = line;
244
245                         for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
246                                 *dst-- = (bits & 0x80) ? vid_priv->colour_fg
247                                         : vid_priv->colour_bg;
248                                 bits <<= 1;
249                         }
250                         break;
251                 }
252 #endif
253 #ifdef CONFIG_VIDEO_BPP32
254                 case VIDEO_BPP32: {
255                         uint32_t *dst = line;
256
257                         for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
258                                 *dst-- = (bits & 0x80) ? vid_priv->colour_fg
259                                         : vid_priv->colour_bg;
260                                 bits <<= 1;
261                         }
262                         break;
263                 }
264 #endif
265                 default:
266                         return -ENOSYS;
267                 }
268                 line -= vid_priv->line_length;
269         }
270
271         return VID_TO_POS(VIDEO_FONT_WIDTH);
272 }
273
274 static int console_set_row_3(struct udevice *dev, uint row, int clr)
275 {
276         struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
277         int pbytes = VNBYTES(vid_priv->bpix);
278         void *line;
279         int i, j;
280
281         line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
282         for (j = 0; j < vid_priv->ysize; j++) {
283                 switch (vid_priv->bpix) {
284 #ifdef CONFIG_VIDEO_BPP8
285                 case VIDEO_BPP8: {
286                         uint8_t *dst = line;
287
288                         for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
289                                 *dst++ = clr;
290                         break;
291                 }
292 #endif
293 #ifdef CONFIG_VIDEO_BPP16
294                 case VIDEO_BPP16: {
295                         uint16_t *dst = line;
296
297                         for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
298                                 *dst++ = clr;
299                         break;
300                 }
301 #endif
302 #ifdef CONFIG_VIDEO_BPP32
303                 case VIDEO_BPP32: {
304                         uint32_t *dst = line;
305
306                         for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
307                                 *dst++ = clr;
308                         break;
309                 }
310 #endif
311                 default:
312                         return -ENOSYS;
313                 }
314                 line += vid_priv->line_length;
315         }
316
317         return 0;
318 }
319
320 static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
321                                uint count)
322 {
323         struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
324         void *dst;
325         void *src;
326         int pbytes = VNBYTES(vid_priv->bpix);
327         int j;
328
329         dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
330         src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
331
332         for (j = 0; j < vid_priv->ysize; j++) {
333                 memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
334                 src += vid_priv->line_length;
335                 dst += vid_priv->line_length;
336         }
337
338         return 0;
339 }
340
341 static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
342 {
343         struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
344         struct udevice *vid = dev->parent;
345         struct video_priv *vid_priv = dev_get_uclass_priv(vid);
346         int pbytes = VNBYTES(vid_priv->bpix);
347         int i, col;
348         int mask = 0x80;
349         void *line = vid_priv->fb +
350                 (vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1) *
351                 vid_priv->line_length + y * pbytes;
352         uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
353
354         if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
355                 return -EAGAIN;
356
357         for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
358                 switch (vid_priv->bpix) {
359 #ifdef CONFIG_VIDEO_BPP8
360                 case VIDEO_BPP8: {
361                         uint8_t *dst = line;
362
363                         for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
364                                 *dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
365                                         : vid_priv->colour_bg;
366                         }
367                         break;
368                 }
369 #endif
370 #ifdef CONFIG_VIDEO_BPP16
371                 case VIDEO_BPP16: {
372                         uint16_t *dst = line;
373
374                         for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
375                                 *dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
376                                         : vid_priv->colour_bg;
377                         }
378                         break;
379                 }
380 #endif
381 #ifdef CONFIG_VIDEO_BPP32
382                 case VIDEO_BPP32: {
383                         uint32_t *dst = line;
384
385                         for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
386                                 *dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
387                                         : vid_priv->colour_bg;
388                         }
389                         break;
390                 }
391 #endif
392                 default:
393                         return -ENOSYS;
394                 }
395                 line -= vid_priv->line_length;
396                 mask >>= 1;
397         }
398
399         return VID_TO_POS(VIDEO_FONT_WIDTH);
400 }
401
402
403 static int console_probe_2(struct udevice *dev)
404 {
405         struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
406         struct udevice *vid_dev = dev->parent;
407         struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
408
409         vc_priv->x_charsize = VIDEO_FONT_WIDTH;
410         vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
411         vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
412         vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
413
414         return 0;
415 }
416
417 static int console_probe_1_3(struct udevice *dev)
418 {
419         struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
420         struct udevice *vid_dev = dev->parent;
421         struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
422
423         vc_priv->x_charsize = VIDEO_FONT_WIDTH;
424         vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
425         vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
426         vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
427         vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
428
429         return 0;
430 }
431
432 struct vidconsole_ops console_ops_1 = {
433         .putc_xy        = console_putc_xy_1,
434         .move_rows      = console_move_rows_1,
435         .set_row        = console_set_row_1,
436 };
437
438 struct vidconsole_ops console_ops_2 = {
439         .putc_xy        = console_putc_xy_2,
440         .move_rows      = console_move_rows_2,
441         .set_row        = console_set_row_2,
442 };
443
444 struct vidconsole_ops console_ops_3 = {
445         .putc_xy        = console_putc_xy_3,
446         .move_rows      = console_move_rows_3,
447         .set_row        = console_set_row_3,
448 };
449
450 U_BOOT_DRIVER(vidconsole_1) = {
451         .name   = "vidconsole1",
452         .id     = UCLASS_VIDEO_CONSOLE,
453         .ops    = &console_ops_1,
454         .probe  = console_probe_1_3,
455 };
456
457 U_BOOT_DRIVER(vidconsole_2) = {
458         .name   = "vidconsole2",
459         .id     = UCLASS_VIDEO_CONSOLE,
460         .ops    = &console_ops_2,
461         .probe  = console_probe_2,
462 };
463
464 U_BOOT_DRIVER(vidconsole_3) = {
465         .name   = "vidconsole3",
466         .id     = UCLASS_VIDEO_CONSOLE,
467         .ops    = &console_ops_3,
468         .probe  = console_probe_1_3,
469 };