1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (c) 2015 Google, Inc
4 */
5
6 #define LOG_CATEGORY UCLASS_VIDEO
7
8 #include <common.h>
9 #include <console.h>
10 #include <cpu_func.h>
11 #include <dm.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <mapmem.h>
15 #include <stdio_dev.h>
16 #include <video.h>
17 #include <video_console.h>
18 #include <asm/cache.h>
19 #include <asm/global_data.h>
20 #include <dm/lists.h>
21 #include <dm/device_compat.h>
22 #include <dm/device-internal.h>
23 #include <dm/uclass-internal.h>
24 #ifdef CONFIG_SANDBOX
25 #include <asm/sdl.h>
26 #endif
27
28 /*
29 * Theory of operation:
30 *
31 * Before relocation each device is bound. The driver for each device must
32 * set the @align and @size values in struct video_uc_plat. This
33 * information represents the requires size and alignment of the frame buffer
34 * for the device. The values can be an over-estimate but cannot be too
35 * small. The actual values will be suppled (in the same manner) by the bind()
36 * method after relocation. Additionally driver can allocate frame buffer
37 * itself by setting plat->base.
38 *
39 * This information is then picked up by video_reserve() which works out how
40 * much memory is needed for all devices. This is allocated between
41 * gd->video_bottom and gd->video_top.
42 *
43 * After relocation the same process occurs. The driver supplies the same
44 * @size and @align information and this time video_post_bind() checks that
45 * the drivers does not overflow the allocated memory.
46 *
47 * The frame buffer address is actually set (to plat->base) in
48 * video_post_probe(). This function also clears the frame buffer and
49 * allocates a suitable text console device. This can then be used to write
50 * text to the video device.
51 */
52 DECLARE_GLOBAL_DATA_PTR;
53
54 /**
55 * struct video_uc_priv - Information for the video uclass
56 *
57 * @video_ptr: Current allocation position of the video framebuffer pointer.
58 * While binding devices after relocation, this points to the next
59 * available address to use for a device's framebuffer. It starts at
60 * gd->video_top and works downwards, running out of space when it hits
61 * gd->video_bottom.
62 */
63 struct video_uc_priv {
64 ulong video_ptr;
65 };
66
67 /** struct vid_rgb - Describes a video colour */
68 struct vid_rgb {
69 u32 r;
70 u32 g;
71 u32 b;
72 };
73
video_set_flush_dcache(struct udevice * dev,bool flush)74 void video_set_flush_dcache(struct udevice *dev, bool flush)
75 {
76 struct video_priv *priv = dev_get_uclass_priv(dev);
77
78 priv->flush_dcache = flush;
79 }
80
alloc_fb_(ulong align,ulong size,ulong * addrp)81 static ulong alloc_fb_(ulong align, ulong size, ulong *addrp)
82 {
83 ulong base;
84
85 align = align ? align : 1 << 20;
86 base = *addrp - size;
87 base &= ~(align - 1);
88 size = *addrp - base;
89 *addrp = base;
90
91 return size;
92 }
93
alloc_fb(struct udevice * dev,ulong * addrp)94 static ulong alloc_fb(struct udevice *dev, ulong *addrp)
95 {
96 struct video_uc_plat *plat = dev_get_uclass_plat(dev);
97 ulong size;
98
99 if (!plat->size) {
100 if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_size) {
101 size = alloc_fb_(plat->align, plat->copy_size, addrp);
102 plat->copy_base = *addrp;
103 return size;
104 }
105
106 return 0;
107 }
108
109 /* Allow drivers to allocate the frame buffer themselves */
110 if (plat->base)
111 return 0;
112
113 size = alloc_fb_(plat->align, plat->size, addrp);
114 plat->base = *addrp;
115
116 return size;
117 }
118
video_reserve(ulong * addrp)119 int video_reserve(ulong *addrp)
120 {
121 struct udevice *dev;
122 ulong size;
123
124 gd->video_top = *addrp;
125 for (uclass_find_first_device(UCLASS_VIDEO, &dev);
126 dev;
127 uclass_find_next_device(&dev)) {
128 size = alloc_fb(dev, addrp);
129 debug("%s: Reserving %lx bytes at %lx for video device '%s'\n",
130 __func__, size, *addrp, dev->name);
131 }
132
133 /* Allocate space for PCI video devices in case there were not bound */
134 if (*addrp == gd->video_top)
135 *addrp -= CONFIG_VAL(VIDEO_PCI_DEFAULT_FB_SIZE);
136
137 gd->video_bottom = *addrp;
138 gd->fb_base = *addrp;
139 debug("Video frame buffers from %lx to %lx\n", gd->video_bottom,
140 gd->video_top);
141
142 return 0;
143 }
144
video_fill(struct udevice * dev,u32 colour)145 int video_fill(struct udevice *dev, u32 colour)
146 {
147 struct video_priv *priv = dev_get_uclass_priv(dev);
148 int ret;
149
150 switch (priv->bpix) {
151 case VIDEO_BPP16:
152 if (CONFIG_IS_ENABLED(VIDEO_BPP16)) {
153 u16 *ppix = priv->fb;
154 u16 *end = priv->fb + priv->fb_size;
155
156 while (ppix < end)
157 *ppix++ = colour;
158 break;
159 }
160 case VIDEO_BPP32:
161 if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
162 u32 *ppix = priv->fb;
163 u32 *end = priv->fb + priv->fb_size;
164
165 while (ppix < end)
166 *ppix++ = colour;
167 break;
168 }
169 default:
170 memset(priv->fb, colour, priv->fb_size);
171 break;
172 }
173 ret = video_sync_copy(dev, priv->fb, priv->fb + priv->fb_size);
174 if (ret)
175 return ret;
176
177 return video_sync(dev, false);
178 }
179
video_clear(struct udevice * dev)180 int video_clear(struct udevice *dev)
181 {
182 struct video_priv *priv = dev_get_uclass_priv(dev);
183 int ret;
184
185 ret = video_fill(dev, priv->colour_bg);
186 if (ret)
187 return ret;
188
189 return 0;
190 }
191
192 static const struct vid_rgb colours[VID_COLOUR_COUNT] = {
193 { 0x00, 0x00, 0x00 }, /* black */
194 { 0xc0, 0x00, 0x00 }, /* red */
195 { 0x00, 0xc0, 0x00 }, /* green */
196 { 0xc0, 0x60, 0x00 }, /* brown */
197 { 0x00, 0x00, 0xc0 }, /* blue */
198 { 0xc0, 0x00, 0xc0 }, /* magenta */
199 { 0x00, 0xc0, 0xc0 }, /* cyan */
200 { 0xc0, 0xc0, 0xc0 }, /* light gray */
201 { 0x80, 0x80, 0x80 }, /* gray */
202 { 0xff, 0x00, 0x00 }, /* bright red */
203 { 0x00, 0xff, 0x00 }, /* bright green */
204 { 0xff, 0xff, 0x00 }, /* yellow */
205 { 0x00, 0x00, 0xff }, /* bright blue */
206 { 0xff, 0x00, 0xff }, /* bright magenta */
207 { 0x00, 0xff, 0xff }, /* bright cyan */
208 { 0xff, 0xff, 0xff }, /* white */
209 };
210
video_index_to_colour(struct video_priv * priv,unsigned int idx)211 u32 video_index_to_colour(struct video_priv *priv, unsigned int idx)
212 {
213 switch (priv->bpix) {
214 case VIDEO_BPP16:
215 if (CONFIG_IS_ENABLED(VIDEO_BPP16)) {
216 return ((colours[idx].r >> 3) << 11) |
217 ((colours[idx].g >> 2) << 5) |
218 ((colours[idx].b >> 3) << 0);
219 }
220 break;
221 case VIDEO_BPP32:
222 if (CONFIG_IS_ENABLED(VIDEO_BPP32)) {
223 if (priv->format == VIDEO_X2R10G10B10)
224 return (colours[idx].r << 22) |
225 (colours[idx].g << 12) |
226 (colours[idx].b << 2);
227 else
228 return (colours[idx].r << 16) |
229 (colours[idx].g << 8) |
230 (colours[idx].b << 0);
231 }
232 break;
233 default:
234 break;
235 }
236
237 /*
238 * For unknown bit arrangements just support
239 * black and white.
240 */
241 if (idx)
242 return 0xffffff; /* white */
243
244 return 0x000000; /* black */
245 }
246
video_set_default_colors(struct udevice * dev,bool invert)247 void video_set_default_colors(struct udevice *dev, bool invert)
248 {
249 struct video_priv *priv = dev_get_uclass_priv(dev);
250 int fore, back;
251
252 if (CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK)) {
253 /* White is used when switching to bold, use light gray here */
254 fore = VID_LIGHT_GRAY;
255 back = VID_BLACK;
256 } else {
257 fore = VID_BLACK;
258 back = VID_WHITE;
259 }
260 if (invert) {
261 int temp;
262
263 temp = fore;
264 fore = back;
265 back = temp;
266 }
267 priv->fg_col_idx = fore;
268 priv->bg_col_idx = back;
269 priv->colour_fg = video_index_to_colour(priv, fore);
270 priv->colour_bg = video_index_to_colour(priv, back);
271 }
272
273 /* Flush video activity to the caches */
video_sync(struct udevice * vid,bool force)274 int video_sync(struct udevice *vid, bool force)
275 {
276 struct video_ops *ops = video_get_ops(vid);
277 int ret;
278
279 if (ops && ops->video_sync) {
280 ret = ops->video_sync(vid);
281 if (ret)
282 return ret;
283 }
284
285 /*
286 * flush_dcache_range() is declared in common.h but it seems that some
287 * architectures do not actually implement it. Is there a way to find
288 * out whether it exists? For now, ARM is safe.
289 */
290 #if defined(CONFIG_ARM) && !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
291 struct video_priv *priv = dev_get_uclass_priv(vid);
292
293 if (priv->flush_dcache) {
294 flush_dcache_range((ulong)priv->fb,
295 ALIGN((ulong)priv->fb + priv->fb_size,
296 CONFIG_SYS_CACHELINE_SIZE));
297 }
298 #elif defined(CONFIG_VIDEO_SANDBOX_SDL)
299 struct video_priv *priv = dev_get_uclass_priv(vid);
300 static ulong last_sync;
301
302 if (force || get_timer(last_sync) > 100) {
303 sandbox_sdl_sync(priv->fb);
304 last_sync = get_timer(0);
305 }
306 #endif
307 return 0;
308 }
309
video_sync_all(void)310 void video_sync_all(void)
311 {
312 struct udevice *dev;
313 int ret;
314
315 for (uclass_find_first_device(UCLASS_VIDEO, &dev);
316 dev;
317 uclass_find_next_device(&dev)) {
318 if (device_active(dev)) {
319 ret = video_sync(dev, true);
320 if (ret)
321 dev_dbg(dev, "Video sync failed\n");
322 }
323 }
324 }
325
video_is_active(void)326 bool video_is_active(void)
327 {
328 struct udevice *dev;
329
330 for (uclass_find_first_device(UCLASS_VIDEO, &dev);
331 dev;
332 uclass_find_next_device(&dev)) {
333 if (device_active(dev))
334 return true;
335 }
336
337 return false;
338 }
339
video_get_xsize(struct udevice * dev)340 int video_get_xsize(struct udevice *dev)
341 {
342 struct video_priv *priv = dev_get_uclass_priv(dev);
343
344 return priv->xsize;
345 }
346
video_get_ysize(struct udevice * dev)347 int video_get_ysize(struct udevice *dev)
348 {
349 struct video_priv *priv = dev_get_uclass_priv(dev);
350
351 return priv->ysize;
352 }
353
354 #ifdef CONFIG_VIDEO_COPY
video_sync_copy(struct udevice * dev,void * from,void * to)355 int video_sync_copy(struct udevice *dev, void *from, void *to)
356 {
357 struct video_priv *priv = dev_get_uclass_priv(dev);
358
359 if (priv->copy_fb) {
360 long offset, size;
361
362 /* Find the offset of the first byte to copy */
363 if ((ulong)to > (ulong)from) {
364 size = to - from;
365 offset = from - priv->fb;
366 } else {
367 size = from - to;
368 offset = to - priv->fb;
369 }
370
371 /*
372 * Allow a bit of leeway for valid requests somewhere near the
373 * frame buffer
374 */
375 if (offset < -priv->fb_size || offset > 2 * priv->fb_size) {
376 #ifdef DEBUG
377 char str[120];
378
379 snprintf(str, sizeof(str),
380 "[** FAULT sync_copy fb=%p, from=%p, to=%p, offset=%lx]",
381 priv->fb, from, to, offset);
382 console_puts_select_stderr(true, str);
383 #endif
384 return -EFAULT;
385 }
386
387 /*
388 * Silently crop the memcpy. This allows callers to avoid doing
389 * this themselves. It is common for the end pointer to go a
390 * few lines after the end of the frame buffer, since most of
391 * the update algorithms terminate a line after their last write
392 */
393 if (offset + size > priv->fb_size) {
394 size = priv->fb_size - offset;
395 } else if (offset < 0) {
396 size += offset;
397 offset = 0;
398 }
399
400 memcpy(priv->copy_fb + offset, priv->fb + offset, size);
401 }
402
403 return 0;
404 }
405
video_sync_copy_all(struct udevice * dev)406 int video_sync_copy_all(struct udevice *dev)
407 {
408 struct video_priv *priv = dev_get_uclass_priv(dev);
409
410 video_sync_copy(dev, priv->fb, priv->fb + priv->fb_size);
411
412 return 0;
413 }
414
415 #endif
416
417 #define SPLASH_DECL(_name) \
418 extern u8 __splash_ ## _name ## _begin[]; \
419 extern u8 __splash_ ## _name ## _end[]
420
421 #define SPLASH_START(_name) __splash_ ## _name ## _begin
422
423 SPLASH_DECL(u_boot_logo);
424
video_get_u_boot_logo(void)425 void *video_get_u_boot_logo(void)
426 {
427 return SPLASH_START(u_boot_logo);
428 }
429
show_splash(struct udevice * dev)430 static int show_splash(struct udevice *dev)
431 {
432 u8 *data = SPLASH_START(u_boot_logo);
433 int ret;
434
435 ret = video_bmp_display(dev, map_to_sysmem(data), -4, 4, true);
436
437 return 0;
438 }
439
video_default_font_height(struct udevice * dev)440 int video_default_font_height(struct udevice *dev)
441 {
442 struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
443
444 if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE))
445 return IF_ENABLED_INT(CONFIG_CONSOLE_TRUETYPE,
446 CONFIG_CONSOLE_TRUETYPE_SIZE);
447
448 return vc_priv->y_charsize;
449 }
450
451 /* Set up the display ready for use */
video_post_probe(struct udevice * dev)452 static int video_post_probe(struct udevice *dev)
453 {
454 struct video_uc_plat *plat = dev_get_uclass_plat(dev);
455 struct video_priv *priv = dev_get_uclass_priv(dev);
456 char name[30], drv[15], *str;
457 const char *drv_name = drv;
458 struct udevice *cons;
459 int ret;
460
461 /* Set up the line and display size */
462 priv->fb = map_sysmem(plat->base, plat->size);
463 if (!priv->line_length)
464 priv->line_length = priv->xsize * VNBYTES(priv->bpix);
465
466 priv->fb_size = priv->line_length * priv->ysize;
467
468 if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_base)
469 priv->copy_fb = map_sysmem(plat->copy_base, plat->size);
470
471 /* Set up colors */
472 video_set_default_colors(dev, false);
473
474 if (!CONFIG_IS_ENABLED(NO_FB_CLEAR))
475 video_clear(dev);
476
477 /*
478 * Create a text console device. For now we always do this, although
479 * it might be useful to support only bitmap drawing on the device
480 * for boards that don't need to display text. We create a TrueType
481 * console if enabled, a rotated console if the video driver requests
482 * it, otherwise a normal console.
483 *
484 * The console can be override by setting vidconsole_drv_name before
485 * probing this video driver, or in the probe() method.
486 *
487 * TrueType does not support rotation at present so fall back to the
488 * rotated console in that case.
489 */
490 if (!priv->rot && IS_ENABLED(CONFIG_CONSOLE_TRUETYPE)) {
491 snprintf(name, sizeof(name), "%s.vidconsole_tt", dev->name);
492 strcpy(drv, "vidconsole_tt");
493 } else {
494 snprintf(name, sizeof(name), "%s.vidconsole%d", dev->name,
495 priv->rot);
496 snprintf(drv, sizeof(drv), "vidconsole%d", priv->rot);
497 }
498
499 str = strdup(name);
500 if (!str)
501 return -ENOMEM;
502 if (priv->vidconsole_drv_name)
503 drv_name = priv->vidconsole_drv_name;
504 ret = device_bind_driver(dev, drv_name, str, &cons);
505 if (ret) {
506 debug("%s: Cannot bind console driver\n", __func__);
507 return ret;
508 }
509
510 ret = device_probe(cons);
511 if (ret) {
512 debug("%s: Cannot probe console driver\n", __func__);
513 return ret;
514 }
515
516 if (CONFIG_IS_ENABLED(VIDEO_LOGO) &&
517 !CONFIG_IS_ENABLED(SPLASH_SCREEN) && !plat->hide_logo) {
518 ret = show_splash(dev);
519 if (ret) {
520 log_debug("Cannot show splash screen\n");
521 return ret;
522 }
523 }
524
525 return 0;
526 };
527
528 /* Post-relocation, allocate memory for the frame buffer */
video_post_bind(struct udevice * dev)529 static int video_post_bind(struct udevice *dev)
530 {
531 struct video_uc_priv *uc_priv;
532 ulong addr;
533 ulong size;
534
535 /* Before relocation there is nothing to do here */
536 if (!(gd->flags & GD_FLG_RELOC))
537 return 0;
538
539 /* Set up the video pointer, if this is the first device */
540 uc_priv = uclass_get_priv(dev->uclass);
541 if (!uc_priv->video_ptr)
542 uc_priv->video_ptr = gd->video_top;
543
544 /* Allocate framebuffer space for this device */
545 addr = uc_priv->video_ptr;
546 size = alloc_fb(dev, &addr);
547 if (addr < gd->video_bottom) {
548 /* Device tree node may need the 'bootph-all' or
549 * 'bootph-some-ram' tag
550 */
551 printf("Video device '%s' cannot allocate frame buffer memory -ensure the device is set up before relocation\n",
552 dev->name);
553 return -ENOSPC;
554 }
555 debug("%s: Claiming %lx bytes at %lx for video device '%s'\n",
556 __func__, size, addr, dev->name);
557 uc_priv->video_ptr = addr;
558
559 return 0;
560 }
561
562 UCLASS_DRIVER(video) = {
563 .id = UCLASS_VIDEO,
564 .name = "video",
565 .flags = DM_UC_FLAG_SEQ_ALIAS,
566 .post_bind = video_post_bind,
567 .post_probe = video_post_probe,
568 .priv_auto = sizeof(struct video_uc_priv),
569 .per_device_auto = sizeof(struct video_priv),
570 .per_device_plat_auto = sizeof(struct video_uc_plat),
571 };
572