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