]>
Commit | Line | Data |
---|---|---|
3bf65cb5 MS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * (C) Copyright 2017 | |
4 | * Mario Six, Guntermann & Drunck GmbH, [email protected] | |
5 | * | |
6 | * based on the gdsys osd driver, which is | |
7 | * | |
8 | * (C) Copyright 2010 | |
9 | * Dirk Eibach, Guntermann & Drunck GmbH, [email protected] | |
10 | */ | |
11 | ||
12 | #include <common.h> | |
09140113 | 13 | #include <command.h> |
3bf65cb5 MS |
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", osd->req_seq, osd->name); | |
79 | if (device_active(osd)) | |
80 | printf(" (active %d)", osd->seq); | |
81 | printf("\n"); | |
82 | } | |
83 | ||
09140113 SG |
84 | static int do_osd_write(struct cmd_tbl *cmdtp, int flag, int argc, |
85 | char *const argv[]) | |
3bf65cb5 MS |
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 = simple_strtoul(argv[1], NULL, 16); | |
103 | y = simple_strtoul(argv[2], NULL, 16); | |
104 | hexstr = argv[3]; | |
105 | count = (argc > 4) ? simple_strtoul(argv[4], NULL, 16) : 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 | ||
09140113 SG |
135 | static int do_osd_print(struct cmd_tbl *cmdtp, int flag, int argc, |
136 | char *const argv[]) | |
3bf65cb5 MS |
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 = simple_strtoul(argv[1], NULL, 16); | |
152 | y = simple_strtoul(argv[2], NULL, 16); | |
153 | color = simple_strtoul(argv[3], NULL, 16); | |
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 | ||
09140113 SG |
165 | static int do_osd_size(struct cmd_tbl *cmdtp, int flag, int argc, |
166 | char *const argv[]) | |
3bf65cb5 MS |
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 = simple_strtoul(argv[1], NULL, 16); | |
180 | y = simple_strtoul(argv[2], NULL, 16); | |
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 | ||
09140113 SG |
191 | static int do_show_osd(struct cmd_tbl *cmdtp, int flag, int argc, |
192 | char *const argv[]) | |
3bf65cb5 MS |
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 = simple_strtoul(argv[1], NULL, 10); | |
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 | ||
09140113 SG |
227 | static int do_osd_num(struct cmd_tbl *cmdtp, int flag, int argc, |
228 | char *const argv[]) | |
3bf65cb5 MS |
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 = osd->seq; | |
239 | else | |
240 | osd_no = -1; | |
241 | printf("Current osd is %d\n", osd_no); | |
242 | } else { | |
243 | osd_no = simple_strtoul(argv[1], NULL, 10); | |
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 | ||
09140113 | 254 | static struct cmd_tbl cmd_osd_sub[] = { |
3bf65cb5 MS |
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 | ||
09140113 | 262 | static int do_osd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) |
3bf65cb5 | 263 | { |
09140113 | 264 | struct cmd_tbl *c; |
3bf65cb5 MS |
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 | ); |