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 }
196