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