xref: /openbmc/u-boot/drivers/video/sandbox_osd.c (revision 5c8fd32b)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2018
4  * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5  */
6 #include <common.h>
7 #include <display.h>
8 #include <dm.h>
9 #include <video_osd.h>
10 
11 #include "sandbox_osd.h"
12 
13 struct sandbox_osd_priv {
14 	uint width;
15 	uint height;
16 	u16 *buf;
17 };
18 
19 static const struct udevice_id sandbox_osd_ids[] = {
20 	{ .compatible = "sandbox,sandbox_osd" },
21 	{ }
22 };
23 
24 inline u16 make_memval(u8 chr, u8 color)
25 {
26 	return chr * 0x100 + color;
27 }
28 
29 int sandbox_osd_get_info(struct udevice *dev, struct video_osd_info *info)
30 {
31 	struct sandbox_osd_priv *priv = dev_get_priv(dev);
32 
33 	info->width = priv->width;
34 	info->height = priv->height;
35 	info->major_version = 1;
36 	info->minor_version = 0;
37 
38 	return 0;
39 }
40 
41 int sandbox_osd_set_mem(struct udevice *dev, uint col, uint row, u8 *buf,
42 			size_t buflen, uint count)
43 {
44 	struct sandbox_osd_priv *priv = dev_get_priv(dev);
45 	int pos;
46 	u8 *mem = (u8 *)priv->buf;
47 	int i;
48 
49 	pos = 2 * (row * priv->width + col);
50 
51 	if (pos >= 2 * (priv->width * priv->height))
52 		return -EINVAL;
53 
54 	for (i = 0; i < count; i++)
55 		memcpy(mem + pos + (i * buflen), buf, buflen);
56 
57 	return 0;
58 }
59 
60 int _sandbox_osd_set_size(struct udevice *dev, uint col, uint row)
61 {
62 	struct sandbox_osd_priv *priv = dev_get_priv(dev);
63 	int i;
64 	uint size;
65 
66 	priv->width = col;
67 	priv->height = row;
68 	size = priv->width * priv->height;
69 	if (!priv->buf)
70 		priv->buf = calloc(size, sizeof(u16));
71 	else
72 		priv->buf = realloc(priv->buf, size * sizeof(u16));
73 
74 	if (!priv->buf)
75 		return -ENOMEM;
76 
77 	/* Fill OSD with black spaces */
78 	for (i = 0; i < size; i++)
79 		priv->buf[i] = make_memval(' ', 'k');
80 
81 	return 0;
82 }
83 
84 int sandbox_osd_set_size(struct udevice *dev, uint col, uint row)
85 {
86 	return _sandbox_osd_set_size(dev, col, row);
87 }
88 
89 int sandbox_osd_print(struct udevice *dev, uint col, uint row, ulong color,
90 		      char *text)
91 {
92 	struct sandbox_osd_priv *priv = dev_get_priv(dev);
93 	char cval;
94 	char *p;
95 	int pos;
96 
97 	if (col >= priv->width || row >= priv->height)
98 		return -EINVAL;
99 
100 	switch (color) {
101 	case COLOR_BLACK:
102 		cval = 'k';
103 		break;
104 	case COLOR_WHITE:
105 		cval = 'w';
106 		break;
107 	case COLOR_RED:
108 		cval = 'r';
109 		break;
110 	case COLOR_GREEN:
111 		cval = 'g';
112 		break;
113 	case COLOR_BLUE:
114 		cval = 'b';
115 		break;
116 	default:
117 		return -EINVAL;
118 	}
119 
120 	p = text;
121 	pos = row * priv->width + col;
122 
123 	while (*p)
124 		priv->buf[pos++] = make_memval(*(p++), cval);
125 
126 	return 0;
127 }
128 
129 int sandbox_osd_get_mem(struct udevice *dev, u8 *buf, size_t buflen)
130 {
131 	struct sandbox_osd_priv *priv = dev_get_priv(dev);
132 	uint memsize = 2 * (priv->width * priv->height);
133 
134 	if (buflen < memsize)
135 		return -EINVAL;
136 
137 	memcpy(buf, priv->buf, memsize);
138 
139 	return 0;
140 }
141 
142 static const struct video_osd_ops sandbox_osd_ops = {
143 	.get_info = sandbox_osd_get_info,
144 	.set_mem = sandbox_osd_set_mem,
145 	.set_size = sandbox_osd_set_size,
146 	.print = sandbox_osd_print,
147 };
148 
149 int sandbox_osd_probe(struct udevice *dev)
150 {
151 	return _sandbox_osd_set_size(dev, 10, 10);
152 }
153 
154 U_BOOT_DRIVER(sandbox_osd_drv) = {
155 	.name           = "sandbox_osd_drv",
156 	.id             = UCLASS_VIDEO_OSD,
157 	.ops		= &sandbox_osd_ops,
158 	.of_match       = sandbox_osd_ids,
159 	.probe          = sandbox_osd_probe,
160 	.priv_auto_alloc_size = sizeof(struct sandbox_osd_priv),
161 };
162