162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * STK1160 driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2012 Ezequiel Garcia
662306a36Sopenharmony_ci * <elezegarcia--a.t--gmail.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Based on Easycap driver by R.M. Thomas
962306a36Sopenharmony_ci *	Copyright (C) 2010 R.M. Thomas
1062306a36Sopenharmony_ci *	<rmthomas--a.t--sciolus.org>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/usb.h>
1562306a36Sopenharmony_ci#include <linux/i2c.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "stk1160.h"
1862306a36Sopenharmony_ci#include "stk1160-reg.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic unsigned int i2c_debug;
2162306a36Sopenharmony_cimodule_param(i2c_debug, int, 0644);
2262306a36Sopenharmony_ciMODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define dprintk_i2c(fmt, args...)				\
2562306a36Sopenharmony_cido {								\
2662306a36Sopenharmony_ci	if (i2c_debug)						\
2762306a36Sopenharmony_ci		printk(KERN_DEBUG fmt, ##args);			\
2862306a36Sopenharmony_ci} while (0)
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic int stk1160_i2c_busy_wait(struct stk1160 *dev, u8 wait_bit_mask)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	unsigned long end;
3362306a36Sopenharmony_ci	u8 flag;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	/* Wait until read/write finish bit is set */
3662306a36Sopenharmony_ci	end = jiffies + msecs_to_jiffies(STK1160_I2C_TIMEOUT);
3762306a36Sopenharmony_ci	while (time_is_after_jiffies(end)) {
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci		stk1160_read_reg(dev, STK1160_SICTL+1, &flag);
4062306a36Sopenharmony_ci		/* read/write done? */
4162306a36Sopenharmony_ci		if (flag & wait_bit_mask)
4262306a36Sopenharmony_ci			goto done;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci		usleep_range(10 * USEC_PER_MSEC, 20 * USEC_PER_MSEC);
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	return -ETIMEDOUT;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cidone:
5062306a36Sopenharmony_ci	return 0;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic int stk1160_i2c_write_reg(struct stk1160 *dev, u8 addr,
5462306a36Sopenharmony_ci		u8 reg, u8 value)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	int rc;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	/* Set serial device address */
5962306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
6062306a36Sopenharmony_ci	if (rc < 0)
6162306a36Sopenharmony_ci		return rc;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	/* Set i2c device register sub-address */
6462306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SBUSW_WA, reg);
6562306a36Sopenharmony_ci	if (rc < 0)
6662306a36Sopenharmony_ci		return rc;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	/* Set i2c device register value */
6962306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SBUSW_WD, value);
7062306a36Sopenharmony_ci	if (rc < 0)
7162306a36Sopenharmony_ci		return rc;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	/* Start write now */
7462306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SICTL, 0x01);
7562306a36Sopenharmony_ci	if (rc < 0)
7662306a36Sopenharmony_ci		return rc;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	rc = stk1160_i2c_busy_wait(dev, 0x04);
7962306a36Sopenharmony_ci	if (rc < 0)
8062306a36Sopenharmony_ci		return rc;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	return 0;
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr,
8662306a36Sopenharmony_ci		u8 reg, u8 *value)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	int rc;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	/* Set serial device address */
9162306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
9262306a36Sopenharmony_ci	if (rc < 0)
9362306a36Sopenharmony_ci		return rc;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	/* Set i2c device register sub-address */
9662306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, reg);
9762306a36Sopenharmony_ci	if (rc < 0)
9862306a36Sopenharmony_ci		return rc;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	/* Start read now */
10162306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
10262306a36Sopenharmony_ci	if (rc < 0)
10362306a36Sopenharmony_ci		return rc;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	rc = stk1160_i2c_busy_wait(dev, 0x01);
10662306a36Sopenharmony_ci	if (rc < 0)
10762306a36Sopenharmony_ci		return rc;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	rc = stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
11062306a36Sopenharmony_ci	if (rc < 0)
11162306a36Sopenharmony_ci		return rc;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	return 0;
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/*
11762306a36Sopenharmony_ci * stk1160_i2c_check_for_device()
11862306a36Sopenharmony_ci * check if there is a i2c_device at the supplied address
11962306a36Sopenharmony_ci */
12062306a36Sopenharmony_cistatic int stk1160_i2c_check_for_device(struct stk1160 *dev,
12162306a36Sopenharmony_ci		unsigned char addr)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	int rc;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* Set serial device address */
12662306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
12762306a36Sopenharmony_ci	if (rc < 0)
12862306a36Sopenharmony_ci		return rc;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	/* Set device sub-address, we'll chip version reg */
13162306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, 0x00);
13262306a36Sopenharmony_ci	if (rc < 0)
13362306a36Sopenharmony_ci		return rc;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* Start read now */
13662306a36Sopenharmony_ci	rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
13762306a36Sopenharmony_ci	if (rc < 0)
13862306a36Sopenharmony_ci		return rc;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	rc = stk1160_i2c_busy_wait(dev, 0x01);
14162306a36Sopenharmony_ci	if (rc < 0)
14262306a36Sopenharmony_ci		return -ENODEV;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	return 0;
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci/*
14862306a36Sopenharmony_ci * stk1160_i2c_xfer()
14962306a36Sopenharmony_ci * the main i2c transfer function
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistatic int stk1160_i2c_xfer(struct i2c_adapter *i2c_adap,
15262306a36Sopenharmony_ci			   struct i2c_msg msgs[], int num)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	struct stk1160 *dev = i2c_adap->algo_data;
15562306a36Sopenharmony_ci	int addr, rc, i;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
15862306a36Sopenharmony_ci		addr = msgs[i].addr << 1;
15962306a36Sopenharmony_ci		dprintk_i2c("%s: addr=%x", __func__, addr);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci		if (!msgs[i].len) {
16262306a36Sopenharmony_ci			/* no len: check only for device presence */
16362306a36Sopenharmony_ci			rc = stk1160_i2c_check_for_device(dev, addr);
16462306a36Sopenharmony_ci			if (rc < 0) {
16562306a36Sopenharmony_ci				dprintk_i2c(" no device\n");
16662306a36Sopenharmony_ci				return rc;
16762306a36Sopenharmony_ci			}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci		} else if (msgs[i].flags & I2C_M_RD) {
17062306a36Sopenharmony_ci			/* read request without preceding register selection */
17162306a36Sopenharmony_ci			dprintk_i2c(" subaddr not selected");
17262306a36Sopenharmony_ci			rc = -EOPNOTSUPP;
17362306a36Sopenharmony_ci			goto err;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci		} else if (i + 1 < num && msgs[i].len <= 2 &&
17662306a36Sopenharmony_ci			   (msgs[i + 1].flags & I2C_M_RD) &&
17762306a36Sopenharmony_ci			   msgs[i].addr == msgs[i + 1].addr) {
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci			if (msgs[i].len != 1 || msgs[i + 1].len != 1) {
18062306a36Sopenharmony_ci				dprintk_i2c(" len not supported");
18162306a36Sopenharmony_ci				rc = -EOPNOTSUPP;
18262306a36Sopenharmony_ci				goto err;
18362306a36Sopenharmony_ci			}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci			dprintk_i2c(" subaddr=%x", msgs[i].buf[0]);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci			rc = stk1160_i2c_read_reg(dev, addr, msgs[i].buf[0],
18862306a36Sopenharmony_ci				msgs[i + 1].buf);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci			dprintk_i2c(" read=%x", *msgs[i + 1].buf);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci			/* consumed two msgs, so we skip one of them */
19362306a36Sopenharmony_ci			i++;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci		} else {
19662306a36Sopenharmony_ci			if (msgs[i].len != 2) {
19762306a36Sopenharmony_ci				dprintk_i2c(" len not supported");
19862306a36Sopenharmony_ci				rc = -EOPNOTSUPP;
19962306a36Sopenharmony_ci				goto err;
20062306a36Sopenharmony_ci			}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci			dprintk_i2c(" subaddr=%x write=%x",
20362306a36Sopenharmony_ci				msgs[i].buf[0],  msgs[i].buf[1]);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci			rc = stk1160_i2c_write_reg(dev, addr, msgs[i].buf[0],
20662306a36Sopenharmony_ci				msgs[i].buf[1]);
20762306a36Sopenharmony_ci		}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci		if (rc < 0)
21062306a36Sopenharmony_ci			goto err;
21162306a36Sopenharmony_ci		dprintk_i2c(" OK\n");
21262306a36Sopenharmony_ci	}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	return num;
21562306a36Sopenharmony_cierr:
21662306a36Sopenharmony_ci	dprintk_i2c(" ERROR: %d\n", rc);
21762306a36Sopenharmony_ci	return num;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci/*
22162306a36Sopenharmony_ci * functionality(), what da heck is this?
22262306a36Sopenharmony_ci */
22362306a36Sopenharmony_cistatic u32 functionality(struct i2c_adapter *adap)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	return I2C_FUNC_SMBUS_EMUL;
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic const struct i2c_algorithm algo = {
22962306a36Sopenharmony_ci	.master_xfer   = stk1160_i2c_xfer,
23062306a36Sopenharmony_ci	.functionality = functionality,
23162306a36Sopenharmony_ci};
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cistatic const struct i2c_adapter adap_template = {
23462306a36Sopenharmony_ci	.owner = THIS_MODULE,
23562306a36Sopenharmony_ci	.name = "stk1160",
23662306a36Sopenharmony_ci	.algo = &algo,
23762306a36Sopenharmony_ci};
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic const struct i2c_client client_template = {
24062306a36Sopenharmony_ci	.name = "stk1160 internal",
24162306a36Sopenharmony_ci};
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci/*
24462306a36Sopenharmony_ci * stk1160_i2c_register()
24562306a36Sopenharmony_ci * register i2c bus
24662306a36Sopenharmony_ci */
24762306a36Sopenharmony_ciint stk1160_i2c_register(struct stk1160 *dev)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	int rc;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	dev->i2c_adap = adap_template;
25262306a36Sopenharmony_ci	dev->i2c_adap.dev.parent = dev->dev;
25362306a36Sopenharmony_ci	strscpy(dev->i2c_adap.name, "stk1160", sizeof(dev->i2c_adap.name));
25462306a36Sopenharmony_ci	dev->i2c_adap.algo_data = dev;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	rc = i2c_add_adapter(&dev->i2c_adap);
25962306a36Sopenharmony_ci	if (rc < 0) {
26062306a36Sopenharmony_ci		stk1160_err("cannot add i2c adapter (%d)\n", rc);
26162306a36Sopenharmony_ci		return rc;
26262306a36Sopenharmony_ci	}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	dev->i2c_client = client_template;
26562306a36Sopenharmony_ci	dev->i2c_client.adapter = &dev->i2c_adap;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	/* Set i2c clock divider device address */
26862306a36Sopenharmony_ci	stk1160_write_reg(dev, STK1160_SICTL_CD,  0x0f);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/* ??? */
27162306a36Sopenharmony_ci	stk1160_write_reg(dev, STK1160_ASIC + 3,  0x00);
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	return 0;
27462306a36Sopenharmony_ci}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci/*
27762306a36Sopenharmony_ci * stk1160_i2c_unregister()
27862306a36Sopenharmony_ci * unregister i2c_bus
27962306a36Sopenharmony_ci */
28062306a36Sopenharmony_ciint stk1160_i2c_unregister(struct stk1160 *dev)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	i2c_del_adapter(&dev->i2c_adap);
28362306a36Sopenharmony_ci	return 0;
28462306a36Sopenharmony_ci}
285