// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2017
 * Mario Six,  Guntermann & Drunck GmbH, mario.six@gdsys.cc
 *
 * based on the gdsys osd driver, which is
 *
 * (C) Copyright 2010
 * Dirk Eibach,  Guntermann & Drunck GmbH, eibach@gdsys.de
 */

#include <common.h>
#include <command.h>
#include <dm.h>
#include <hexdump.h>
#include <video_osd.h>
#include <malloc.h>

/* Container for selected OSD device */
static struct udevice *osd_cur;

/**
 * cmd_osd_set_osd_num() - Set the OSD selected for operation
 *
 * Set the OSD device, which will be used by all subsequent OSD commands.
 *
 * Devices are identified by their uclass sequence number (as listed by 'osd
 * show').
 *
 * @osdnum: The OSD device to be selected, identified by its sequence number.
 * Return: 0 if OK, -ve on error
 */
static int cmd_osd_set_osd_num(unsigned int osdnum)
{
	struct udevice *osd;
	int res;

	res = uclass_get_device_by_seq(UCLASS_VIDEO_OSD, osdnum, &osd);
	if (res) {
		printf("%s: No OSD %u (err = %d)\n", __func__, osdnum, res);
		return res;
	}
	osd_cur = osd;

	return 0;
}

/**
 * osd_get_osd_cur() - Get the selected OSD device
 *
 * Get the OSD device that is used by all OSD commands.
 *
 * @osdp: Pointer to structure that will receive the currently selected OSD
 *	  device.
 * Return: 0 if OK, -ve on error
 */
static int osd_get_osd_cur(struct udevice **osdp)
{
	if (!osd_cur) {
		puts("No osd selected\n");
		return -ENODEV;
	}
	*osdp = osd_cur;

	return 0;
}

/**
 * show_osd() - Display information about a OSD device
 *
 * Display a device's ID (sequence number), and whether it is active (i.e.
 * probed) or not.
 *
 * @osd: OSD device to print information for
 */
static void show_osd(struct udevice *osd)
{
	printf("OSD %d:\t%s", dev_seq(osd), osd->name);
	if (device_active(osd))
		printf("  (active)");
	printf("\n");
}

static int do_osd_write(struct cmd_tbl *cmdtp, int flag, int argc,
			char *const argv[])
{
	uint x, y;
	uint count;
	char *hexstr;
	u8 *buffer;
	size_t buflen;
	int res;

	if (argc < 4 || (strlen(argv[3]) % 2))
		return CMD_RET_USAGE;

	if (!osd_cur) {
		puts("No osd selected\n");
		return CMD_RET_FAILURE;
	}

	x = hextoul(argv[1], NULL);
	y = hextoul(argv[2], NULL);
	hexstr = argv[3];
	count = (argc > 4) ? hextoul(argv[4], NULL) : 1;

	buflen = strlen(hexstr) / 2;

	buffer = malloc(buflen);
	if (!buffer) {
		puts("Memory allocation failure\n");
		return CMD_RET_FAILURE;
	}

	res = hex2bin(buffer, hexstr, buflen);
	if (res) {
		free(buffer);
		puts("Hexadecimal input contained invalid characters\n");
		return CMD_RET_FAILURE;
	}

	res = video_osd_set_mem(osd_cur, x, y, buffer, buflen, count);
	if (res) {
		free(buffer);
		printf("%s: Could not write to video mem\n",
		       osd_cur->name);
		return CMD_RET_FAILURE;
	}

	free(buffer);

	return CMD_RET_SUCCESS;
}

static int do_osd_print(struct cmd_tbl *cmdtp, int flag, int argc,
			char *const argv[])
{
	uint x, y;
	u8 color;
	char *text;
	int res;

	if (argc < 5)
		return CMD_RET_USAGE;

	if (!osd_cur) {
		puts("No osd selected\n");
		return CMD_RET_FAILURE;
	}

	x = hextoul(argv[1], NULL);
	y = hextoul(argv[2], NULL);
	color = hextoul(argv[3], NULL);
	text = argv[4];

	res = video_osd_print(osd_cur, x, y, color, text);
	if (res) {
		printf("Could not print string to osd %s\n", osd_cur->name);
		return CMD_RET_FAILURE;
	}

	return CMD_RET_SUCCESS;
}

