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