brintos

brintos / linux-shallow public Read only

0
0
Text · 8.8 KiB · 749f90d Raw
394 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Driver for the Auvitek AU0828 USB bridge4 *5 *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>6 */7 8#include "au0828.h"9 10#include <linux/module.h>11#include <linux/moduleparam.h>12#include <linux/init.h>13#include <linux/delay.h>14#include <linux/io.h>15 16#include "media/tuner.h"17#include <media/v4l2-common.h>18 19static int i2c_scan;20module_param(i2c_scan, int, 0444);21MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");22 23#define I2C_WAIT_DELAY 2524#define I2C_WAIT_RETRY 100025 26static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)27{28	struct au0828_dev *dev = i2c_adap->algo_data;29	return au0828_read(dev, AU0828_I2C_STATUS_201) &30		AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1;31}32 33static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)34{35	int count;36 37	for (count = 0; count < I2C_WAIT_RETRY; count++) {38		if (!i2c_slave_did_read_ack(i2c_adap))39			break;40		udelay(I2C_WAIT_DELAY);41	}42 43	if (I2C_WAIT_RETRY == count)44		return 0;45 46	return 1;47}48 49static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)50{51	struct au0828_dev *dev = i2c_adap->algo_data;52	return au0828_read(dev, AU0828_I2C_STATUS_201) &53		AU0828_I2C_STATUS_READ_DONE ? 0 : 1;54}55 56static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)57{58	int count;59 60	for (count = 0; count < I2C_WAIT_RETRY; count++) {61		if (!i2c_is_read_busy(i2c_adap))62			break;63		udelay(I2C_WAIT_DELAY);64	}65 66	if (I2C_WAIT_RETRY == count)67		return 0;68 69	return 1;70}71 72static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)73{74	struct au0828_dev *dev = i2c_adap->algo_data;75	return au0828_read(dev, AU0828_I2C_STATUS_201) &76		AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0;77}78 79static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)80{81	int count;82 83	for (count = 0; count < I2C_WAIT_RETRY; count++) {84		if (i2c_is_write_done(i2c_adap))85			break;86		udelay(I2C_WAIT_DELAY);87	}88 89	if (I2C_WAIT_RETRY == count)90		return 0;91 92	return 1;93}94 95static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)96{97	struct au0828_dev *dev = i2c_adap->algo_data;98	return au0828_read(dev, AU0828_I2C_STATUS_201) &99		AU0828_I2C_STATUS_BUSY ? 1 : 0;100}101 102static int i2c_wait_done(struct i2c_adapter *i2c_adap)103{104	int count;105 106	for (count = 0; count < I2C_WAIT_RETRY; count++) {107		if (!i2c_is_busy(i2c_adap))108			break;109		udelay(I2C_WAIT_DELAY);110	}111 112	if (I2C_WAIT_RETRY == count)113		return 0;114 115	return 1;116}117 118/* FIXME: Implement join handling correctly */119static int i2c_sendbytes(struct i2c_adapter *i2c_adap,120	const struct i2c_msg *msg, int joined_rlen)121{122	int i, strobe = 0;123	struct au0828_dev *dev = i2c_adap->algo_data;124	u8 i2c_speed = dev->board.i2c_clk_divider;125 126	dprintk(4, "%s()\n", __func__);127 128	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);129 130	if (((dev->board.tuner_type == TUNER_XC5000) ||131	     (dev->board.tuner_type == TUNER_XC5000C)) &&132	    (dev->board.tuner_addr == msg->addr)) {133		/*134		 * Due to I2C clock stretch, we need to use a lower speed135		 * on xc5000 for commands. However, firmware transfer can136		 * speed up to 400 KHz.137		 */138		if (msg->len == 64)139			i2c_speed = AU0828_I2C_CLK_250KHZ;140		else141			i2c_speed = AU0828_I2C_CLK_20KHZ;142	}143	/* Set the I2C clock */144	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);145 146	/* Hardware needs 8 bit addresses */147	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);148 149	dprintk(4, "SEND: %02x\n", msg->addr);150 151	/* Deal with i2c_scan */152	if (msg->len == 0) {153		/* The analog tuner detection code makes use of the SMBUS_QUICK154		   message (which involves a zero length i2c write).  To avoid155		   checking the status register when we didn't strobe out any156		   actual bytes to the bus, just do a read check.  This is157		   consistent with how I saw i2c device checking done in the158		   USB trace of the Windows driver */159		au0828_write(dev, AU0828_I2C_TRIGGER_200,160			     AU0828_I2C_TRIGGER_READ);161 162		if (!i2c_wait_done(i2c_adap))163			return -EIO;164 165		if (i2c_wait_read_ack(i2c_adap))166			return -EIO;167 168		return 0;169	}170 171	for (i = 0; i < msg->len;) {172 173		dprintk(4, " %02x\n", msg->buf[i]);174 175		au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]);176 177		strobe++;178		i++;179 180		if ((strobe >= 4) || (i >= msg->len)) {181 182			/* Strobe the byte into the bus */183			if (i < msg->len)184				au0828_write(dev, AU0828_I2C_TRIGGER_200,185					     AU0828_I2C_TRIGGER_WRITE |186					     AU0828_I2C_TRIGGER_HOLD);187			else188				au0828_write(dev, AU0828_I2C_TRIGGER_200,189					     AU0828_I2C_TRIGGER_WRITE);190 191			/* Reset strobe trigger */192			strobe = 0;193 194			if (!i2c_wait_write_done(i2c_adap))195				return -EIO;196 197		}198 199	}200	if (!i2c_wait_done(i2c_adap))201		return -EIO;202 203	dprintk(4, "\n");204 205	return msg->len;206}207 208/* FIXME: Implement join handling correctly */209static int i2c_readbytes(struct i2c_adapter *i2c_adap,210	const struct i2c_msg *msg, int joined)211{212	struct au0828_dev *dev = i2c_adap->algo_data;213	u8 i2c_speed = dev->board.i2c_clk_divider;214	int i;215 216	dprintk(4, "%s()\n", __func__);217 218	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);219 220	/*221	 * Due to xc5000c clock stretch, we cannot use full speed at222	 * readings from xc5000, as otherwise they'll fail.223	 */224	if (((dev->board.tuner_type == TUNER_XC5000) ||225	     (dev->board.tuner_type == TUNER_XC5000C)) &&226	    (dev->board.tuner_addr == msg->addr))227		i2c_speed = AU0828_I2C_CLK_20KHZ;228 229	/* Set the I2C clock */230	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);231 232	/* Hardware needs 8 bit addresses */233	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);234 235	dprintk(4, " RECV:\n");236 237	/* Deal with i2c_scan */238	if (msg->len == 0) {239		au0828_write(dev, AU0828_I2C_TRIGGER_200,240			     AU0828_I2C_TRIGGER_READ);241 242		if (i2c_wait_read_ack(i2c_adap))243			return -EIO;244		return 0;245	}246 247	for (i = 0; i < msg->len;) {248 249		i++;250 251		if (i < msg->len)252			au0828_write(dev, AU0828_I2C_TRIGGER_200,253				     AU0828_I2C_TRIGGER_READ |254				     AU0828_I2C_TRIGGER_HOLD);255		else256			au0828_write(dev, AU0828_I2C_TRIGGER_200,257				     AU0828_I2C_TRIGGER_READ);258 259		if (!i2c_wait_read_done(i2c_adap))260			return -EIO;261 262		msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) &263			0xff;264 265		dprintk(4, " %02x\n", msg->buf[i-1]);266	}267	if (!i2c_wait_done(i2c_adap))268		return -EIO;269 270	dprintk(4, "\n");271 272	return msg->len;273}274 275static int i2c_xfer(struct i2c_adapter *i2c_adap,276		    struct i2c_msg *msgs, int num)277{278	int i, retval = 0;279 280	dprintk(4, "%s(num = %d)\n", __func__, num);281 282	for (i = 0; i < num; i++) {283		dprintk(4, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",284			__func__, num, msgs[i].addr, msgs[i].len);285		if (msgs[i].flags & I2C_M_RD) {286			/* read */287			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);288		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&289			   msgs[i].addr == msgs[i + 1].addr) {290			/* write then read from same address */291			retval = i2c_sendbytes(i2c_adap, &msgs[i],292					       msgs[i + 1].len);293			if (retval < 0)294				goto err;295			i++;296			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);297		} else {298			/* write */299			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);300		}301		if (retval < 0)302			goto err;303	}304	return num;305 306err:307	return retval;308}309 310static u32 au0828_functionality(struct i2c_adapter *adap)311{312	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;313}314 315static const struct i2c_algorithm au0828_i2c_algo_template = {316	.master_xfer	= i2c_xfer,317	.functionality	= au0828_functionality,318};319 320/* ----------------------------------------------------------------------- */321 322static const struct i2c_adapter au0828_i2c_adap_template = {323	.name              = KBUILD_MODNAME,324	.owner             = THIS_MODULE,325	.algo              = &au0828_i2c_algo_template,326};327 328static const struct i2c_client au0828_i2c_client_template = {329	.name	= "au0828 internal",330};331 332static char *i2c_devs[128] = {333	[0x8e >> 1] = "au8522",334	[0xa0 >> 1] = "eeprom",335	[0xc2 >> 1] = "tuner/xc5000",336};337 338static void do_i2c_scan(char *name, struct i2c_client *c)339{340	unsigned char buf;341	int i, rc;342 343	for (i = 0; i < 128; i++) {344		c->addr = i;345		rc = i2c_master_recv(c, &buf, 0);346		if (rc < 0)347			continue;348		pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",349		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");350	}351}352 353/* init + register i2c adapter */354int au0828_i2c_register(struct au0828_dev *dev)355{356	dprintk(1, "%s()\n", __func__);357 358	dev->i2c_adap = au0828_i2c_adap_template;359	dev->i2c_algo = au0828_i2c_algo_template;360	dev->i2c_client = au0828_i2c_client_template;361 362	dev->i2c_adap.dev.parent = &dev->usbdev->dev;363 364	strscpy(dev->i2c_adap.name, KBUILD_MODNAME,365		sizeof(dev->i2c_adap.name));366 367	dev->i2c_adap.algo = &dev->i2c_algo;368	dev->i2c_adap.algo_data = dev;369#ifdef CONFIG_VIDEO_AU0828_V4L2370	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);371#else372	i2c_set_adapdata(&dev->i2c_adap, dev);373#endif374	i2c_add_adapter(&dev->i2c_adap);375 376	dev->i2c_client.adapter = &dev->i2c_adap;377 378	if (0 == dev->i2c_rc) {379		pr_info("i2c bus registered\n");380		if (i2c_scan)381			do_i2c_scan(KBUILD_MODNAME, &dev->i2c_client);382	} else383		pr_info("i2c bus register FAILED\n");384 385	return dev->i2c_rc;386}387 388int au0828_i2c_unregister(struct au0828_dev *dev)389{390	i2c_del_adapter(&dev->i2c_adap);391	return 0;392}393 394