blob: 7e722326b3d9364e57a651ea37711fcd7e15425a [file] [log] [blame]
Mario Six4eea5312018-09-27 09:19:31 +02001// 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>
Simon Glass336d4612020-02-03 07:36:16 -07009#include <malloc.h>
Mario Six4eea5312018-09-27 09:19:31 +020010#include <video_osd.h>
11
12#include "sandbox_osd.h"
13
14struct sandbox_osd_priv {
15 uint width;
16 uint height;
17 u16 *buf;
18};
19
20static const struct udevice_id sandbox_osd_ids[] = {
21 { .compatible = "sandbox,sandbox_osd" },
22 { }
23};
24
25inline u16 make_memval(u8 chr, u8 color)
26{
27 return chr * 0x100 + color;
28}
29
30int 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
42int 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
61int _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
85int sandbox_osd_set_size(struct udevice *dev, uint col, uint row)
86{
87 return _sandbox_osd_set_size(dev, col, row);
88}
89
90int 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
130int 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
143static 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
150int sandbox_osd_probe(struct udevice *dev)
151{
152 return _sandbox_osd_set_size(dev, 10, 10);
153}
154
155U_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_alloc_size = sizeof(struct sandbox_osd_priv),
162};