// SPDX-License-Identifier: GPL-2.0
#include <linux/export.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include "fbtft.h"

/*****************************************************************************
 *
 *   void (*write_reg)(struct fbtft_par *par, int len, ...);
 *
 *****************************************************************************/

#define define_fbtft_write_reg(func, buffer_type, data_type, modifier)        \
void func(struct fbtft_par *par, int len, ...)                                \
{                                                                             \
	va_list args;                                                         \
	int i, ret;                                                           \
	int offset = 0;                                                       \
	buffer_type *buf = (buffer_type *)par->buf;                           \
									      \
	if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) {                    \
		va_start(args, len);                                          \
		for (i = 0; i < len; i++) {                                   \
			buf[i] = modifier((data_type)va_arg(args,             \
							    unsigned int));   \
		}                                                             \
		va_end(args);                                                 \
		fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par,                  \
				  par->info->device, buffer_type, buf, len,   \
				  "%s: ", __func__);                          \
	}                                                                     \
									      \
	va_start(args, len);                                                  \
									      \
	if (par->startbyte) {                                                 \
		*(u8 *)par->buf = par->startbyte;                             \
		buf = (buffer_type *)(par->buf + 1);                          \
		offset = 1;                                                   \
	}                                                                     \
									      \
	*buf = modifier((data_type)va_arg(args, unsigned int));               \
	ret = fbtft_write_buf_dc(par, par->buf, sizeof(data_type) + offset,   \
				 0);                                          \
	if (ret < 0)							      \
		goto out;						      \
	len--;                                                                \
									      \
	if (par->startbyte)                                                   \
		*(u8 *)par->buf = par->startbyte | 0x2;                       \
									      \
	if (len) {                                                            \
		i = len;                                                      \
		while (i--)						      \
			*buf++ = modifier((data_type)va_arg(args,             \
							    unsigned int));   \
		fbtft_write_buf_dc(par, par->buf,			      \
				   len * (sizeof(data_type) + offset), 1);    \
	}                                                                     \
out:									      \
	va_end(args);                                                         \
}                                                                             \
EXPORT_SYMBOL(func);

define_fbtft_write_reg(fbtft_write_reg8_bus8, u8, u8, )
define_fbtft_write_reg(fbtft_write_reg16_bus8, __be16, u16, cpu_to_be16)
define_fbtft_write_reg(fbtft_write_reg16_bus16, u16, u16, )

void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...)
{
	va_list args;
	int i, ret;
	int pad = 0;
	u16 *buf = (u16 *)par->buf;

	if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) {
		va_start(args, len);
		for (i = 0; i < len; i++)
			*(((u8 *)buf) + i) = (u8)va_arg(args, unsigned int);
		va_end(args);
		fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par,
				  par->info->device, u8, buf, len, "%s: ",
				  __func__);
	}
	if (len <= 0)
		return;

	if (par->spi && (par->spi->bits_per_word == 8)) {
		/* we're emulating 9-bit, pad start of buffer with no-ops
		 * (assuming here that zero is a no-op)
		 */
		pad = (len % 4) ? 4 - (len % 4) : 0;
		for (i = 0; i < pad; i++)
			*buf++ = 0x000;
	}

	va_start(args, len);
	*buf++ = (u8)va_arg(args, unsigned int);
	i = len - 1;
	while (i--) {
		*buf = (u8)va_arg(args, unsigned int);
		*buf++ |= 0x100; /* dc=1 */
	}
	va_end(args);
	ret = par->fbtftops.write(par, par->buf, (len + pad) * sizeof(u16));
	if (ret < 0) {
		dev_err(par->info->device,
			"write() failed and returned %d\n", ret);
		return;
	}
}
EXPORT_SYMBOL(fbtft_write_reg8_bus9);

/*****************************************************************************
 *
 *   int (*write_vmem)(struct fbtft_par *par);
 *
 *****************************************************************************/

/* 16 bit pixel over 8-bit databus */
int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
{
	u16 *vmem16;
	__be16 *txbuf16 = par->txbuf.buf;
	size_t remain;
	size_t to_copy;
	size_t tx_array_size;
	int i;
	int ret = 0;
	size_t startbyte_size = 0;

	fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n",
		      __func__, offset, len);

	remain = len / 2;
	vmem16 = (u16 *)(par->info->screen_buffer + offset);

	if (par->gpio.dc != -1)
		gpio_set_value(par->gpio.dc, 1);

	/* non buffered write */
	if (!par->txbuf.buf)
		return par->fbtftops.write(par, vmem16, len);

	/* buffered write */
	tx_array_size = par->txbuf.len / 2;

	if (par->startbyte) {
		txbuf16 = par->txbuf.buf + 1;
		tx_array_size -= 2;
		*(u8 *)(par->txbuf.buf) = par->startbyte | 0x2;
		startbyte_size = 1;
	}

	while (remain) {
		to_copy = min(tx_array_size, remain);
		dev_dbg(par->info->device, "to_copy=%zu, remain=%zu\n",
			to_copy, remain - to_copy);

		for (i = 0; i < to_copy; i++)
			txbuf16[i] = cpu_to_be16(vmem16[i]);

		vmem16 = vmem16 + to_copy;
		ret = par->fbtftops.write(par, par->txbuf.buf,
						startbyte_size + to_copy * 2);
		if (ret < 0)
			return ret;
		remain -= to_copy;
	}

	return ret;
}
EXPORT_SYMBOL(fbtft_write_vmem16_bus8);

/* 16 bit pixel over 9-bit SPI bus: dc + high byte, dc + low byte */
int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len)
{
	u8 *vmem8;
	u16 *txbuf16 = par->txbuf.buf;
	size_t remain;
	size_t to_copy;
	size_t tx_array_size;
	int i;
	int ret = 0;

	fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n",
		      __func__, offset, len);

	if (!par->txbuf.buf) {
		dev_err(par->info->device, "%s: txbuf.buf is NULL\n", __func__);
		return -1;
	}

	remain = len;
	vmem8 = par->info->screen_buffer + offset;

	tx_array_size = par->txbuf.len / 2;

	while (remain) {
		to_copy = min(tx_array_size, remain);
		dev_dbg(par->info->device, "to_copy=%zu, remain=%zu\n",
			to_copy, remain - to_copy);

#ifdef __LITTLE_ENDIAN
		for (i = 0; i < to_copy; i += 2) {
			txbuf16[i]     = 0x0100 | vmem8[i + 1];
			txbuf16[i + 1] = 0x0100 | vmem8[i];
		}
#else
		for (i = 0; i < to_copy; i++)
			txbuf16[i]   = 0x0100 | vmem8[i];
#endif
		vmem8 = vmem8 + to_copy;
		ret = par->fbtftops.write(par, par->txbuf.buf, to_copy * 2);
		if (ret < 0)
			return ret;
		remain -= to_copy;
	}

	return ret;
}
EXPORT_SYMBOL(fbtft_write_vmem16_bus9);

int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len)
{
	dev_err(par->info->device, "%s: function not implemented\n", __func__);
	return -1;
}
EXPORT_SYMBOL(fbtft_write_vmem8_bus8);

/* 16 bit pixel over 16-bit databus */
int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len)
{
	u16 *vmem16;

	fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n",
		      __func__, offset, len);

	vmem16 = (u16 *)(par->info->screen_buffer + offset);

	/* no need for buffered write with 16-bit bus */
	return fbtft_write_buf_dc(par, vmem16, len, 1);
}
EXPORT_SYMBOL(fbtft_write_vmem16_bus16);
