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