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
make_memval(u8 chr,u8 color)24 inline u16 make_memval(u8 chr, u8 color)
25 {
26 return chr * 0x100 + color;
27 }
28
sandbox_osd_get_info(struct udevice * dev,struct video_osd_info * info)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
sandbox_osd_set_mem(struct udevice * dev,uint col,uint row,u8 * buf,size_t buflen,uint count)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
_sandbox_osd_set_size(struct udevice * dev,uint col,uint row)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
sandbox_osd_set_size(struct udevice * dev,uint col,uint row)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
sandbox_osd_print(struct udevice * dev,uint col,uint row,ulong color,char * text)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
sandbox_osd_get_mem(struct udevice * dev,u8 * buf,size_t buflen)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
sandbox_osd_probe(struct udevice * dev)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