common/lcd_console: introduce display/framebuffer rotation
[platform/kernel/u-boot.git] / common / lcd_console_rotation.c
1 /*
2  * (C) Copyright 2015
3  * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <lcd.h>
10 #include <video_font.h>         /* Get font data, width and height */
11
12 static void lcd_putc_xy90(struct console_t *pcons, ushort x, ushort y, char c)
13 {
14         int fg_color = lcd_getfgcolor();
15         int bg_color = lcd_getbgcolor();
16         int col, i;
17
18         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
19                                   (x+1) * pcons->lcdsizex -
20                                   y;
21
22         uchar msk = 0x80;
23         uchar *pfont = video_fontdata + c * VIDEO_FONT_HEIGHT;
24         for (col = 0; col < VIDEO_FONT_WIDTH; ++col) {
25                 for (i = 0; i < VIDEO_FONT_HEIGHT; ++i)
26                         *dst-- = (*(pfont + i) & msk) ? fg_color : bg_color;
27                 msk >>= 1;
28                 dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
29         }
30 }
31
32 static inline void console_setrow90(struct console_t *pcons, u32 row, int clr)
33 {
34         int i, j;
35         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
36                                   pcons->lcdsizex -
37                                   row*VIDEO_FONT_HEIGHT+1;
38
39         for (j = 0; j < pcons->lcdsizey; j++) {
40                 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
41                         *dst-- = clr;
42                 dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
43         }
44 }
45
46 static inline void console_moverow90(struct console_t *pcons,
47                                       u32 rowdst, u32 rowsrc)
48 {
49         int i, j;
50         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
51                                   pcons->lcdsizex -
52                                   (rowdst*VIDEO_FONT_HEIGHT+1);
53
54         fbptr_t *src = (fbptr_t *)pcons->fbbase +
55                                   pcons->lcdsizex -
56                                   (rowsrc*VIDEO_FONT_HEIGHT+1);
57
58         for (j = 0; j < pcons->lcdsizey; j++) {
59                 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
60                         *dst-- = *src--;
61                 src += (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
62                 dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
63         }
64 }
65 static void lcd_putc_xy180(struct console_t *pcons, ushort x, ushort y, char c)
66 {
67         int fg_color = lcd_getfgcolor();
68         int bg_color = lcd_getbgcolor();
69         int i, row;
70         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
71                                   pcons->lcdsizex +
72                                   pcons->lcdsizey * pcons->lcdsizex -
73                                   y * pcons->lcdsizex -
74                                   (x+1);
75
76         for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
77                 uchar bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
78
79                 for (i = 0; i < VIDEO_FONT_WIDTH; ++i) {
80                         *dst-- = (bits & 0x80) ? fg_color : bg_color;
81                         bits <<= 1;
82                 }
83                 dst -= (pcons->lcdsizex - VIDEO_FONT_WIDTH);
84         }
85 }
86
87 static inline void console_setrow180(struct console_t *pcons, u32 row, int clr)
88 {
89         int i;
90         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
91                                   (pcons->rows-row-1) * VIDEO_FONT_HEIGHT *
92                                   pcons->lcdsizex;
93
94         for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
95                 *dst++ = clr;
96 }
97
98 static inline void console_moverow180(struct console_t *pcons,
99                                       u32 rowdst, u32 rowsrc)
100 {
101         int i;
102         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
103                                   (pcons->rows-rowdst-1) * VIDEO_FONT_HEIGHT *
104                                   pcons->lcdsizex;
105
106         fbptr_t *src = (fbptr_t *)pcons->fbbase +
107                                   (pcons->rows-rowsrc-1) * VIDEO_FONT_HEIGHT *
108                                   pcons->lcdsizex;
109
110         for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
111                 *dst++ = *src++;
112 }
113
114 static void lcd_putc_xy270(struct console_t *pcons, ushort x, ushort y, char c)
115 {
116         int fg_color = lcd_getfgcolor();
117         int bg_color = lcd_getbgcolor();
118         int i, col;
119         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
120                                   pcons->lcdsizey * pcons->lcdsizex -
121                                   (x+1) * pcons->lcdsizex +
122                                   y;
123
124         uchar msk = 0x80;
125         uchar *pfont = video_fontdata + c * VIDEO_FONT_HEIGHT;
126         for (col = 0; col < VIDEO_FONT_WIDTH; ++col) {
127                 for (i = 0; i < VIDEO_FONT_HEIGHT; ++i)
128                         *dst++ = (*(pfont + i) & msk) ? fg_color : bg_color;
129                 msk >>= 1;
130                 dst -= (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
131         }
132 }
133
134 static inline void console_setrow270(struct console_t *pcons, u32 row, int clr)
135 {
136         int i, j;
137         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
138                                   row*VIDEO_FONT_HEIGHT;
139
140         for (j = 0; j < pcons->lcdsizey; j++) {
141                 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
142                         *dst++ = clr;
143                 dst += (pcons->lcdsizex - VIDEO_FONT_HEIGHT);
144         }
145 }
146
147 static inline void console_moverow270(struct console_t *pcons,
148                                      u32 rowdst, u32 rowsrc)
149 {
150         int i, j;
151         fbptr_t *dst = (fbptr_t *)pcons->fbbase +
152                                   rowdst*VIDEO_FONT_HEIGHT;
153
154         fbptr_t *src = (fbptr_t *)pcons->fbbase +
155                                   rowsrc*VIDEO_FONT_HEIGHT;
156
157         for (j = 0; j < pcons->lcdsizey; j++) {
158                 for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
159                         *dst++ = *src++;
160                 src += (pcons->lcdsizex - VIDEO_FONT_HEIGHT);
161                 dst += (pcons->lcdsizex - VIDEO_FONT_HEIGHT);
162         }
163 }
164
165 static void console_calc_rowcol_rot(struct console_t *pcons)
166 {
167         if (pcons->lcdrot == 1 || pcons->lcdrot == 3)
168                 console_calc_rowcol(pcons, pcons->lcdsizey, pcons->lcdsizex);
169         else
170                 console_calc_rowcol(pcons, pcons->lcdsizex, pcons->lcdsizey);
171 }
172
173 void lcd_init_console_rot(struct console_t *pcons)
174 {
175         if (pcons->lcdrot == 0) {
176                 return;
177         } else if (pcons->lcdrot == 1) {
178                 pcons->fp_putc_xy = &lcd_putc_xy90;
179                 pcons->fp_console_moverow = &console_moverow90;
180                 pcons->fp_console_setrow = &console_setrow90;
181         } else if (pcons->lcdrot == 2) {
182                 pcons->fp_putc_xy = &lcd_putc_xy180;
183                 pcons->fp_console_moverow = &console_moverow180;
184                 pcons->fp_console_setrow = &console_setrow180;
185         } else if (pcons->lcdrot == 3) {
186                 pcons->fp_putc_xy = &lcd_putc_xy270;
187                 pcons->fp_console_moverow = &console_moverow270;
188                 pcons->fp_console_setrow = &console_setrow270;
189         } else {
190                 printf("%s: invalid framebuffer rotation (%d)!\n",
191                        __func__, pcons->lcdrot);
192                 return;
193         }
194         console_calc_rowcol_rot(pcons);
195 }