static int do_osd_size(struct cmd_tbl *cmdtp, int flag, int argc,
		       char *const argv[])
{
	uint x, y;
	int res;

	if (argc < 3)
		return CMD_RET_USAGE;

	if (!osd_cur) {
		puts("No osd selected\n");
		return CMD_RET_FAILURE;
	}

	x = hextoul(argv[1], NULL);
	y = hextoul(argv[2], NULL);

	res = video_osd_set_size(osd_cur, x, y);
	if (res) {
		printf("Could not set size on osd %s\n", osd_cur->name);
		return CMD_RET_FAILURE;
	}

	return CMD_RET_SUCCESS;
}

static int do_show_osd(struct cmd_tbl *cmdtp, int flag, int argc,
		       char *const argv[])
{
	struct udevice *osd;

	if (argc == 1) {
		/* show all OSDs */
		struct uclass *uc;
		int res;

		res = uclass_get(UCLASS_VIDEO_OSD, &uc);
		if (res) {
			printf("Error while getting OSD uclass (err=%d)\n",
			       res);
			return CMD_RET_FAILURE;
		}

		uclass_foreach_dev(osd, uc)
			show_osd(osd);
	} else {
		int i, res;

		/* show specific OSD */
		i = dectoul(argv[1], NULL);

		res = uclass_get_device_by_seq(UCLASS_VIDEO_OSD, i, &osd);
		if (res) {
			printf("Invalid osd %d: err=%d\n", i, res);
			return CMD_RET_FAILURE;
		}
		show_osd(osd);
	}

	return CMD_RET_SUCCESS;
}

static int do_osd_num(struct cmd_tbl *cmdtp, int flag, int argc,
		      char *const argv[])
{
	int osd_no;
	int res = 0;

	if (argc == 1) {
		/* querying current setting */
		struct udevice *osd;

		if (!osd_get_osd_cur(&osd))
			osd_no = dev_seq(osd);
		else
			osd_no = -1;
		printf("Current osd is %d\n", osd_no);
	} else {
		osd_no = dectoul(argv[1], NULL);
		printf("Setting osd to %d\n", osd_no);

		res = cmd_osd_set_osd_num(osd_no);
		if (res)
			printf("Failure changing osd number (err = %d)\n", res);
	}

	return res ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
}

static struct cmd_tbl cmd_osd_sub[] = {
	U_BOOT_CMD_MKENT(show, 1, 1, do_show_osd, "", ""),
	U_BOOT_CMD_MKENT(dev, 1, 1, do_osd_num, "", ""),
	U_BOOT_CMD_MKENT(write, 4, 1, do_osd_write, "", ""),
	U_BOOT_CMD_MKENT(print, 4, 1, do_osd_print, "", ""),
	U_BOOT_CMD_MKENT(size, 2, 1, do_osd_size, "", ""),
};

static int do_osd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
	struct cmd_tbl *c;

	if (argc < 2)
		return CMD_RET_USAGE;

	/* Strip off leading 'osd' command argument */
	argc--;
	argv++;

	c = find_cmd_tbl(argv[0], &cmd_osd_sub[0], ARRAY_SIZE(cmd_osd_sub));

	if (c)
		return c->cmd(cmdtp, flag, argc, argv);
	else
		return CMD_RET_USAGE;
}

U_BOOT_LONGHELP(osd,
	"show  - show OSD info\n"
	"osd dev [dev] - show or set current OSD\n"
	"write [pos_x] [pos_y] [buffer] [count] - write 8-bit hex encoded buffer to osd memory at a given position\n"
	"print [pos_x] [pos_y] [color] [text] - write ASCII buffer (given by text data and driver-specific color information) to osd memory\n"
	"size [size_x] [size_y] - set OSD XY size in characters\n");

U_BOOT_CMD(
	osd, 6, 1, do_osd,
	"OSD sub-system",
	osd_help_text
);
