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