Merge tag 'u-boot-imx-next-20230404' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / cmd / osd.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2017
4  * Mario Six,  Guntermann & Drunck GmbH, mario.six@gdsys.cc
5  *
6  * based on the gdsys osd driver, which is
7  *
8  * (C) Copyright 2010
9  * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
10  */
11
12 #include <common.h>
13 #include <command.h>
14 #include <dm.h>
15 #include <hexdump.h>
16 #include <video_osd.h>
17 #include <malloc.h>
18
19 /* Container for selected OSD device */
20 static struct udevice *osd_cur;
21
22 /**
23  * cmd_osd_set_osd_num() - Set the OSD selected for operation
24  *
25  * Set the OSD device, which will be used by all subsequent OSD commands.
26  *
27  * Devices are identified by their uclass sequence number (as listed by 'osd
28  * show').
29  *
30  * @osdnum: The OSD device to be selected, identified by its sequence number.
31  * Return: 0 if OK, -ve on error
32  */
33 static int cmd_osd_set_osd_num(unsigned int osdnum)
34 {
35         struct udevice *osd;
36         int res;
37
38         res = uclass_get_device_by_seq(UCLASS_VIDEO_OSD, osdnum, &osd);
39         if (res) {
40                 printf("%s: No OSD %u (err = %d)\n", __func__, osdnum, res);
41                 return res;
42         }
43         osd_cur = osd;
44
45         return 0;
46 }
47
48 /**
49  * osd_get_osd_cur() - Get the selected OSD device
50  *
51  * Get the OSD device that is used by all OSD commands.
52  *
53  * @osdp: Pointer to structure that will receive the currently selected OSD
54  *        device.
55  * Return: 0 if OK, -ve on error
56  */
57 static int osd_get_osd_cur(struct udevice **osdp)
58 {
59         if (!osd_cur) {
60                 puts("No osd selected\n");
61                 return -ENODEV;
62         }
63         *osdp = osd_cur;
64
65         return 0;
66 }
67
68 /**
69  * show_osd() - Display information about a OSD device
70  *
71  * Display a device's ID (sequence number), and whether it is active (i.e.
72  * probed) or not.
73  *
74  * @osd: OSD device to print information for
75  */
76 static void show_osd(struct udevice *osd)
77 {
78         printf("OSD %d:\t%s", dev_seq(osd), osd->name);
79         if (device_active(osd))
80                 printf("  (active)");
81         printf("\n");
82 }
83
84 static int do_osd_write(struct cmd_tbl *cmdtp, int flag, int argc,
85                         char *const argv[])
86 {
87         uint x, y;
88         uint count;
89         char *hexstr;
90         u8 *buffer;
91         size_t buflen;
92         int res;
93
94         if (argc < 4 || (strlen(argv[3]) % 2))
95                 return CMD_RET_USAGE;
96
97         if (!osd_cur) {
98                 puts("No osd selected\n");
99                 return CMD_RET_FAILURE;
100         }
101
102         x = hextoul(argv[1], NULL);
103         y = hextoul(argv[2], NULL);
104         hexstr = argv[3];
105         count = (argc > 4) ? hextoul(argv[4], NULL) : 1;
106
107         buflen = strlen(hexstr) / 2;
108
109         buffer = malloc(buflen);
110         if (!buffer) {
111                 puts("Memory allocation failure\n");
112                 return CMD_RET_FAILURE;
113         }
114
115         res = hex2bin(buffer, hexstr, buflen);
116         if (res) {
117                 free(buffer);
118                 puts("Hexadecimal input contained invalid characters\n");
119                 return CMD_RET_FAILURE;
120         }
121
122         res = video_osd_set_mem(osd_cur, x, y, buffer, buflen, count);
123         if (res) {
124                 free(buffer);
125                 printf("%s: Could not write to video mem\n",
126                        osd_cur->name);
127                 return CMD_RET_FAILURE;
128         }
129
130         free(buffer);
131
132         return CMD_RET_SUCCESS;
133 }
134
135 static int do_osd_print(struct cmd_tbl *cmdtp, int flag, int argc,
136                         char *const argv[])
137 {
138         uint x, y;
139         u8 color;
140         char *text;
141         int res;
142
143         if (argc < 5)
144                 return CMD_RET_USAGE;
145
146         if (!osd_cur) {
147                 puts("No osd selected\n");
148                 return CMD_RET_FAILURE;
149         }
150
151         x = hextoul(argv[1], NULL);
152         y = hextoul(argv[2], NULL);
153         color = hextoul(argv[3], NULL);
154         text = argv[4];
155
156         res = video_osd_print(osd_cur, x, y, color, text);
157         if (res) {
158                 printf("Could not print string to osd %s\n", osd_cur->name);
159                 return CMD_RET_FAILURE;
160         }
161
162         return CMD_RET_SUCCESS;
163 }
164
165 static int do_osd_size(struct cmd_tbl *cmdtp, int flag, int argc,
166                        char *const argv[])
167 {
168         uint x, y;
169         int res;
170
171         if (argc < 3)
172                 return CMD_RET_USAGE;
173
174         if (!osd_cur) {
175                 puts("No osd selected\n");
176                 return CMD_RET_FAILURE;
177         }
178
179         x = hextoul(argv[1], NULL);
180         y = hextoul(argv[2], NULL);
181
182         res = video_osd_set_size(osd_cur, x, y);
183         if (res) {
184                 printf("Could not set size on osd %s\n", osd_cur->name);
185                 return CMD_RET_FAILURE;
186         }
187
188         return CMD_RET_SUCCESS;
189 }
190
191 static int do_show_osd(struct cmd_tbl *cmdtp, int flag, int argc,
192                        char *const argv[])
193 {
194         struct udevice *osd;
195
196         if (argc == 1) {
197                 /* show all OSDs */
198                 struct uclass *uc;
199                 int res;
200
201                 res = uclass_get(UCLASS_VIDEO_OSD, &uc);
202                 if (res) {
203                         printf("Error while getting OSD uclass (err=%d)\n",
204                                res);
205                         return CMD_RET_FAILURE;
206                 }
207
208                 uclass_foreach_dev(osd, uc)
209                         show_osd(osd);
210         } else {
211                 int i, res;
212
213                 /* show specific OSD */
214                 i = dectoul(argv[1], NULL);
215
216                 res = uclass_get_device_by_seq(UCLASS_VIDEO_OSD, i, &osd);
217                 if (res) {
218                         printf("Invalid osd %d: err=%d\n", i, res);
219                         return CMD_RET_FAILURE;
220                 }
221                 show_osd(osd);
222         }
223
224         return CMD_RET_SUCCESS;
225 }
226
227 static int do_osd_num(struct cmd_tbl *cmdtp, int flag, int argc,
228                       char *const argv[])
229 {
230         int osd_no;
231         int res = 0;
232
233         if (argc == 1) {
234                 /* querying current setting */
235                 struct udevice *osd;
236
237                 if (!osd_get_osd_cur(&osd))
238                         osd_no = dev_seq(osd);
239                 else
240                         osd_no = -1;
241                 printf("Current osd is %d\n", osd_no);
242         } else {
243                 osd_no = dectoul(argv[1], NULL);
244                 printf("Setting osd to %d\n", osd_no);
245
246                 res = cmd_osd_set_osd_num(osd_no);
247                 if (res)
248                         printf("Failure changing osd number (err = %d)\n", res);
249         }
250
251         return res ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
252 }
253
254 static struct cmd_tbl cmd_osd_sub[] = {
255         U_BOOT_CMD_MKENT(show, 1, 1, do_show_osd, "", ""),
256         U_BOOT_CMD_MKENT(dev, 1, 1, do_osd_num, "", ""),
257         U_BOOT_CMD_MKENT(write, 4, 1, do_osd_write, "", ""),
258         U_BOOT_CMD_MKENT(print, 4, 1, do_osd_print, "", ""),
259         U_BOOT_CMD_MKENT(size, 2, 1, do_osd_size, "", ""),
260 };
261
262 static int do_osd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
263 {
264         struct cmd_tbl *c;
265
266         if (argc < 2)
267                 return CMD_RET_USAGE;
268
269         /* Strip off leading 'osd' command argument */
270         argc--;
271         argv++;
272
273         c = find_cmd_tbl(argv[0], &cmd_osd_sub[0], ARRAY_SIZE(cmd_osd_sub));
274
275         if (c)
276                 return c->cmd(cmdtp, flag, argc, argv);
277         else
278                 return CMD_RET_USAGE;
279 }
280
281 static char osd_help_text[] =
282         "show  - show OSD info\n"
283         "osd dev [dev] - show or set current OSD\n"
284         "write [pos_x] [pos_y] [buffer] [count] - write 8-bit hex encoded buffer to osd memory at a given position\n"
285         "print [pos_x] [pos_y] [color] [text] - write ASCII buffer (given by text data and driver-specific color information) to osd memory\n"
286         "size [size_x] [size_y] - set OSD XY size in characters\n";
287
288 U_BOOT_CMD(
289         osd, 6, 1, do_osd,
290         "OSD sub-system",
291         osd_help_text
292 );