Home | History | Annotate | Download | only in video
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (c) 2015 Google, Inc
      4  * (C) Copyright 2015
      5  * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
      6  */
      7 
      8 #include <common.h>
      9 #include <dm.h>
     10 #include <video.h>
     11 #include <video_console.h>
     12 #include <video_font.h>		/* Get font data, width and height */
     13 
     14 static int console_set_row_1(struct udevice *dev, uint row, int clr)
     15 {
     16 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
     17 	int pbytes = VNBYTES(vid_priv->bpix);
     18 	void *line;
     19 	int i, j;
     20 
     21 	line = vid_priv->fb + vid_priv->line_length -
     22 		(row + 1) * VIDEO_FONT_HEIGHT * pbytes;
     23 	for (j = 0; j < vid_priv->ysize; j++) {
     24 		switch (vid_priv->bpix) {
     25 #ifdef CONFIG_VIDEO_BPP8
     26 		case VIDEO_BPP8: {
     27 			uint8_t *dst = line;
     28 
     29 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
     30 				*dst++ = clr;
     31 			break;
     32 		}
     33 #endif
     34 #ifdef CONFIG_VIDEO_BPP16
     35 		case VIDEO_BPP16: {
     36 			uint16_t *dst = line;
     37 
     38 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
     39 				*dst++ = clr;
     40 			break;
     41 		}
     42 #endif
     43 #ifdef CONFIG_VIDEO_BPP32
     44 		case VIDEO_BPP32: {
     45 			uint32_t *dst = line;
     46 
     47 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
     48 				*dst++ = clr;
     49 			break;
     50 		}
     51 #endif
     52 		default:
     53 			return -ENOSYS;
     54 		}
     55 		line += vid_priv->line_length;
     56 	}
     57 
     58 	return 0;
     59 }
     60 
     61 static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
     62 			       uint count)
     63 {
     64 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
     65 	void *dst;
     66 	void *src;
     67 	int pbytes = VNBYTES(vid_priv->bpix);
     68 	int j;
     69 
     70 	dst = vid_priv->fb + vid_priv->line_length -
     71 		(rowdst + count) * VIDEO_FONT_HEIGHT * pbytes;
     72 	src = vid_priv->fb + vid_priv->line_length -
     73 		(rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes;
     74 
     75 	for (j = 0; j < vid_priv->ysize; j++) {
     76 		memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
     77 		src += vid_priv->line_length;
     78 		dst += vid_priv->line_length;
     79 	}
     80 
     81 	return 0;
     82 }
     83 
     84 static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch)
     85 {
     86 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
     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;
     93 	uchar *pfont = video_fontdata + ch * VIDEO_FONT_HEIGHT;
     94 
     95 	line = vid_priv->fb + (VID_TO_PIXEL(x_frac) + 1) *
     96 			vid_priv->line_length - (y + 1) * pbytes;
     97 	if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
     98 		return -EAGAIN;
     99 
    100 	for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
    101 		switch (vid_priv->bpix) {
    102 #ifdef CONFIG_VIDEO_BPP8
    103 		case VIDEO_BPP8: {
    104 			uint8_t *dst = line;
    105 
    106 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
    107 				*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
    108 					: vid_priv->colour_bg;
    109 			}
    110 			break;
    111 		}
    112 #endif
    113 #ifdef CONFIG_VIDEO_BPP16
    114 		case VIDEO_BPP16: {
    115 			uint16_t *dst = line;
    116 
    117 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
    118 				*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
    119 					: vid_priv->colour_bg;
    120 			}
    121 			break;
    122 		}
    123 #endif
    124 #ifdef CONFIG_VIDEO_BPP32
    125 		case VIDEO_BPP32: {
    126 			uint32_t *dst = line;
    127 
    128 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
    129 				*dst-- = (pfont[i] & mask) ? vid_priv->colour_fg
    130 					: vid_priv->colour_bg;
    131 			}
    132 			break;
    133 		}
    134 #endif
    135 		default:
    136 			return -ENOSYS;
    137 		}
    138 		line += vid_priv->line_length;
    139 		mask >>= 1;
    140 	}
    141 
    142 	return VID_TO_POS(VIDEO_FONT_WIDTH);
    143 }
    144 
    145 
    146 static int console_set_row_2(struct udevice *dev, uint row, int clr)
    147 {
    148 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
    149 	void *line;
    150 	int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
    151 	int i;
    152 
    153 	line = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
    154 		(row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
    155 	switch (vid_priv->bpix) {
    156 #ifdef CONFIG_VIDEO_BPP8
    157 	case VIDEO_BPP8: {
    158 		uint8_t *dst = line;
    159 
    160 		for (i = 0; i < pixels; i++)
    161 			*dst++ = clr;
    162 		break;
    163 	}
    164 #endif
    165 #ifdef CONFIG_VIDEO_BPP16
    166 	case VIDEO_BPP16: {
    167 		uint16_t *dst = line;
    168 
    169 		for (i = 0; i < pixels; i++)
    170 			*dst++ = clr;
    171 		break;
    172 	}
    173 #endif
    174 #ifdef CONFIG_VIDEO_BPP32
    175 	case VIDEO_BPP32: {
    176 		uint32_t *dst = line;
    177 
    178 		for (i = 0; i < pixels; i++)
    179 			*dst++ = clr;
    180 		break;
    181 	}
    182 #endif
    183 	default:
    184 		return -ENOSYS;
    185 	}
    186 
    187 	return 0;
    188 }
    189 
    190 static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
    191 			       uint count)
    192 {
    193 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
    194 	void *dst;
    195 	void *src;
    196 	void *end;
    197 
    198 	end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
    199 	dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT *
    200 		vid_priv->line_length;
    201 	src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT *
    202 		vid_priv->line_length;
    203 	memmove(dst, src, VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
    204 
    205 	return 0;
    206 }
    207 
    208 static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
    209 {
    210 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
    211 	struct udevice *vid = dev->parent;
    212 	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
    213 	int i, row;
    214 	void *line;
    215 
    216 	if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
    217 		return -EAGAIN;
    218 
    219 	line = vid_priv->fb + (vid_priv->ysize - y - 1) *
    220 			vid_priv->line_length +
    221 			(vid_priv->xsize - VID_TO_PIXEL(x_frac) -
    222 			VIDEO_FONT_WIDTH - 1) * VNBYTES(vid_priv->bpix);
    223 
    224 	for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
    225 		uchar bits = video_fontdata[ch * VIDEO_FONT_HEIGHT + row];
    226 
    227 		switch (vid_priv->bpix) {
    228 #ifdef CONFIG_VIDEO_BPP8
    229 		case VIDEO_BPP8: {
    230 			uint8_t *dst = line;
    231 
    232 			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
    233 				*dst-- = (bits & 0x80) ? vid_priv->colour_fg
    234 					: vid_priv->colour_bg;
    235 				bits <<= 1;
    236 			}
    237 			break;
    238 		}
    239 #endif
    240 #ifdef CONFIG_VIDEO_BPP16
    241 		case VIDEO_BPP16: {
    242 			uint16_t *dst = line;
    243 
    244 			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
    245 				*dst-- = (bits & 0x80) ? vid_priv->colour_fg
    246 					: vid_priv->colour_bg;
    247 				bits <<= 1;
    248 			}
    249 			break;
    250 		}
    251 #endif
    252 #ifdef CONFIG_VIDEO_BPP32
    253 		case VIDEO_BPP32: {
    254 			uint32_t *dst = line;
    255 
    256 			for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
    257 				*dst-- = (bits & 0x80) ? vid_priv->colour_fg
    258 					: vid_priv->colour_bg;
    259 				bits <<= 1;
    260 			}
    261 			break;
    262 		}
    263 #endif
    264 		default:
    265 			return -ENOSYS;
    266 		}
    267 		line -= vid_priv->line_length;
    268 	}
    269 
    270 	return VID_TO_POS(VIDEO_FONT_WIDTH);
    271 }
    272 
    273 static int console_set_row_3(struct udevice *dev, uint row, int clr)
    274 {
    275 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
    276 	int pbytes = VNBYTES(vid_priv->bpix);
    277 	void *line;
    278 	int i, j;
    279 
    280 	line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
    281 	for (j = 0; j < vid_priv->ysize; j++) {
    282 		switch (vid_priv->bpix) {
    283 #ifdef CONFIG_VIDEO_BPP8
    284 		case VIDEO_BPP8: {
    285 			uint8_t *dst = line;
    286 
    287 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
    288 				*dst++ = clr;
    289 			break;
    290 		}
    291 #endif
    292 #ifdef CONFIG_VIDEO_BPP16
    293 		case VIDEO_BPP16: {
    294 			uint16_t *dst = line;
    295 
    296 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
    297 				*dst++ = clr;
    298 			break;
    299 		}
    300 #endif
    301 #ifdef CONFIG_VIDEO_BPP32
    302 		case VIDEO_BPP32: {
    303 			uint32_t *dst = line;
    304 
    305 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
    306 				*dst++ = clr;
    307 			break;
    308 		}
    309 #endif
    310 		default:
    311 			return -ENOSYS;
    312 		}
    313 		line += vid_priv->line_length;
    314 	}
    315 
    316 	return 0;
    317 }
    318 
    319 static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
    320 			       uint count)
    321 {
    322 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
    323 	void *dst;
    324 	void *src;
    325 	int pbytes = VNBYTES(vid_priv->bpix);
    326 	int j;
    327 
    328 	dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
    329 	src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
    330 
    331 	for (j = 0; j < vid_priv->ysize; j++) {
    332 		memmove(dst, src, VIDEO_FONT_HEIGHT * pbytes * count);
    333 		src += vid_priv->line_length;
    334 		dst += vid_priv->line_length;
    335 	}
    336 
    337 	return 0;
    338 }
    339 
    340 static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
    341 {
    342 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
    343 	struct udevice *vid = dev->parent;
    344 	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
    345 	int pbytes = VNBYTES(vid_priv->bpix);
    346 	int i, col;
    347 	int mask = 0x80;
    348 	void *line = vid_priv->fb +
    349 		(vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1) *
    350 		vid_priv->line_length + y * pbytes;
    351 	uchar *pfont = video_fontdata + ch * VIDEO_FONT_HEIGHT;
    352 
    353 	if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
    354 		return -EAGAIN;
    355 
    356 	for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
    357 		switch (vid_priv->bpix) {
    358 #ifdef CONFIG_VIDEO_BPP8
    359 		case VIDEO_BPP8: {
    360 			uint8_t *dst = line;
    361 
    362 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
    363 				*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
    364 					: vid_priv->colour_bg;
    365 			}
    366 			break;
    367 		}
    368 #endif
    369 #ifdef CONFIG_VIDEO_BPP16
    370 		case VIDEO_BPP16: {
    371 			uint16_t *dst = line;
    372 
    373 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
    374 				*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
    375 					: vid_priv->colour_bg;
    376 			}
    377 			break;
    378 		}
    379 #endif
    380 #ifdef CONFIG_VIDEO_BPP32
    381 		case VIDEO_BPP32: {
    382 			uint32_t *dst = line;
    383 
    384 			for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
    385 				*dst++ = (pfont[i] & mask) ? vid_priv->colour_fg
    386 					: vid_priv->colour_bg;
    387 			}
    388 			break;
    389 		}
    390 #endif
    391 		default:
    392 			return -ENOSYS;
    393 		}
    394 		line -= vid_priv->line_length;
    395 		mask >>= 1;
    396 	}
    397 
    398 	return VID_TO_POS(VIDEO_FONT_WIDTH);
    399 }
    400 
    401 
    402 static int console_probe_2(struct udevice *dev)
    403 {
    404 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
    405 	struct udevice *vid_dev = dev->parent;
    406 	struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
    407 
    408 	vc_priv->x_charsize = VIDEO_FONT_WIDTH;
    409 	vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
    410 	vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
    411 	vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
    412 
    413 	return 0;
    414 }
    415 
    416 static int console_probe_1_3(struct udevice *dev)
    417 {
    418 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
    419 	struct udevice *vid_dev = dev->parent;
    420 	struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
    421 
    422 	vc_priv->x_charsize = VIDEO_FONT_WIDTH;
    423 	vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
    424 	vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
    425 	vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
    426 	vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
    427 
    428 	return 0;
    429 }
    430 
    431 struct vidconsole_ops console_ops_1 = {
    432 	.putc_xy	= console_putc_xy_1,
    433 	.move_rows	= console_move_rows_1,
    434 	.set_row	= console_set_row_1,
    435 };
    436 
    437 struct vidconsole_ops console_ops_2 = {
    438 	.putc_xy	= console_putc_xy_2,
    439 	.move_rows	= console_move_rows_2,
    440 	.set_row	= console_set_row_2,
    441 };
    442 
    443 struct vidconsole_ops console_ops_3 = {
    444 	.putc_xy	= console_putc_xy_3,
    445 	.move_rows	= console_move_rows_3,
    446 	.set_row	= console_set_row_3,
    447 };
    448 
    449 U_BOOT_DRIVER(vidconsole_1) = {
    450 	.name	= "vidconsole1",
    451 	.id	= UCLASS_VIDEO_CONSOLE,
    452 	.ops	= &console_ops_1,
    453 	.probe	= console_probe_1_3,
    454 };
    455 
    456 U_BOOT_DRIVER(vidconsole_2) = {
    457 	.name	= "vidconsole2",
    458 	.id	= UCLASS_VIDEO_CONSOLE,
    459 	.ops	= &console_ops_2,
    460 	.probe	= console_probe_2,
    461 };
    462 
    463 U_BOOT_DRIVER(vidconsole_3) = {
    464 	.name	= "vidconsole3",
    465 	.id	= UCLASS_VIDEO_CONSOLE,
    466 	.ops	= &console_ops_3,
    467 	.probe	= console_probe_1_3,
    468 };
    469