// SPDX-License-Identifier: GPL-2.0
// tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
//
// Copyright (c) 2006-2007 Mauro Carvalho Chehab <mchehab@kernel.org>
//
// Copyright (c) 2007 Michel Ludwig <michel.ludwig@gmail.com>
//	- Fix SMBus Read Byte command

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/usb.h>
#include <linux/i2c.h>

#include "tm6000.h"
#include "tm6000-regs.h"
#include <media/v4l2-common.h>
#include <media/tuner.h>
#include "tuner-xc2028.h"


/* ----------------------------------------------------------- */

static unsigned int i2c_debug;
module_param(i2c_debug, int, 0644);
MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");

#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
			printk(KERN_DEBUG "%s at %s: " fmt, \
			dev->name, __func__, ##args); } while (0)

static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
				__u8 reg, char *buf, int len)
{
	int rc;
	unsigned int i2c_packet_limit = 16;

	if (dev->dev_type == TM6010)
		i2c_packet_limit = 80;

	if (!buf)
		return -1;

	if (len < 1 || len > i2c_packet_limit) {
		printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
			len, i2c_packet_limit);
		return -1;
	}

	/* capture mutex */
	rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
		USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
		addr | reg << 8, 0, buf, len);

	if (rc < 0) {
		/* release mutex */
		return rc;
	}

	/* release mutex */
	return rc;
}

/* Generic read - doesn't work fine with 16bit registers */
static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
				__u8 reg, char *buf, int len)
{
	int rc;
	u8 b[2];
	unsigned int i2c_packet_limit = 16;

	if (dev->dev_type == TM6010)
		i2c_packet_limit = 64;

	if (!buf)
		return -1;

	if (len < 1 || len > i2c_packet_limit) {
		printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
			len, i2c_packet_limit);
		return -1;
	}

	/* capture mutex */
	if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
		/*
		 * Workaround an I2C bug when reading from zl10353
		 */
		reg -= 1;
		len += 1;

		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);

		*buf = b[1];
	} else {
		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
	}

	/* release mutex */
	return rc;
}

/*
 * read from a 16bit register
 * for example xc2028, xc3028 or xc3028L
 */
static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
				  __u16 reg, char *buf, int len)
{
	int rc;
	unsigned char ureg;

	if (!buf || len != 2)
		return -1;

	/* capture mutex */
	if (dev->dev_type == TM6010) {
		ureg = reg & 0xFF;
		rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
			USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
			addr | (reg & 0xFF00), 0, &ureg, 1);

		if (rc < 0) {
			/* release mutex */
			return rc;
		}

		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
			USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
			reg, 0, buf, len);
	} else {
		rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
			USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
			addr, reg, buf, len);
	}

	/* release mutex */
	return rc;
}

static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
			   struct i2c_msg msgs[], int num)
{
	struct tm6000_core *dev = i2c_adap->algo_data;
	int addr, rc, i, byte;

	for (i = 0; i < num; i++) {
		addr = (msgs[i].addr << 1) & 0xff;
		i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
		if (msgs[i].flags & I2C_M_RD) {
			/* read request without preceding register selection */
			/*
			 * The TM6000 only supports a read transaction
			 * immediately after a 1 or 2 byte write to select
			 * a register.  We cannot fulfill this request.
			 */
			i2c_dprintk(2, " read without preceding write not supported");
			rc = -EOPNOTSUPP;
			goto err;
		} else if (i + 1 < num && msgs[i].len <= 2 &&
			   (msgs[i + 1].flags & I2C_M_RD) &&
			   msgs[i].addr == msgs[i + 1].addr) {
			/* 1 or 2 byte write followed by a read */
			if (i2c_debug >= 2)
				for (byte = 0; byte < msgs[i].len; byte++)
					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
			i2c_dprintk(2, "; joined to read %s len=%d:",
				    i == num - 2 ? "stop" : "nonstop",
				    msgs[i + 1].len);

			if (msgs[i].len == 2) {
				rc = tm6000_i2c_recv_regs16(dev, addr,
					msgs[i].buf[0] << 8 | msgs[i].buf[1],
					msgs[i + 1].buf, msgs[i + 1].len);
			} else {
				rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
					msgs[i + 1].buf, msgs[i + 1].len);
			}

			i++;

			if (addr == dev->tuner_addr << 1) {
				tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
				tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
			}
			if (i2c_debug >= 2)
				for (byte = 0; byte < msgs[i].len; byte++)
					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
		} else {
			/* write bytes */
			if (i2c_debug >= 2)
				for (byte = 0; byte < msgs[i].len; byte++)
					printk(KERN_CONT " %02x", msgs[i].buf[byte]);
			rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
				msgs[i].buf + 1, msgs[i].len - 1);
		}
		if (i2c_debug >= 2)
			printk(KERN_CONT "\n");
		if (rc < 0)
			goto err;
	}

	return num;
err:
	i2c_dprintk(2, " ERROR: %i\n", rc);
	return rc;
}

static int tm6000_i2c_eeprom(struct tm6000_core *dev)
{
	int i, rc;
	unsigned char *p = dev->eedata;
	unsigned char bytes[17];

	dev->i2c_client.addr = 0xa0 >> 1;
	dev->eedata_size = 0;

	bytes[16] = '\0';
	for (i = 0; i < sizeof(dev->eedata); ) {
		*p = i;
		rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
		if (rc < 1) {
			if (p == dev->eedata)
				goto noeeprom;
			else {
				printk(KERN_WARNING
				"%s: i2c eeprom read error (err=%d)\n",
				dev->name, rc);
			}
			return -EINVAL;
		}
		dev->eedata_size++;
		p++;
		if (0 == (i % 16))
			printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
		printk(KERN_CONT " %02x", dev->eedata[i]);
		if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z'))
			bytes[i%16] = dev->eedata[i];
		else
			bytes[i%16] = '.';

		i++;

		if (0 == (i % 16)) {
			bytes[16] = '\0';
			printk(KERN_CONT "  %s\n", bytes);
		}
	}
	if (0 != (i%16)) {
		bytes[i%16] = '\0';
		for (i %= 16; i < 16; i++)
			printk(KERN_CONT "   ");
		printk(KERN_CONT "  %s\n", bytes);
	}

	return 0;

noeeprom:
	printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
	       dev->name, rc);
	return -EINVAL;
}

/* ----------------------------------------------------------- */

/*
 * functionality()
 */
static u32 functionality(struct i2c_adapter *adap)
{
	return I2C_FUNC_SMBUS_EMUL;
}

static const struct i2c_algorithm tm6000_algo = {
	.master_xfer   = tm6000_i2c_xfer,
	.functionality = functionality,
};

/* ----------------------------------------------------------- */

/*
 * tm6000_i2c_register()
 * register i2c bus
 */
int tm6000_i2c_register(struct tm6000_core *dev)
{
	int rc;

	dev->i2c_adap.owner = THIS_MODULE;
	dev->i2c_adap.algo = &tm6000_algo;
	dev->i2c_adap.dev.parent = &dev->udev->dev;
	strscpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
	dev->i2c_adap.algo_data = dev;
	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
	rc = i2c_add_adapter(&dev->i2c_adap);
	if (rc)
		return rc;

	dev->i2c_client.adapter = &dev->i2c_adap;
	strscpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
	tm6000_i2c_eeprom(dev);

	return 0;
}

/*
 * tm6000_i2c_unregister()
 * unregister i2c_bus
 */
int tm6000_i2c_unregister(struct tm6000_core *dev)
{
	i2c_del_adapter(&dev->i2c_adap);
	return 0;
}
