blob: dd84489add0640b3e6f58d708186556bf32356b5 [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>
9#include <video_osd.h>
10
11#include "sandbox_osd.h"
12
13struct sandbox_osd_priv {
14 uint width;
15 uint height;
16 u16 *buf;
17};
18
19static const struct udevice_id sandbox_osd_ids[] = {
20 { .compatible = "sandbox,sandbox_osd" },
21 { }
22};
23
24inline u16 make_memval(u8 chr, u8 color)
25{
26 return chr * 0x100 + color;
27}
28
29int 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
41int 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
60int _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
84int sandbox_osd_set_size(struct udevice *dev, uint col, uint row)
85{
86 return _sandbox_osd_set_size(dev, col, row);
87}
88
89int 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
129int 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
142static 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
149int sandbox_osd_probe(struct udevice *dev)
150{
151 return _sandbox_osd_set_size(dev, 10, 10);
152}
153
154U_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};