1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2604c7d4aSHannes Petermaier /*
3604c7d4aSHannes Petermaier  * (C) Copyright 2015
4604c7d4aSHannes Petermaier  * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
5604c7d4aSHannes Petermaier  */
6604c7d4aSHannes Petermaier 
7604c7d4aSHannes Petermaier #include <common.h>
8604c7d4aSHannes Petermaier #include <lcd.h>
9604c7d4aSHannes Petermaier #include <video_font.h>		/* Get font data, width and height */
10604c7d4aSHannes Petermaier 
lcd_putc_xy90(struct console_t * pcons,ushort x,ushort y,char c)11604c7d4aSHannes Petermaier static void lcd_putc_xy90(struct console_t *pcons, ushort x, ushort y, char c)
12604c7d4aSHannes Petermaier {
13604c7d4aSHannes Petermaier 	int fg_color = lcd_getfgcolor();
14604c7d4aSHannes Petermaier 	int bg_color = lcd_getbgcolor();
15604c7d4aSHannes Petermaier 	int col, i;
16604c7d4aSHannes Petermaier 
17604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
18604c7d4aSHannes Petermaier 				  (x+1) * pcons->lcdsizex -
19604c7d4aSHannes Petermaier 				  y;
20604c7d4aSHannes Petermaier 
21604c7d4aSHannes Petermaier 	uchar msk = 0x80;
22604c7d4aSHannes Petermaier 	uchar *pfont = video_fontdata + c * VIDEO_FONT_HEIGHT;
23604c7d4aSHannes Petermaier 	for (col = 0; col < VIDEO_FONT_WIDTH; ++col) {
24604c7d4aSHannes Petermaier 		for (i = 0; i < VIDEO_FONT_HEIGHT; ++i)
25604c7d4aSHannes Petermaier 			*dst-- = (*(pfont + i) & msk) ? fg_color : bg_color;
26604c7d4aSHannes Petermaier 		msk >>= 1;
27604c7d4aSHannes Petermaier 		dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
28604c7d4aSHannes Petermaier 	}
29604c7d4aSHannes Petermaier }
30604c7d4aSHannes Petermaier 
console_setrow90(struct console_t * pcons,u32 row,int clr)31604c7d4aSHannes Petermaier static inline void console_setrow90(struct console_t *pcons, u32 row, int clr)
32604c7d4aSHannes Petermaier {
33604c7d4aSHannes Petermaier 	int i, j;
34604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
35604c7d4aSHannes Petermaier 				  pcons->lcdsizex -
36604c7d4aSHannes Petermaier 				  row*VIDEO_FONT_HEIGHT+1;
37604c7d4aSHannes Petermaier 
38604c7d4aSHannes Petermaier 	for (j = 0; j < pcons->lcdsizey; j++) {
39604c7d4aSHannes Petermaier 		for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
40604c7d4aSHannes Petermaier 			*dst-- = clr;
41604c7d4aSHannes Petermaier 		dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
42604c7d4aSHannes Petermaier 	}
43604c7d4aSHannes Petermaier }
44604c7d4aSHannes Petermaier 
console_moverow90(struct console_t * pcons,u32 rowdst,u32 rowsrc)45604c7d4aSHannes Petermaier static inline void console_moverow90(struct console_t *pcons,
46604c7d4aSHannes Petermaier 				      u32 rowdst, u32 rowsrc)
47604c7d4aSHannes Petermaier {
48604c7d4aSHannes Petermaier 	int i, j;
49604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
50604c7d4aSHannes Petermaier 				  pcons->lcdsizex -
51604c7d4aSHannes Petermaier 				  (rowdst*VIDEO_FONT_HEIGHT+1);
52604c7d4aSHannes Petermaier 
53604c7d4aSHannes Petermaier 	fbptr_t *src = (fbptr_t *)pcons->fbbase +
54604c7d4aSHannes Petermaier 				  pcons->lcdsizex -
55604c7d4aSHannes Petermaier 				  (rowsrc*VIDEO_FONT_HEIGHT+1);
56604c7d4aSHannes Petermaier 
57604c7d4aSHannes Petermaier 	for (j = 0; j < pcons->lcdsizey; j++) {
58604c7d4aSHannes Petermaier 		for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
59604c7d4aSHannes Petermaier 			*dst-- = *src--;
60604c7d4aSHannes Petermaier 		src += (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
61604c7d4aSHannes Petermaier 		dst += (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
62604c7d4aSHannes Petermaier 	}
63604c7d4aSHannes Petermaier }
lcd_putc_xy180(struct console_t * pcons,ushort x,ushort y,char c)64604c7d4aSHannes Petermaier static void lcd_putc_xy180(struct console_t *pcons, ushort x, ushort y, char c)
65604c7d4aSHannes Petermaier {
66604c7d4aSHannes Petermaier 	int fg_color = lcd_getfgcolor();
67604c7d4aSHannes Petermaier 	int bg_color = lcd_getbgcolor();
68604c7d4aSHannes Petermaier 	int i, row;
69604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
70604c7d4aSHannes Petermaier 				  pcons->lcdsizex +
71604c7d4aSHannes Petermaier 				  pcons->lcdsizey * pcons->lcdsizex -
72604c7d4aSHannes Petermaier 				  y * pcons->lcdsizex -
73604c7d4aSHannes Petermaier 				  (x+1);
74604c7d4aSHannes Petermaier 
75604c7d4aSHannes Petermaier 	for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
76604c7d4aSHannes Petermaier 		uchar bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
77604c7d4aSHannes Petermaier 
78604c7d4aSHannes Petermaier 		for (i = 0; i < VIDEO_FONT_WIDTH; ++i) {
79604c7d4aSHannes Petermaier 			*dst-- = (bits & 0x80) ? fg_color : bg_color;
80604c7d4aSHannes Petermaier 			bits <<= 1;
81604c7d4aSHannes Petermaier 		}
82604c7d4aSHannes Petermaier 		dst -= (pcons->lcdsizex - VIDEO_FONT_WIDTH);
83604c7d4aSHannes Petermaier 	}
84604c7d4aSHannes Petermaier }
85604c7d4aSHannes Petermaier 
console_setrow180(struct console_t * pcons,u32 row,int clr)86604c7d4aSHannes Petermaier static inline void console_setrow180(struct console_t *pcons, u32 row, int clr)
87604c7d4aSHannes Petermaier {
88604c7d4aSHannes Petermaier 	int i;
89604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
90604c7d4aSHannes Petermaier 				  (pcons->rows-row-1) * VIDEO_FONT_HEIGHT *
91604c7d4aSHannes Petermaier 				  pcons->lcdsizex;
92604c7d4aSHannes Petermaier 
93604c7d4aSHannes Petermaier 	for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
94604c7d4aSHannes Petermaier 		*dst++ = clr;
95604c7d4aSHannes Petermaier }
96604c7d4aSHannes Petermaier 
console_moverow180(struct console_t * pcons,u32 rowdst,u32 rowsrc)97604c7d4aSHannes Petermaier static inline void console_moverow180(struct console_t *pcons,
98604c7d4aSHannes Petermaier 				      u32 rowdst, u32 rowsrc)
99604c7d4aSHannes Petermaier {
100604c7d4aSHannes Petermaier 	int i;
101604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
102604c7d4aSHannes Petermaier 				  (pcons->rows-rowdst-1) * VIDEO_FONT_HEIGHT *
103604c7d4aSHannes Petermaier 				  pcons->lcdsizex;
104604c7d4aSHannes Petermaier 
105604c7d4aSHannes Petermaier 	fbptr_t *src = (fbptr_t *)pcons->fbbase +
106604c7d4aSHannes Petermaier 				  (pcons->rows-rowsrc-1) * VIDEO_FONT_HEIGHT *
107604c7d4aSHannes Petermaier 				  pcons->lcdsizex;
108604c7d4aSHannes Petermaier 
109604c7d4aSHannes Petermaier 	for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
110604c7d4aSHannes Petermaier 		*dst++ = *src++;
111604c7d4aSHannes Petermaier }
112604c7d4aSHannes Petermaier 
lcd_putc_xy270(struct console_t * pcons,ushort x,ushort y,char c)113604c7d4aSHannes Petermaier static void lcd_putc_xy270(struct console_t *pcons, ushort x, ushort y, char c)
114604c7d4aSHannes Petermaier {
115604c7d4aSHannes Petermaier 	int fg_color = lcd_getfgcolor();
116604c7d4aSHannes Petermaier 	int bg_color = lcd_getbgcolor();
117604c7d4aSHannes Petermaier 	int i, col;
118604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
119604c7d4aSHannes Petermaier 				  pcons->lcdsizey * pcons->lcdsizex -
120604c7d4aSHannes Petermaier 				  (x+1) * pcons->lcdsizex +
121604c7d4aSHannes Petermaier 				  y;
122604c7d4aSHannes Petermaier 
123604c7d4aSHannes Petermaier 	uchar msk = 0x80;
124604c7d4aSHannes Petermaier 	uchar *pfont = video_fontdata + c * VIDEO_FONT_HEIGHT;
125604c7d4aSHannes Petermaier 	for (col = 0; col < VIDEO_FONT_WIDTH; ++col) {
126604c7d4aSHannes Petermaier 		for (i = 0; i < VIDEO_FONT_HEIGHT; ++i)
127604c7d4aSHannes Petermaier 			*dst++ = (*(pfont + i) & msk) ? fg_color : bg_color;
128604c7d4aSHannes Petermaier 		msk >>= 1;
129604c7d4aSHannes Petermaier 		dst -= (pcons->lcdsizex + VIDEO_FONT_HEIGHT);
130604c7d4aSHannes Petermaier 	}
131604c7d4aSHannes Petermaier }
132604c7d4aSHannes Petermaier 
console_setrow270(struct console_t * pcons,u32 row,int clr)133604c7d4aSHannes Petermaier static inline void console_setrow270(struct console_t *pcons, u32 row, int clr)
134604c7d4aSHannes Petermaier {
135604c7d4aSHannes Petermaier 	int i, j;
136604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
137604c7d4aSHannes Petermaier 				  row*VIDEO_FONT_HEIGHT;
138604c7d4aSHannes Petermaier 
139604c7d4aSHannes Petermaier 	for (j = 0; j < pcons->lcdsizey; j++) {
140604c7d4aSHannes Petermaier 		for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
141604c7d4aSHannes Petermaier 			*dst++ = clr;
142604c7d4aSHannes Petermaier 		dst += (pcons->lcdsizex - VIDEO_FONT_HEIGHT);
143604c7d4aSHannes Petermaier 	}
144604c7d4aSHannes Petermaier }
145604c7d4aSHannes Petermaier 
console_moverow270(struct console_t * pcons,u32 rowdst,u32 rowsrc)146604c7d4aSHannes Petermaier static inline void console_moverow270(struct console_t *pcons,
147604c7d4aSHannes Petermaier 				     u32 rowdst, u32 rowsrc)
148604c7d4aSHannes Petermaier {
149604c7d4aSHannes Petermaier 	int i, j;
150604c7d4aSHannes Petermaier 	fbptr_t *dst = (fbptr_t *)pcons->fbbase +
151604c7d4aSHannes Petermaier 				  rowdst*VIDEO_FONT_HEIGHT;
152604c7d4aSHannes Petermaier 
153604c7d4aSHannes Petermaier 	fbptr_t *src = (fbptr_t *)pcons->fbbase +
154604c7d4aSHannes Petermaier 				  rowsrc*VIDEO_FONT_HEIGHT;
155604c7d4aSHannes Petermaier 
156604c7d4aSHannes Petermaier 	for (j = 0; j < pcons->lcdsizey; j++) {
157604c7d4aSHannes Petermaier 		for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
158604c7d4aSHannes Petermaier 			*dst++ = *src++;
159604c7d4aSHannes Petermaier 		src += (pcons->lcdsizex - VIDEO_FONT_HEIGHT);
160604c7d4aSHannes Petermaier 		dst += (pcons->lcdsizex - VIDEO_FONT_HEIGHT);
161604c7d4aSHannes Petermaier 	}
162604c7d4aSHannes Petermaier }
163604c7d4aSHannes Petermaier 
console_calc_rowcol_rot(struct console_t * pcons)164604c7d4aSHannes Petermaier static void console_calc_rowcol_rot(struct console_t *pcons)
165604c7d4aSHannes Petermaier {
166604c7d4aSHannes Petermaier 	if (pcons->lcdrot == 1 || pcons->lcdrot == 3)
167604c7d4aSHannes Petermaier 		console_calc_rowcol(pcons, pcons->lcdsizey, pcons->lcdsizex);
168604c7d4aSHannes Petermaier 	else
169604c7d4aSHannes Petermaier 		console_calc_rowcol(pcons, pcons->lcdsizex, pcons->lcdsizey);
170604c7d4aSHannes Petermaier }
171604c7d4aSHannes Petermaier 
lcd_init_console_rot(struct console_t * pcons)172604c7d4aSHannes Petermaier void lcd_init_console_rot(struct console_t *pcons)
173604c7d4aSHannes Petermaier {
174604c7d4aSHannes Petermaier 	if (pcons->lcdrot == 0) {
175604c7d4aSHannes Petermaier 		return;
176604c7d4aSHannes Petermaier 	} else if (pcons->lcdrot == 1) {
177604c7d4aSHannes Petermaier 		pcons->fp_putc_xy = &lcd_putc_xy90;
178604c7d4aSHannes Petermaier 		pcons->fp_console_moverow = &console_moverow90;
179604c7d4aSHannes Petermaier 		pcons->fp_console_setrow = &console_setrow90;
180604c7d4aSHannes Petermaier 	} else if (pcons->lcdrot == 2) {
181604c7d4aSHannes Petermaier 		pcons->fp_putc_xy = &lcd_putc_xy180;
182604c7d4aSHannes Petermaier 		pcons->fp_console_moverow = &console_moverow180;
183604c7d4aSHannes Petermaier 		pcons->fp_console_setrow = &console_setrow180;
184604c7d4aSHannes Petermaier 	} else if (pcons->lcdrot == 3) {
185604c7d4aSHannes Petermaier 		pcons->fp_putc_xy = &lcd_putc_xy270;
186604c7d4aSHannes Petermaier 		pcons->fp_console_moverow = &console_moverow270;
187604c7d4aSHannes Petermaier 		pcons->fp_console_setrow = &console_setrow270;
188604c7d4aSHannes Petermaier 	} else {
189604c7d4aSHannes Petermaier 		printf("%s: invalid framebuffer rotation (%d)!\n",
190604c7d4aSHannes Petermaier 		       __func__, pcons->lcdrot);
191604c7d4aSHannes Petermaier 		return;
192604c7d4aSHannes Petermaier 	}
193604c7d4aSHannes Petermaier 	console_calc_rowcol_rot(pcons);
194604c7d4aSHannes Petermaier }
195