// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2018
 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
 */
#include <common.h>
#include <display.h>
#include <dm.h>
#include <malloc.h>
#include <video_osd.h>

#include "sandbox_osd.h"

struct sandbox_osd_priv {
	uint width;
	uint height;
	u16 *buf;
};

static const struct udevice_id sandbox_osd_ids[] = {
	{ .compatible = "sandbox,sandbox_osd" },
	{ }
};

inline u16 make_memval(u8 chr, u8 color)
{
	return chr * 0x100 + color;
}

int sandbox_osd_get_info(struct udevice *dev, struct video_osd_info *info)
{
	struct sandbox_osd_priv *priv = dev_get_priv(dev);

	info->width = priv->width;
	info->height = priv->height;
	info->major_version = 1;
	info->minor_version = 0;

	return 0;
}

int sandbox_osd_set_mem(struct udevice *dev, uint col, uint row, u8 *buf,
			size_t buflen, uint count)
{
	struct sandbox_osd_priv *priv = dev_get_priv(dev);
	int pos;
	u8 *mem = (u8 *)priv->buf;
	int i;

	pos = 2 * (row * priv->width + col);

	if (pos >= 2 * (priv->width * priv->height))
		return -EINVAL;

	for (i = 0; i < count; i++)
		memcpy(mem + pos + (i * buflen), buf, buflen);

	return 0;
}

int _sandbox_osd_set_size(struct udevice *dev, uint col, uint row)
{
	struct sandbox_osd_priv *priv = dev_get_priv(dev);
	int i;
	uint size;

	priv->width = col;
	priv->height = row;
	size = priv->width * priv->height;
	if (!priv->buf)
		priv->buf = calloc(size, sizeof(u16));
	else
		priv->buf = realloc(priv->buf, size * sizeof(u16));

	if (!priv->buf)
		return -ENOMEM;

	/* Fill OSD with black spaces */
	for (i = 0; i < size; i++)
		priv->buf[i] = make_memval(' ', 'k');

	return 0;
}

int sandbox_osd_set_size(struct udevice *dev, uint col, uint row)
{
	return _sandbox_osd_set_size(dev, col, row);
}

int sandbox_osd_print(struct udevice *dev, uint col, uint row, ulong color,
		      char *text)
{
	struct sandbox_osd_priv *priv = dev_get_priv(dev);
	char cval;
	char *p;
	int pos;

	if (col >= priv->width || row >= priv->height)
		return -EINVAL;

	switch (color) {
	case COLOR_BLACK:
		cval = 'k';
		break;
	case COLOR_WHITE:
		cval = 'w';
		break;
	case COLOR_RED:
		cval = 'r';
		break;
	case COLOR_GREEN:
		cval = 'g';
		break;
	case COLOR_BLUE:
		cval = 'b';
		break;
	default:
		return -EINVAL;
	}

	p = text;
	pos = row * priv->width + col;

	while (*p)
		priv->buf[pos++] = make_memval(*(p++), cval);

	return 0;
}

int sandbox_osd_get_mem(struct udevice *dev, u8 *buf, size_t buflen)
{
	struct sandbox_osd_priv *priv = dev_get_priv(dev);
	uint memsize = 2 * (priv->width * priv->height);

	if (buflen < memsize)
		return -EINVAL;

	memcpy(buf, priv->buf, memsize);

	return 0;
}

static const struct video_osd_ops sandbox_osd_ops = {
	.get_info = sandbox_osd_get_info,
	.set_mem = sandbox_osd_set_mem,
	.set_size = sandbox_osd_set_size,
	.print = sandbox_osd_print,
};

int sandbox_osd_probe(struct udevice *dev)
{
	return _sandbox_osd_set_size(dev, 10, 10);
}

U_BOOT_DRIVER(sandbox_osd_drv) = {
	.name           = "sandbox_osd_drv",
	.id             = UCLASS_VIDEO_OSD,
	.ops		= &sandbox_osd_ops,
	.of_match       = sandbox_osd_ids,
	.probe          = sandbox_osd_probe,
	.priv_auto	= sizeof(struct sandbox_osd_priv),
};
