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