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 };
437