xref: /openbmc/linux/drivers/media/usb/em28xx/em28xx-i2c.c (revision 6843868fd092406b544064e4db1ca902af13cf48)
10c0d06caSMauro Carvalho Chehab /*
20c0d06caSMauro Carvalho Chehab    em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
30c0d06caSMauro Carvalho Chehab 
40c0d06caSMauro Carvalho Chehab    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
50c0d06caSMauro Carvalho Chehab 		      Markus Rechberger <mrechberger@gmail.com>
60c0d06caSMauro Carvalho Chehab 		      Mauro Carvalho Chehab <mchehab@infradead.org>
70c0d06caSMauro Carvalho Chehab 		      Sascha Sommer <saschasommer@freenet.de>
8a3ea4bf9SFrank Schaefer    Copyright (C) 2013 Frank Schäfer <fschaefer.oss@googlemail.com>
90c0d06caSMauro Carvalho Chehab 
100c0d06caSMauro Carvalho Chehab    This program is free software; you can redistribute it and/or modify
110c0d06caSMauro Carvalho Chehab    it under the terms of the GNU General Public License as published by
120c0d06caSMauro Carvalho Chehab    the Free Software Foundation; either version 2 of the License, or
130c0d06caSMauro Carvalho Chehab    (at your option) any later version.
140c0d06caSMauro Carvalho Chehab 
150c0d06caSMauro Carvalho Chehab    This program is distributed in the hope that it will be useful,
160c0d06caSMauro Carvalho Chehab    but WITHOUT ANY WARRANTY; without even the implied warranty of
170c0d06caSMauro Carvalho Chehab    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
180c0d06caSMauro Carvalho Chehab    GNU General Public License for more details.
190c0d06caSMauro Carvalho Chehab 
200c0d06caSMauro Carvalho Chehab    You should have received a copy of the GNU General Public License
210c0d06caSMauro Carvalho Chehab    along with this program; if not, write to the Free Software
220c0d06caSMauro Carvalho Chehab    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
230c0d06caSMauro Carvalho Chehab  */
240c0d06caSMauro Carvalho Chehab 
258314d402SMauro Carvalho Chehab #include "em28xx.h"
268314d402SMauro Carvalho Chehab 
270c0d06caSMauro Carvalho Chehab #include <linux/module.h>
280c0d06caSMauro Carvalho Chehab #include <linux/kernel.h>
290c0d06caSMauro Carvalho Chehab #include <linux/usb.h>
300c0d06caSMauro Carvalho Chehab #include <linux/i2c.h>
314b83626aSMauro Carvalho Chehab #include <linux/jiffies.h>
320c0d06caSMauro Carvalho Chehab 
330c0d06caSMauro Carvalho Chehab #include "tuner-xc2028.h"
340c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h>
350c0d06caSMauro Carvalho Chehab #include <media/tuner.h>
360c0d06caSMauro Carvalho Chehab 
370c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
380c0d06caSMauro Carvalho Chehab 
390c0d06caSMauro Carvalho Chehab static unsigned int i2c_scan;
400c0d06caSMauro Carvalho Chehab module_param(i2c_scan, int, 0444);
410c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
420c0d06caSMauro Carvalho Chehab 
430c0d06caSMauro Carvalho Chehab static unsigned int i2c_debug;
440c0d06caSMauro Carvalho Chehab module_param(i2c_debug, int, 0644);
4550f0a9dfSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug, "i2c debug message level (1: normal debug, 2: show I2C transfers)");
460c0d06caSMauro Carvalho Chehab 
47ce8591ffSMauro Carvalho Chehab #define dprintk(level, fmt, arg...) do {				\
48ce8591ffSMauro Carvalho Chehab 	if (i2c_debug > level)						\
4929b05e22SMauro Carvalho Chehab 		dev_printk(KERN_DEBUG, &dev->intf->dev,			\
50ce8591ffSMauro Carvalho Chehab 			   "i2c: %s: " fmt, __func__, ## arg);		\
51ce8591ffSMauro Carvalho Chehab } while (0)
52ce8591ffSMauro Carvalho Chehab 
53ce8591ffSMauro Carvalho Chehab 
540c0d06caSMauro Carvalho Chehab /*
55f5ae371aSFrank Schaefer  * em2800_i2c_send_bytes()
56f5ae371aSFrank Schaefer  * send up to 4 bytes to the em2800 i2c device
570c0d06caSMauro Carvalho Chehab  */
58f5ae371aSFrank Schaefer static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
590c0d06caSMauro Carvalho Chehab {
60d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
610c0d06caSMauro Carvalho Chehab 	int ret;
62a6bad040SFrank Schaefer 	u8 b2[6];
63f5ae371aSFrank Schaefer 
64f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
65f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
66f5ae371aSFrank Schaefer 
670c0d06caSMauro Carvalho Chehab 	BUG_ON(len < 1 || len > 4);
680c0d06caSMauro Carvalho Chehab 	b2[5] = 0x80 + len - 1;
690c0d06caSMauro Carvalho Chehab 	b2[4] = addr;
700c0d06caSMauro Carvalho Chehab 	b2[3] = buf[0];
710c0d06caSMauro Carvalho Chehab 	if (len > 1)
720c0d06caSMauro Carvalho Chehab 		b2[2] = buf[1];
730c0d06caSMauro Carvalho Chehab 	if (len > 2)
740c0d06caSMauro Carvalho Chehab 		b2[1] = buf[2];
750c0d06caSMauro Carvalho Chehab 	if (len > 3)
760c0d06caSMauro Carvalho Chehab 		b2[0] = buf[3];
770c0d06caSMauro Carvalho Chehab 
782fcc82d8SFrank Schaefer 	/* trigger write */
790c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
800c0d06caSMauro Carvalho Chehab 	if (ret != 2 + len) {
8129b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
82ce8591ffSMauro Carvalho Chehab 			 "failed to trigger write to i2c address 0x%x (error=%i)\n",
83d230d5adSFrank Schaefer 			    addr, ret);
8445f04e82SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
850c0d06caSMauro Carvalho Chehab 	}
862fcc82d8SFrank Schaefer 	/* wait for completion */
874b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
880c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
894b83626aSMauro Carvalho Chehab 		if (ret == 0x80 + len - 1)
900c0d06caSMauro Carvalho Chehab 			return len;
914b83626aSMauro Carvalho Chehab 		if (ret == 0x94 + len - 1) {
92ce8591ffSMauro Carvalho Chehab 			dprintk(1, "R05 returned 0x%02x: I2C ACK error\n", ret);
93e63b009dSMauro Carvalho Chehab 			return -ENXIO;
944b83626aSMauro Carvalho Chehab 		}
954b83626aSMauro Carvalho Chehab 		if (ret < 0) {
9629b05e22SMauro Carvalho Chehab 			dev_warn(&dev->intf->dev,
97ce8591ffSMauro Carvalho Chehab 				 "failed to get i2c transfer status from bridge register (error=%i)\n",
98d230d5adSFrank Schaefer 				ret);
9945f04e82SFrank Schaefer 			return ret;
10045f04e82SFrank Schaefer 		}
1010c0d06caSMauro Carvalho Chehab 		msleep(5);
1020c0d06caSMauro Carvalho Chehab 	}
103ce8591ffSMauro Carvalho Chehab 	dprintk(0, "write to i2c device at 0x%x timed out\n", addr);
104e63b009dSMauro Carvalho Chehab 	return -ETIMEDOUT;
1050c0d06caSMauro Carvalho Chehab }
1060c0d06caSMauro Carvalho Chehab 
1070c0d06caSMauro Carvalho Chehab /*
1080c0d06caSMauro Carvalho Chehab  * em2800_i2c_recv_bytes()
1092fcc82d8SFrank Schaefer  * read up to 4 bytes from the em2800 i2c device
1100c0d06caSMauro Carvalho Chehab  */
111a6bad040SFrank Schaefer static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
1120c0d06caSMauro Carvalho Chehab {
113d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
1142fcc82d8SFrank Schaefer 	u8 buf2[4];
1150c0d06caSMauro Carvalho Chehab 	int ret;
1162fcc82d8SFrank Schaefer 	int i;
117f5ae371aSFrank Schaefer 
118f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
119f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
120f5ae371aSFrank Schaefer 
1212fcc82d8SFrank Schaefer 	/* trigger read */
1222fcc82d8SFrank Schaefer 	buf2[1] = 0x84 + len - 1;
1232fcc82d8SFrank Schaefer 	buf2[0] = addr;
1242fcc82d8SFrank Schaefer 	ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
1252fcc82d8SFrank Schaefer 	if (ret != 2) {
12629b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
127ce8591ffSMauro Carvalho Chehab 			 "failed to trigger read from i2c address 0x%x (error=%i)\n",
128d230d5adSFrank Schaefer 			 addr, ret);
1292fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1302fcc82d8SFrank Schaefer 	}
1312fcc82d8SFrank Schaefer 
1322fcc82d8SFrank Schaefer 	/* wait for completion */
1334b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
1342fcc82d8SFrank Schaefer 		ret = dev->em28xx_read_reg(dev, 0x05);
1354b83626aSMauro Carvalho Chehab 		if (ret == 0x84 + len - 1)
1362fcc82d8SFrank Schaefer 			break;
1374b83626aSMauro Carvalho Chehab 		if (ret == 0x94 + len - 1) {
138ce8591ffSMauro Carvalho Chehab 			dprintk(1, "R05 returned 0x%02x: I2C ACK error\n",
139d845fb3aSMauro Carvalho Chehab 				ret);
140e63b009dSMauro Carvalho Chehab 			return -ENXIO;
1414b83626aSMauro Carvalho Chehab 		}
1424b83626aSMauro Carvalho Chehab 		if (ret < 0) {
14329b05e22SMauro Carvalho Chehab 			dev_warn(&dev->intf->dev,
144ce8591ffSMauro Carvalho Chehab 				 "failed to get i2c transfer status from bridge register (error=%i)\n",
145d230d5adSFrank Schaefer 				 ret);
1460c0d06caSMauro Carvalho Chehab 			return ret;
1470c0d06caSMauro Carvalho Chehab 		}
1482fcc82d8SFrank Schaefer 		msleep(5);
1492fcc82d8SFrank Schaefer 	}
15050f0a9dfSMauro Carvalho Chehab 	if (ret != 0x84 + len - 1) {
151ce8591ffSMauro Carvalho Chehab 		dprintk(0, "read from i2c device at 0x%x timed out\n", addr);
15250f0a9dfSMauro Carvalho Chehab 	}
1532fcc82d8SFrank Schaefer 
1542fcc82d8SFrank Schaefer 	/* get the received message */
1552fcc82d8SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
1562fcc82d8SFrank Schaefer 	if (ret != len) {
15729b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
158ce8591ffSMauro Carvalho Chehab 			 "reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
159d230d5adSFrank Schaefer 			 addr, ret);
1602fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1612fcc82d8SFrank Schaefer 	}
1622fcc82d8SFrank Schaefer 	for (i = 0; i < len; i++)
1632fcc82d8SFrank Schaefer 		buf[i] = buf2[len - 1 - i];
1642fcc82d8SFrank Schaefer 
1650c0d06caSMauro Carvalho Chehab 	return ret;
1660c0d06caSMauro Carvalho Chehab }
1672fcc82d8SFrank Schaefer 
1682fcc82d8SFrank Schaefer /*
1692fcc82d8SFrank Schaefer  * em2800_i2c_check_for_device()
1702fcc82d8SFrank Schaefer  * check if there is an i2c device at the supplied address
1712fcc82d8SFrank Schaefer  */
1722fcc82d8SFrank Schaefer static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
1732fcc82d8SFrank Schaefer {
1742fcc82d8SFrank Schaefer 	u8 buf;
1752fcc82d8SFrank Schaefer 	int ret;
1762fcc82d8SFrank Schaefer 
1772fcc82d8SFrank Schaefer 	ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1);
1782fcc82d8SFrank Schaefer 	if (ret == 1)
1792fcc82d8SFrank Schaefer 		return 0;
1802fcc82d8SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
1810c0d06caSMauro Carvalho Chehab }
1820c0d06caSMauro Carvalho Chehab 
1830c0d06caSMauro Carvalho Chehab /*
1840c0d06caSMauro Carvalho Chehab  * em28xx_i2c_send_bytes()
1850c0d06caSMauro Carvalho Chehab  */
186a6bad040SFrank Schaefer static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
187a6bad040SFrank Schaefer 				 u16 len, int stop)
1880c0d06caSMauro Carvalho Chehab {
189d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
1904b83626aSMauro Carvalho Chehab 	int ret;
1910c0d06caSMauro Carvalho Chehab 
192f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
193f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
194fa74aca3SFrank Schaefer 	/*
195fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
196fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
197fa74aca3SFrank Schaefer 	 */
198f5ae371aSFrank Schaefer 
19945f04e82SFrank Schaefer 	/* Write to i2c device */
20045f04e82SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
20145f04e82SFrank Schaefer 	if (ret != len) {
20245f04e82SFrank Schaefer 		if (ret < 0) {
20329b05e22SMauro Carvalho Chehab 			dev_warn(&dev->intf->dev,
204ce8591ffSMauro Carvalho Chehab 				 "writing to i2c device at 0x%x failed (error=%i)\n",
205d230d5adSFrank Schaefer 				 addr, ret);
20645f04e82SFrank Schaefer 			return ret;
20745f04e82SFrank Schaefer 		} else {
20829b05e22SMauro Carvalho Chehab 			dev_warn(&dev->intf->dev,
209ce8591ffSMauro Carvalho Chehab 				 "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
21045f04e82SFrank Schaefer 				 len, addr, ret);
21145f04e82SFrank Schaefer 			return -EIO;
21245f04e82SFrank Schaefer 		}
21345f04e82SFrank Schaefer 	}
2140c0d06caSMauro Carvalho Chehab 
2154b83626aSMauro Carvalho Chehab 	/* wait for completion */
2164b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
2170c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
2184b83626aSMauro Carvalho Chehab 		if (ret == 0) /* success */
21945f04e82SFrank Schaefer 			return len;
2204b83626aSMauro Carvalho Chehab 		if (ret == 0x10) {
221ce8591ffSMauro Carvalho Chehab 			dprintk(1, "I2C ACK error on writing to addr 0x%02x\n",
222d845fb3aSMauro Carvalho Chehab 				addr);
223e63b009dSMauro Carvalho Chehab 			return -ENXIO;
2244b83626aSMauro Carvalho Chehab 		}
2254b83626aSMauro Carvalho Chehab 		if (ret < 0) {
22629b05e22SMauro Carvalho Chehab 			dev_warn(&dev->intf->dev,
227ce8591ffSMauro Carvalho Chehab 				 "failed to get i2c transfer status from bridge register (error=%i)\n",
228d230d5adSFrank Schaefer 				 ret);
22945f04e82SFrank Schaefer 			return ret;
2300c0d06caSMauro Carvalho Chehab 		}
23145f04e82SFrank Schaefer 		msleep(5);
232fa74aca3SFrank Schaefer 		/*
233fa74aca3SFrank Schaefer 		 * NOTE: do we really have to wait for success ?
234fa74aca3SFrank Schaefer 		 * Never seen anything else than 0x00 or 0x10
235fa74aca3SFrank Schaefer 		 * (even with high payload) ...
236fa74aca3SFrank Schaefer 		 */
23745f04e82SFrank Schaefer 	}
238123a17d1SFrank Schaefer 
239123a17d1SFrank Schaefer 	if (ret == 0x02 || ret == 0x04) {
240123a17d1SFrank Schaefer 		/* NOTE: these errors seem to be related to clock stretching */
241ce8591ffSMauro Carvalho Chehab 		dprintk(0,
242ce8591ffSMauro Carvalho Chehab 			"write to i2c device at 0x%x timed out (status=%i)\n",
24350f0a9dfSMauro Carvalho Chehab 			addr, ret);
244e63b009dSMauro Carvalho Chehab 		return -ETIMEDOUT;
2450c0d06caSMauro Carvalho Chehab 	}
2460c0d06caSMauro Carvalho Chehab 
24729b05e22SMauro Carvalho Chehab 	dev_warn(&dev->intf->dev,
248ce8591ffSMauro Carvalho Chehab 		 "write to i2c device at 0x%x failed with unknown error (status=%i)\n",
249123a17d1SFrank Schaefer 		 addr, ret);
250123a17d1SFrank Schaefer 	return -EIO;
251123a17d1SFrank Schaefer }
252123a17d1SFrank Schaefer 
2530c0d06caSMauro Carvalho Chehab /*
2540c0d06caSMauro Carvalho Chehab  * em28xx_i2c_recv_bytes()
2550c0d06caSMauro Carvalho Chehab  * read a byte from the i2c device
2560c0d06caSMauro Carvalho Chehab  */
257a6bad040SFrank Schaefer static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
2580c0d06caSMauro Carvalho Chehab {
2590c0d06caSMauro Carvalho Chehab 	int ret;
260f5ae371aSFrank Schaefer 
261f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
262f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
263fa74aca3SFrank Schaefer 	/*
264fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
265fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
266fa74aca3SFrank Schaefer 	 */
267f5ae371aSFrank Schaefer 
26845f04e82SFrank Schaefer 	/* Read data from i2c device */
2690c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
2700c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
27129b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
272ce8591ffSMauro Carvalho Chehab 			 "reading from i2c device at 0x%x failed (error=%i)\n",
2737f6301d1SFrank Schaefer 			 addr, ret);
27445f04e82SFrank Schaefer 		return ret;
27545f04e82SFrank Schaefer 	}
276fa74aca3SFrank Schaefer 	/*
277fa74aca3SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
2787f6301d1SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
2797f6301d1SFrank Schaefer 	 * specified slave address before AND no device is present at the
2807f6301d1SFrank Schaefer 	 * requested slave address.
281e63b009dSMauro Carvalho Chehab 	 * Anyway, the next check will fail with -ENXIO in this case, so avoid
2827f6301d1SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
2837f6301d1SFrank Schaefer 	 */
28445f04e82SFrank Schaefer 
28545f04e82SFrank Schaefer 	/* Check success of the i2c operation */
28645f04e82SFrank Schaefer 	ret = dev->em28xx_read_reg(dev, 0x05);
2874b83626aSMauro Carvalho Chehab 	if (ret == 0) /* success */
2884b83626aSMauro Carvalho Chehab 		return len;
28945f04e82SFrank Schaefer 	if (ret < 0) {
29029b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
291ce8591ffSMauro Carvalho Chehab 			 "failed to get i2c transfer status from bridge register (error=%i)\n",
292d230d5adSFrank Schaefer 			 ret);
2930c0d06caSMauro Carvalho Chehab 		return ret;
2940c0d06caSMauro Carvalho Chehab 	}
295d845fb3aSMauro Carvalho Chehab 	if (ret == 0x10) {
296ce8591ffSMauro Carvalho Chehab 		dprintk(1, "I2C ACK error on writing to addr 0x%02x\n",
297d845fb3aSMauro Carvalho Chehab 			addr);
298e63b009dSMauro Carvalho Chehab 		return -ENXIO;
299d845fb3aSMauro Carvalho Chehab 	}
3004b83626aSMauro Carvalho Chehab 
301123a17d1SFrank Schaefer 	if (ret == 0x02 || ret == 0x04) {
302123a17d1SFrank Schaefer 		/* NOTE: these errors seem to be related to clock stretching */
303ce8591ffSMauro Carvalho Chehab 		dprintk(0,
304ce8591ffSMauro Carvalho Chehab 			"write to i2c device at 0x%x timed out (status=%i)\n",
305123a17d1SFrank Schaefer 			addr, ret);
306e63b009dSMauro Carvalho Chehab 		return -ETIMEDOUT;
30745f04e82SFrank Schaefer 	}
3080c0d06caSMauro Carvalho Chehab 
30929b05e22SMauro Carvalho Chehab 	dev_warn(&dev->intf->dev,
310ce8591ffSMauro Carvalho Chehab 		 "write to i2c device at 0x%x failed with unknown error (status=%i)\n",
311123a17d1SFrank Schaefer 		 addr, ret);
312123a17d1SFrank Schaefer 	return -EIO;
313123a17d1SFrank Schaefer }
314123a17d1SFrank Schaefer 
3150c0d06caSMauro Carvalho Chehab /*
3160c0d06caSMauro Carvalho Chehab  * em28xx_i2c_check_for_device()
3170c0d06caSMauro Carvalho Chehab  * check if there is a i2c_device at the supplied address
3180c0d06caSMauro Carvalho Chehab  */
319a6bad040SFrank Schaefer static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
3200c0d06caSMauro Carvalho Chehab {
3210c0d06caSMauro Carvalho Chehab 	int ret;
32245f04e82SFrank Schaefer 	u8 buf;
3230c0d06caSMauro Carvalho Chehab 
32445f04e82SFrank Schaefer 	ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1);
32545f04e82SFrank Schaefer 	if (ret == 1)
3260c0d06caSMauro Carvalho Chehab 		return 0;
32745f04e82SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
3280c0d06caSMauro Carvalho Chehab }
3290c0d06caSMauro Carvalho Chehab 
3300c0d06caSMauro Carvalho Chehab /*
331a3ea4bf9SFrank Schaefer  * em25xx_bus_B_send_bytes
332a3ea4bf9SFrank Schaefer  * write bytes to the i2c device
333a3ea4bf9SFrank Schaefer  */
334a3ea4bf9SFrank Schaefer static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
335a3ea4bf9SFrank Schaefer 				   u16 len)
336a3ea4bf9SFrank Schaefer {
337a3ea4bf9SFrank Schaefer 	int ret;
338a3ea4bf9SFrank Schaefer 
339a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
340a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
341a3ea4bf9SFrank Schaefer 	/*
342a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
343a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
344a3ea4bf9SFrank Schaefer 	 */
345a3ea4bf9SFrank Schaefer 
346a3ea4bf9SFrank Schaefer 	/* Set register and write value */
347a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len);
348a3ea4bf9SFrank Schaefer 	if (ret != len) {
349a3ea4bf9SFrank Schaefer 		if (ret < 0) {
35029b05e22SMauro Carvalho Chehab 			dev_warn(&dev->intf->dev,
351ce8591ffSMauro Carvalho Chehab 				 "writing to i2c device at 0x%x failed (error=%i)\n",
352a3ea4bf9SFrank Schaefer 				 addr, ret);
353a3ea4bf9SFrank Schaefer 			return ret;
354a3ea4bf9SFrank Schaefer 		} else {
35529b05e22SMauro Carvalho Chehab 			dev_warn(&dev->intf->dev,
356ce8591ffSMauro Carvalho Chehab 				 "%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
357a3ea4bf9SFrank Schaefer 				 len, addr, ret);
358a3ea4bf9SFrank Schaefer 			return -EIO;
359a3ea4bf9SFrank Schaefer 		}
360a3ea4bf9SFrank Schaefer 	}
361a3ea4bf9SFrank Schaefer 	/* Check success */
362a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
363a3ea4bf9SFrank Schaefer 	/*
364a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
365a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
366a3ea4bf9SFrank Schaefer 	 */
367a3ea4bf9SFrank Schaefer 	if (!ret)
368a3ea4bf9SFrank Schaefer 		return len;
369d845fb3aSMauro Carvalho Chehab 	else if (ret > 0) {
370ce8591ffSMauro Carvalho Chehab 		dprintk(1, "Bus B R08 returned 0x%02x: I2C ACK error\n", ret);
371e63b009dSMauro Carvalho Chehab 		return -ENXIO;
372d845fb3aSMauro Carvalho Chehab 	}
373a3ea4bf9SFrank Schaefer 
374a3ea4bf9SFrank Schaefer 	return ret;
375a3ea4bf9SFrank Schaefer 	/*
376a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
377a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
378a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
379a3ea4bf9SFrank Schaefer 	 */
380a3ea4bf9SFrank Schaefer }
381a3ea4bf9SFrank Schaefer 
382a3ea4bf9SFrank Schaefer /*
383a3ea4bf9SFrank Schaefer  * em25xx_bus_B_recv_bytes
384a3ea4bf9SFrank Schaefer  * read bytes from the i2c device
385a3ea4bf9SFrank Schaefer  */
386a3ea4bf9SFrank Schaefer static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf,
387a3ea4bf9SFrank Schaefer 				   u16 len)
388a3ea4bf9SFrank Schaefer {
389a3ea4bf9SFrank Schaefer 	int ret;
390a3ea4bf9SFrank Schaefer 
391a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
392a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
393a3ea4bf9SFrank Schaefer 	/*
394a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
395a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
396a3ea4bf9SFrank Schaefer 	 */
397a3ea4bf9SFrank Schaefer 
398a3ea4bf9SFrank Schaefer 	/* Read value */
399a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len);
400a3ea4bf9SFrank Schaefer 	if (ret < 0) {
40129b05e22SMauro Carvalho Chehab 		dev_warn(&dev->intf->dev,
402ce8591ffSMauro Carvalho Chehab 			 "reading from i2c device at 0x%x failed (error=%i)\n",
403a3ea4bf9SFrank Schaefer 			 addr, ret);
404a3ea4bf9SFrank Schaefer 		return ret;
405a3ea4bf9SFrank Schaefer 	}
406a3ea4bf9SFrank Schaefer 	/*
407a3ea4bf9SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
408a3ea4bf9SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
409a3ea4bf9SFrank Schaefer 	 * specified slave address before AND no device is present at the
410a3ea4bf9SFrank Schaefer 	 * requested slave address.
411e63b009dSMauro Carvalho Chehab 	 * Anyway, the next check will fail with -ENXIO in this case, so avoid
412a3ea4bf9SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
413a3ea4bf9SFrank Schaefer 	 */
414a3ea4bf9SFrank Schaefer 
415a3ea4bf9SFrank Schaefer 	/* Check success */
416a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
417a3ea4bf9SFrank Schaefer 	/*
418a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
419a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
420a3ea4bf9SFrank Schaefer 	 */
421a3ea4bf9SFrank Schaefer 	if (!ret)
422a3ea4bf9SFrank Schaefer 		return len;
423d845fb3aSMauro Carvalho Chehab 	else if (ret > 0) {
424ce8591ffSMauro Carvalho Chehab 		dprintk(1, "Bus B R08 returned 0x%02x: I2C ACK error\n", ret);
425e63b009dSMauro Carvalho Chehab 		return -ENXIO;
426d845fb3aSMauro Carvalho Chehab 	}
427a3ea4bf9SFrank Schaefer 
428a3ea4bf9SFrank Schaefer 	return ret;
429a3ea4bf9SFrank Schaefer 	/*
430a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
431a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
432a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
433a3ea4bf9SFrank Schaefer 	 */
434a3ea4bf9SFrank Schaefer }
435a3ea4bf9SFrank Schaefer 
436a3ea4bf9SFrank Schaefer /*
437a3ea4bf9SFrank Schaefer  * em25xx_bus_B_check_for_device()
438a3ea4bf9SFrank Schaefer  * check if there is a i2c device at the supplied address
439a3ea4bf9SFrank Schaefer  */
440a3ea4bf9SFrank Schaefer static int em25xx_bus_B_check_for_device(struct em28xx *dev, u16 addr)
441a3ea4bf9SFrank Schaefer {
442a3ea4bf9SFrank Schaefer 	u8 buf;
443a3ea4bf9SFrank Schaefer 	int ret;
444a3ea4bf9SFrank Schaefer 
445a3ea4bf9SFrank Schaefer 	ret = em25xx_bus_B_recv_bytes(dev, addr, &buf, 1);
446a3ea4bf9SFrank Schaefer 	if (ret < 0)
447a3ea4bf9SFrank Schaefer 		return ret;
448a3ea4bf9SFrank Schaefer 
449a3ea4bf9SFrank Schaefer 	return 0;
450a3ea4bf9SFrank Schaefer 	/*
451a3ea4bf9SFrank Schaefer 	 * NOTE: With chips which do not support this operation,
452a3ea4bf9SFrank Schaefer 	 * it seems to succeed ALWAYS ! (even if no device connected)
453a3ea4bf9SFrank Schaefer 	 */
454a3ea4bf9SFrank Schaefer }
455a3ea4bf9SFrank Schaefer 
456a3ea4bf9SFrank Schaefer static inline int i2c_check_for_device(struct em28xx_i2c_bus *i2c_bus, u16 addr)
457a3ea4bf9SFrank Schaefer {
458a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
459a3ea4bf9SFrank Schaefer 	int rc = -EOPNOTSUPP;
460a3ea4bf9SFrank Schaefer 
461a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
462a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_check_for_device(dev, addr);
463a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
464a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_check_for_device(dev, addr);
465a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
466a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_check_for_device(dev, addr);
467a3ea4bf9SFrank Schaefer 	return rc;
468a3ea4bf9SFrank Schaefer }
469a3ea4bf9SFrank Schaefer 
470a3ea4bf9SFrank Schaefer static inline int i2c_recv_bytes(struct em28xx_i2c_bus *i2c_bus,
471a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg)
472a3ea4bf9SFrank Schaefer {
473a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
474a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
47550f0a9dfSMauro Carvalho Chehab 	int rc = -EOPNOTSUPP;
476a3ea4bf9SFrank Schaefer 
477a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
478a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
479a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
480a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
481a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
482a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len);
483a3ea4bf9SFrank Schaefer 	return rc;
484a3ea4bf9SFrank Schaefer }
485a3ea4bf9SFrank Schaefer 
486a3ea4bf9SFrank Schaefer static inline int i2c_send_bytes(struct em28xx_i2c_bus *i2c_bus,
487a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg, int stop)
488a3ea4bf9SFrank Schaefer {
489a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
490a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
49150f0a9dfSMauro Carvalho Chehab 	int rc = -EOPNOTSUPP;
492a3ea4bf9SFrank Schaefer 
493a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
494a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop);
495a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
496a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_send_bytes(dev, addr, msg.buf, msg.len);
497a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
498a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_send_bytes(dev, addr, msg.buf, msg.len);
499a3ea4bf9SFrank Schaefer 	return rc;
500a3ea4bf9SFrank Schaefer }
501a3ea4bf9SFrank Schaefer 
502a3ea4bf9SFrank Schaefer /*
5030c0d06caSMauro Carvalho Chehab  * em28xx_i2c_xfer()
5040c0d06caSMauro Carvalho Chehab  * the main i2c transfer function
5050c0d06caSMauro Carvalho Chehab  */
5060c0d06caSMauro Carvalho Chehab static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
5070c0d06caSMauro Carvalho Chehab 			   struct i2c_msg msgs[], int num)
5080c0d06caSMauro Carvalho Chehab {
509aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
510aab3125cSMauro Carvalho Chehab 	struct em28xx *dev = i2c_bus->dev;
511aab3125cSMauro Carvalho Chehab 	unsigned bus = i2c_bus->bus;
512a3ea4bf9SFrank Schaefer 	int addr, rc, i;
5133190fbeeSMauro Carvalho Chehab 	u8 reg;
5140c0d06caSMauro Carvalho Chehab 
515cc5c5d20SShuah Khan 	/* prevent i2c xfer attempts after device is disconnected
516cc5c5d20SShuah Khan 	   some fe's try to do i2c writes/reads from their release
517cc5c5d20SShuah Khan 	   interfaces when called in disconnect path */
518cc5c5d20SShuah Khan 	if (dev->disconnected)
519cc5c5d20SShuah Khan 		return -ENODEV;
520cc5c5d20SShuah Khan 
521e44c153bSDan Carpenter 	if (!rt_mutex_trylock(&dev->i2c_bus_lock))
522e44c153bSDan Carpenter 		return -EAGAIN;
523aab3125cSMauro Carvalho Chehab 
524aab3125cSMauro Carvalho Chehab 	/* Switch I2C bus if needed */
525a3ea4bf9SFrank Schaefer 	if (bus != dev->cur_i2c_bus &&
526a3ea4bf9SFrank Schaefer 	    i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) {
527aab3125cSMauro Carvalho Chehab 		if (bus == 1)
5283190fbeeSMauro Carvalho Chehab 			reg = EM2874_I2C_SECONDARY_BUS_SELECT;
529aab3125cSMauro Carvalho Chehab 		else
5303190fbeeSMauro Carvalho Chehab 			reg = 0;
5313190fbeeSMauro Carvalho Chehab 		em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg,
5323190fbeeSMauro Carvalho Chehab 				      EM2874_I2C_SECONDARY_BUS_SELECT);
533aab3125cSMauro Carvalho Chehab 		dev->cur_i2c_bus = bus;
534aab3125cSMauro Carvalho Chehab 	}
535aab3125cSMauro Carvalho Chehab 
536aab3125cSMauro Carvalho Chehab 	if (num <= 0) {
537aab3125cSMauro Carvalho Chehab 		rt_mutex_unlock(&dev->i2c_bus_lock);
5380c0d06caSMauro Carvalho Chehab 		return 0;
539aab3125cSMauro Carvalho Chehab 	}
5400c0d06caSMauro Carvalho Chehab 	for (i = 0; i < num; i++) {
5410c0d06caSMauro Carvalho Chehab 		addr = msgs[i].addr << 1;
542e63b009dSMauro Carvalho Chehab 		if (!msgs[i].len) {
543e63b009dSMauro Carvalho Chehab 			/*
544e63b009dSMauro Carvalho Chehab 			 * no len: check only for device presence
545e63b009dSMauro Carvalho Chehab 			 * This code is only called during device probe.
546e63b009dSMauro Carvalho Chehab 			 */
547a3ea4bf9SFrank Schaefer 			rc = i2c_check_for_device(i2c_bus, addr);
548ce8591ffSMauro Carvalho Chehab 
549ce8591ffSMauro Carvalho Chehab 			if (rc == -ENXIO)
55050f0a9dfSMauro Carvalho Chehab 				rc = -ENODEV;
5510c0d06caSMauro Carvalho Chehab 		} else if (msgs[i].flags & I2C_M_RD) {
5520c0d06caSMauro Carvalho Chehab 			/* read bytes */
553a3ea4bf9SFrank Schaefer 			rc = i2c_recv_bytes(i2c_bus, msgs[i]);
5540c0d06caSMauro Carvalho Chehab 		} else {
5550c0d06caSMauro Carvalho Chehab 			/* write bytes */
556a3ea4bf9SFrank Schaefer 			rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1);
5570c0d06caSMauro Carvalho Chehab 		}
558ce8591ffSMauro Carvalho Chehab 
559ce8591ffSMauro Carvalho Chehab 		if (rc < 0)
560ce8591ffSMauro Carvalho Chehab 			goto error;
561ce8591ffSMauro Carvalho Chehab 
562ce8591ffSMauro Carvalho Chehab 		dprintk(2, "%s %s addr=%02x len=%d: %*ph\n",
563ce8591ffSMauro Carvalho Chehab 			(msgs[i].flags & I2C_M_RD) ? "read" : "write",
564ce8591ffSMauro Carvalho Chehab 			i == num - 1 ? "stop" : "nonstop",
565ce8591ffSMauro Carvalho Chehab 			addr, msgs[i].len,
566ce8591ffSMauro Carvalho Chehab 			msgs[i].len, msgs[i].buf);
5670c0d06caSMauro Carvalho Chehab 	}
5680c0d06caSMauro Carvalho Chehab 
569aab3125cSMauro Carvalho Chehab 	rt_mutex_unlock(&dev->i2c_bus_lock);
5700c0d06caSMauro Carvalho Chehab 	return num;
571ce8591ffSMauro Carvalho Chehab 
572ce8591ffSMauro Carvalho Chehab error:
573ce8591ffSMauro Carvalho Chehab 	dprintk(2, "%s %s addr=%02x len=%d: %sERROR: %i\n",
574ce8591ffSMauro Carvalho Chehab 		(msgs[i].flags & I2C_M_RD) ? "read" : "write",
575ce8591ffSMauro Carvalho Chehab 		i == num - 1 ? "stop" : "nonstop",
576ce8591ffSMauro Carvalho Chehab 		addr, msgs[i].len,
577ce8591ffSMauro Carvalho Chehab 		(rc == -ENODEV) ? "no device " : "",
578ce8591ffSMauro Carvalho Chehab 		rc);
579ce8591ffSMauro Carvalho Chehab 
580ce8591ffSMauro Carvalho Chehab 	rt_mutex_unlock(&dev->i2c_bus_lock);
581ce8591ffSMauro Carvalho Chehab 	return rc;
5820c0d06caSMauro Carvalho Chehab }
5830c0d06caSMauro Carvalho Chehab 
584fa74aca3SFrank Schaefer /*
585fa74aca3SFrank Schaefer  * based on linux/sunrpc/svcauth.h and linux/hash.h
5860c0d06caSMauro Carvalho Chehab  * The original hash function returns a different value, if arch is x86_64
5870c0d06caSMauro Carvalho Chehab  * or i386.
5880c0d06caSMauro Carvalho Chehab  */
5890c0d06caSMauro Carvalho Chehab static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
5900c0d06caSMauro Carvalho Chehab {
5910c0d06caSMauro Carvalho Chehab 	unsigned long hash = 0;
5920c0d06caSMauro Carvalho Chehab 	unsigned long l = 0;
5930c0d06caSMauro Carvalho Chehab 	int len = 0;
5940c0d06caSMauro Carvalho Chehab 	unsigned char c;
595fdf1bc9fSMauro Carvalho Chehab 
5960c0d06caSMauro Carvalho Chehab 	do {
5970c0d06caSMauro Carvalho Chehab 		if (len == length) {
5980c0d06caSMauro Carvalho Chehab 			c = (char)len;
5990c0d06caSMauro Carvalho Chehab 			len = -1;
6000c0d06caSMauro Carvalho Chehab 		} else
6010c0d06caSMauro Carvalho Chehab 			c = *buf++;
6020c0d06caSMauro Carvalho Chehab 		l = (l << 8) | c;
6030c0d06caSMauro Carvalho Chehab 		len++;
6040c0d06caSMauro Carvalho Chehab 		if ((len & (32 / 8 - 1)) == 0)
6050c0d06caSMauro Carvalho Chehab 			hash = ((hash^l) * 0x9e370001UL);
6060c0d06caSMauro Carvalho Chehab 	} while (len);
6070c0d06caSMauro Carvalho Chehab 
6080c0d06caSMauro Carvalho Chehab 	return (hash >> (32 - bits)) & 0xffffffffUL;
6090c0d06caSMauro Carvalho Chehab }
6100c0d06caSMauro Carvalho Chehab 
611fa74aca3SFrank Schaefer /*
612fa74aca3SFrank Schaefer  * Helper function to read data blocks from i2c clients with 8 or 16 bit
613fa74aca3SFrank Schaefer  * address width, 8 bit register width and auto incrementation been activated
614fa74aca3SFrank Schaefer  */
615aab3125cSMauro Carvalho Chehab static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
616aab3125cSMauro Carvalho Chehab 				 bool addr_w16, u16 len, u8 *data)
617d832c5b2SFrank Schaefer {
618d832c5b2SFrank Schaefer 	int remain = len, rsize, rsize_max, ret;
619d832c5b2SFrank Schaefer 	u8 buf[2];
620d832c5b2SFrank Schaefer 
621d832c5b2SFrank Schaefer 	/* Sanity check */
622d832c5b2SFrank Schaefer 	if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1))
623d832c5b2SFrank Schaefer 		return -EINVAL;
624d832c5b2SFrank Schaefer 	/* Select address */
625d832c5b2SFrank Schaefer 	buf[0] = addr >> 8;
626d832c5b2SFrank Schaefer 	buf[1] = addr & 0xff;
627aab3125cSMauro Carvalho Chehab 	ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16);
628d832c5b2SFrank Schaefer 	if (ret < 0)
629d832c5b2SFrank Schaefer 		return ret;
630d832c5b2SFrank Schaefer 	/* Read data */
631d832c5b2SFrank Schaefer 	if (dev->board.is_em2800)
632d832c5b2SFrank Schaefer 		rsize_max = 4;
633d832c5b2SFrank Schaefer 	else
634d832c5b2SFrank Schaefer 		rsize_max = 64;
635d832c5b2SFrank Schaefer 	while (remain > 0) {
636d832c5b2SFrank Schaefer 		if (remain > rsize_max)
637d832c5b2SFrank Schaefer 			rsize = rsize_max;
638d832c5b2SFrank Schaefer 		else
639d832c5b2SFrank Schaefer 			rsize = remain;
640d832c5b2SFrank Schaefer 
641aab3125cSMauro Carvalho Chehab 		ret = i2c_master_recv(&dev->i2c_client[bus], data, rsize);
642d832c5b2SFrank Schaefer 		if (ret < 0)
643d832c5b2SFrank Schaefer 			return ret;
644d832c5b2SFrank Schaefer 
645d832c5b2SFrank Schaefer 		remain -= rsize;
646d832c5b2SFrank Schaefer 		data += rsize;
647d832c5b2SFrank Schaefer 	}
648d832c5b2SFrank Schaefer 
649d832c5b2SFrank Schaefer 	return len;
650d832c5b2SFrank Schaefer }
651d832c5b2SFrank Schaefer 
652aab3125cSMauro Carvalho Chehab static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
653aab3125cSMauro Carvalho Chehab 			     u8 **eedata, u16 *eedata_len)
6540c0d06caSMauro Carvalho Chehab {
655510e884cSFrank Schaefer 	const u16 len = 256;
656fa74aca3SFrank Schaefer 	/*
657fa74aca3SFrank Schaefer 	 * FIXME common length/size for bytes to read, to display, hash
658510e884cSFrank Schaefer 	 * calculation and returned device dataset. Simplifies the code a lot,
659fa74aca3SFrank Schaefer 	 * but we might have to deal with multiple sizes in the future !
660fa74aca3SFrank Schaefer 	 */
66150f0a9dfSMauro Carvalho Chehab 	int err;
662510e884cSFrank Schaefer 	struct em28xx_eeprom *dev_config;
663510e884cSFrank Schaefer 	u8 buf, *data;
6640c0d06caSMauro Carvalho Chehab 
665a217968fSFrank Schaefer 	*eedata = NULL;
666510e884cSFrank Schaefer 	*eedata_len = 0;
667a217968fSFrank Schaefer 
668aab3125cSMauro Carvalho Chehab 	/* EEPROM is always on i2c bus 0 on all known devices. */
669aab3125cSMauro Carvalho Chehab 
670aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].addr = 0xa0 >> 1;
6710c0d06caSMauro Carvalho Chehab 
6720c0d06caSMauro Carvalho Chehab 	/* Check if board has eeprom */
673aab3125cSMauro Carvalho Chehab 	err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
6740c0d06caSMauro Carvalho Chehab 	if (err < 0) {
67529b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "board has no eeprom\n");
6760c0d06caSMauro Carvalho Chehab 		return -ENODEV;
6770c0d06caSMauro Carvalho Chehab 	}
6780c0d06caSMauro Carvalho Chehab 
679a217968fSFrank Schaefer 	data = kzalloc(len, GFP_KERNEL);
680a217968fSFrank Schaefer 	if (data == NULL)
681a217968fSFrank Schaefer 		return -ENOMEM;
682a217968fSFrank Schaefer 
683d832c5b2SFrank Schaefer 	/* Read EEPROM content */
684aab3125cSMauro Carvalho Chehab 	err = em28xx_i2c_read_block(dev, bus, 0x0000,
685aab3125cSMauro Carvalho Chehab 				    dev->eeprom_addrwidth_16bit,
686a217968fSFrank Schaefer 				    len, data);
687d832c5b2SFrank Schaefer 	if (err != len) {
68829b05e22SMauro Carvalho Chehab 		dev_err(&dev->intf->dev,
689ce8591ffSMauro Carvalho Chehab 			"failed to read eeprom (err=%d)\n", err);
690510e884cSFrank Schaefer 		goto error;
6910c0d06caSMauro Carvalho Chehab 	}
69290271964SFrank Schaefer 
69350f0a9dfSMauro Carvalho Chehab 	if (i2c_debug) {
69487b52439SFrank Schaefer 		/* Display eeprom content */
695ce8591ffSMauro Carvalho Chehab 		print_hex_dump(KERN_DEBUG, "em28xx eeprom ", DUMP_PREFIX_OFFSET,
69650f0a9dfSMauro Carvalho Chehab 			       16, 1, data, len, true);
69750f0a9dfSMauro Carvalho Chehab 
69887b52439SFrank Schaefer 		if (dev->eeprom_addrwidth_16bit)
69929b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev,
700ce8591ffSMauro Carvalho Chehab 				 "eeprom %06x: ... (skipped)\n", 256);
70187b52439SFrank Schaefer 	}
7020c0d06caSMauro Carvalho Chehab 
70387b52439SFrank Schaefer 	if (dev->eeprom_addrwidth_16bit &&
704a217968fSFrank Schaefer 	    data[0] == 0x26 && data[3] == 0x00) {
70587b52439SFrank Schaefer 		/* new eeprom format; size 4-64kb */
706510e884cSFrank Schaefer 		u16 mc_start;
707510e884cSFrank Schaefer 		u16 hwconf_offset;
708510e884cSFrank Schaefer 
709a217968fSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
710510e884cSFrank Schaefer 		mc_start = (data[1] << 8) + 4;	/* usually 0x0004 */
711510e884cSFrank Schaefer 
71229b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev,
713ce8591ffSMauro Carvalho Chehab 			 "EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
714510e884cSFrank Schaefer 			 data[0], data[1], data[2], data[3], dev->hash);
71529b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev,
716ce8591ffSMauro Carvalho Chehab 			 "EEPROM info:\n");
71729b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev,
718ce8591ffSMauro Carvalho Chehab 			 "\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n",
719510e884cSFrank Schaefer 			 mc_start, data[2]);
720fa74aca3SFrank Schaefer 		/*
721fa74aca3SFrank Schaefer 		 * boot configuration (address 0x0002):
72287b52439SFrank Schaefer 		 * [0]   microcode download speed: 1 = 400 kHz; 0 = 100 kHz
72387b52439SFrank Schaefer 		 * [1]   always selects 12 kb RAM
72487b52439SFrank Schaefer 		 * [2]   USB device speed: 1 = force Full Speed; 0 = auto detect
72587b52439SFrank Schaefer 		 * [4]   1 = force fast mode and no suspend for device testing
72687b52439SFrank Schaefer 		 * [5:7] USB PHY tuning registers; determined by device
72787b52439SFrank Schaefer 		 *       characterization
72887b52439SFrank Schaefer 		 */
72987b52439SFrank Schaefer 
730fa74aca3SFrank Schaefer 		/*
731fa74aca3SFrank Schaefer 		 * Read hardware config dataset offset from address
732fa74aca3SFrank Schaefer 		 * (microcode start + 46)
733fa74aca3SFrank Schaefer 		 */
734aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2,
735aab3125cSMauro Carvalho Chehab 					    data);
736510e884cSFrank Schaefer 		if (err != 2) {
73729b05e22SMauro Carvalho Chehab 			dev_err(&dev->intf->dev,
738ce8591ffSMauro Carvalho Chehab 				"failed to read hardware configuration data from eeprom (err=%d)\n",
739510e884cSFrank Schaefer 				err);
740510e884cSFrank Schaefer 			goto error;
741510e884cSFrank Schaefer 		}
74287b52439SFrank Schaefer 
743510e884cSFrank Schaefer 		/* Calculate hardware config dataset start address */
744510e884cSFrank Schaefer 		hwconf_offset = mc_start + data[0] + (data[1] << 8);
745510e884cSFrank Schaefer 
746510e884cSFrank Schaefer 		/* Read hardware config dataset */
747fa74aca3SFrank Schaefer 		/*
748fa74aca3SFrank Schaefer 		 * NOTE: the microcode copy can be multiple pages long, but
749510e884cSFrank Schaefer 		 * we assume the hardware config dataset is the same as in
750510e884cSFrank Schaefer 		 * the old eeprom and not longer than 256 bytes.
751510e884cSFrank Schaefer 		 * tveeprom is currently also limited to 256 bytes.
752510e884cSFrank Schaefer 		 */
753aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len,
754aab3125cSMauro Carvalho Chehab 					    data);
755510e884cSFrank Schaefer 		if (err != len) {
75629b05e22SMauro Carvalho Chehab 			dev_err(&dev->intf->dev,
757ce8591ffSMauro Carvalho Chehab 				"failed to read hardware configuration data from eeprom (err=%d)\n",
758510e884cSFrank Schaefer 				err);
759510e884cSFrank Schaefer 			goto error;
760510e884cSFrank Schaefer 		}
761510e884cSFrank Schaefer 
762510e884cSFrank Schaefer 		/* Verify hardware config dataset */
763510e884cSFrank Schaefer 		/* NOTE: not all devices provide this type of dataset */
764510e884cSFrank Schaefer 		if (data[0] != 0x1a || data[1] != 0xeb ||
765a217968fSFrank Schaefer 		    data[2] != 0x67 || data[3] != 0x95) {
76629b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev,
767ce8591ffSMauro Carvalho Chehab 				 "\tno hardware configuration dataset found in eeprom\n");
768510e884cSFrank Schaefer 			kfree(data);
769510e884cSFrank Schaefer 			return 0;
770510e884cSFrank Schaefer 		}
771510e884cSFrank Schaefer 
772510e884cSFrank Schaefer 		/* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */
773510e884cSFrank Schaefer 
774510e884cSFrank Schaefer 	} else if (!dev->eeprom_addrwidth_16bit &&
775510e884cSFrank Schaefer 		   data[0] == 0x1a && data[1] == 0xeb &&
776510e884cSFrank Schaefer 		   data[2] == 0x67 && data[3] == 0x95) {
777510e884cSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
77829b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev,
779ce8591ffSMauro Carvalho Chehab 			 "EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
780510e884cSFrank Schaefer 			 data[0], data[1], data[2], data[3], dev->hash);
78129b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev,
782ce8591ffSMauro Carvalho Chehab 			 "EEPROM info:\n");
783510e884cSFrank Schaefer 	} else {
78429b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev,
785ce8591ffSMauro Carvalho Chehab 			 "unknown eeprom format or eeprom corrupted !\n");
786510e884cSFrank Schaefer 		err = -ENODEV;
787510e884cSFrank Schaefer 		goto error;
788f55eacbeSFrank Schaefer 	}
789f55eacbeSFrank Schaefer 
790a217968fSFrank Schaefer 	*eedata = data;
791510e884cSFrank Schaefer 	*eedata_len = len;
79232bf7c6cSAlban Browaeys 	dev_config = (void *)*eedata;
793a217968fSFrank Schaefer 
794510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
7950c0d06caSMauro Carvalho Chehab 	case 0:
79629b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "\tNo audio on board.\n");
7970c0d06caSMauro Carvalho Chehab 		break;
7980c0d06caSMauro Carvalho Chehab 	case 1:
79929b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "\tAC97 audio (5 sample rates)\n");
8000c0d06caSMauro Carvalho Chehab 		break;
8010c0d06caSMauro Carvalho Chehab 	case 2:
802687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
80329b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev,
804ce8591ffSMauro Carvalho Chehab 				 "\tI2S audio, sample rate=32k\n");
805687ff8b0SFrank Schaefer 		else
80629b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev,
807ce8591ffSMauro Carvalho Chehab 				 "\tI2S audio, 3 sample rates\n");
8080c0d06caSMauro Carvalho Chehab 		break;
8090c0d06caSMauro Carvalho Chehab 	case 3:
810687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
81129b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev,
812ce8591ffSMauro Carvalho Chehab 				 "\tI2S audio, 3 sample rates\n");
813687ff8b0SFrank Schaefer 		else
81429b05e22SMauro Carvalho Chehab 			dev_info(&dev->intf->dev,
815ce8591ffSMauro Carvalho Chehab 				 "\tI2S audio, 5 sample rates\n");
8160c0d06caSMauro Carvalho Chehab 		break;
8170c0d06caSMauro Carvalho Chehab 	}
8180c0d06caSMauro Carvalho Chehab 
819510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 3)
82029b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "\tUSB Remote wakeup capable\n");
8210c0d06caSMauro Carvalho Chehab 
822510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 2)
82329b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "\tUSB Self power capable\n");
8240c0d06caSMauro Carvalho Chehab 
825510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) & 0x3) {
8260c0d06caSMauro Carvalho Chehab 	case 0:
82729b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "\t500mA max power\n");
8280c0d06caSMauro Carvalho Chehab 		break;
8290c0d06caSMauro Carvalho Chehab 	case 1:
83029b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "\t400mA max power\n");
8310c0d06caSMauro Carvalho Chehab 		break;
8320c0d06caSMauro Carvalho Chehab 	case 2:
83329b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "\t300mA max power\n");
8340c0d06caSMauro Carvalho Chehab 		break;
8350c0d06caSMauro Carvalho Chehab 	case 3:
83629b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev, "\t200mA max power\n");
8370c0d06caSMauro Carvalho Chehab 		break;
8380c0d06caSMauro Carvalho Chehab 	}
83929b05e22SMauro Carvalho Chehab 	dev_info(&dev->intf->dev,
840ce8591ffSMauro Carvalho Chehab 		 "\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
841510e884cSFrank Schaefer 		 dev_config->string_idx_table,
842510e884cSFrank Schaefer 		 le16_to_cpu(dev_config->string1),
843510e884cSFrank Schaefer 		 le16_to_cpu(dev_config->string2),
844510e884cSFrank Schaefer 		 le16_to_cpu(dev_config->string3));
8450c0d06caSMauro Carvalho Chehab 
8460c0d06caSMauro Carvalho Chehab 	return 0;
847510e884cSFrank Schaefer 
848510e884cSFrank Schaefer error:
849510e884cSFrank Schaefer 	kfree(data);
850510e884cSFrank Schaefer 	return err;
8510c0d06caSMauro Carvalho Chehab }
8520c0d06caSMauro Carvalho Chehab 
8530c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
8540c0d06caSMauro Carvalho Chehab 
8550c0d06caSMauro Carvalho Chehab /*
8560c0d06caSMauro Carvalho Chehab  * functionality()
8570c0d06caSMauro Carvalho Chehab  */
858aab3125cSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *i2c_adap)
8590c0d06caSMauro Carvalho Chehab {
860aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
861aab3125cSMauro Carvalho Chehab 
862a3ea4bf9SFrank Schaefer 	if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) ||
863a3ea4bf9SFrank Schaefer 	    (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) {
864a3ea4bf9SFrank Schaefer 		return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
865a3ea4bf9SFrank Schaefer 	} else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)  {
866a3ea4bf9SFrank Schaefer 		return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) &
867a3ea4bf9SFrank Schaefer 			~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
868a3ea4bf9SFrank Schaefer 	}
869a3ea4bf9SFrank Schaefer 
870a3ea4bf9SFrank Schaefer 	WARN(1, "Unknown i2c bus algorithm.\n");
871a3ea4bf9SFrank Schaefer 	return 0;
8720c0d06caSMauro Carvalho Chehab }
8730c0d06caSMauro Carvalho Chehab 
87478f2c50bSJulia Lawall static const struct i2c_algorithm em28xx_algo = {
8750c0d06caSMauro Carvalho Chehab 	.master_xfer   = em28xx_i2c_xfer,
8760c0d06caSMauro Carvalho Chehab 	.functionality = functionality,
8770c0d06caSMauro Carvalho Chehab };
8780c0d06caSMauro Carvalho Chehab 
879*6843868fSBhumika Goyal static const struct i2c_adapter em28xx_adap_template = {
8800c0d06caSMauro Carvalho Chehab 	.owner = THIS_MODULE,
8810c0d06caSMauro Carvalho Chehab 	.name = "em28xx",
8820c0d06caSMauro Carvalho Chehab 	.algo = &em28xx_algo,
8830c0d06caSMauro Carvalho Chehab };
8840c0d06caSMauro Carvalho Chehab 
8850c0d06caSMauro Carvalho Chehab static struct i2c_client em28xx_client_template = {
8860c0d06caSMauro Carvalho Chehab 	.name = "em28xx internal",
8870c0d06caSMauro Carvalho Chehab };
8880c0d06caSMauro Carvalho Chehab 
8890c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
8900c0d06caSMauro Carvalho Chehab 
8910c0d06caSMauro Carvalho Chehab /*
8920c0d06caSMauro Carvalho Chehab  * i2c_devs
8930c0d06caSMauro Carvalho Chehab  * incomplete list of known devices
8940c0d06caSMauro Carvalho Chehab  */
8950c0d06caSMauro Carvalho Chehab static char *i2c_devs[128] = {
8969aa785b1SWilson Michaels        [0x1c >> 1] = "lgdt330x",
8970b3966e4SFrank Schaefer 	[0x3e >> 1] = "remote IR sensor",
8980c0d06caSMauro Carvalho Chehab 	[0x4a >> 1] = "saa7113h",
8990c0d06caSMauro Carvalho Chehab 	[0x52 >> 1] = "drxk",
9000c0d06caSMauro Carvalho Chehab 	[0x60 >> 1] = "remote IR sensor",
9010c0d06caSMauro Carvalho Chehab 	[0x8e >> 1] = "remote IR sensor",
9020c0d06caSMauro Carvalho Chehab 	[0x86 >> 1] = "tda9887",
9030c0d06caSMauro Carvalho Chehab 	[0x80 >> 1] = "msp34xx",
9040c0d06caSMauro Carvalho Chehab 	[0x88 >> 1] = "msp34xx",
9050c0d06caSMauro Carvalho Chehab 	[0xa0 >> 1] = "eeprom",
9060c0d06caSMauro Carvalho Chehab 	[0xb0 >> 1] = "tda9874",
9070c0d06caSMauro Carvalho Chehab 	[0xb8 >> 1] = "tvp5150a",
9080c0d06caSMauro Carvalho Chehab 	[0xba >> 1] = "webcam sensor or tvp5150a",
9090c0d06caSMauro Carvalho Chehab 	[0xc0 >> 1] = "tuner (analog)",
9100c0d06caSMauro Carvalho Chehab 	[0xc2 >> 1] = "tuner (analog)",
9110c0d06caSMauro Carvalho Chehab 	[0xc4 >> 1] = "tuner (analog)",
9120c0d06caSMauro Carvalho Chehab 	[0xc6 >> 1] = "tuner (analog)",
9130c0d06caSMauro Carvalho Chehab };
9140c0d06caSMauro Carvalho Chehab 
9150c0d06caSMauro Carvalho Chehab /*
9160c0d06caSMauro Carvalho Chehab  * do_i2c_scan()
9170c0d06caSMauro Carvalho Chehab  * check i2c address range for devices
9180c0d06caSMauro Carvalho Chehab  */
919aab3125cSMauro Carvalho Chehab void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus)
9200c0d06caSMauro Carvalho Chehab {
9210c0d06caSMauro Carvalho Chehab 	u8 i2c_devicelist[128];
9220c0d06caSMauro Carvalho Chehab 	unsigned char buf;
9230c0d06caSMauro Carvalho Chehab 	int i, rc;
9240c0d06caSMauro Carvalho Chehab 
9250c0d06caSMauro Carvalho Chehab 	memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
9260c0d06caSMauro Carvalho Chehab 
9270c0d06caSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
928aab3125cSMauro Carvalho Chehab 		dev->i2c_client[bus].addr = i;
929aab3125cSMauro Carvalho Chehab 		rc = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
9300c0d06caSMauro Carvalho Chehab 		if (rc < 0)
9310c0d06caSMauro Carvalho Chehab 			continue;
9320c0d06caSMauro Carvalho Chehab 		i2c_devicelist[i] = i;
93329b05e22SMauro Carvalho Chehab 		dev_info(&dev->intf->dev,
934ce8591ffSMauro Carvalho Chehab 			 "found i2c device @ 0x%x on bus %d [%s]\n",
935aab3125cSMauro Carvalho Chehab 			 i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???");
9360c0d06caSMauro Carvalho Chehab 	}
9370c0d06caSMauro Carvalho Chehab 
938aab3125cSMauro Carvalho Chehab 	if (bus == dev->def_i2c_bus)
9390c0d06caSMauro Carvalho Chehab 		dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
9400c0d06caSMauro Carvalho Chehab 						ARRAY_SIZE(i2c_devicelist), 32);
9410c0d06caSMauro Carvalho Chehab }
9420c0d06caSMauro Carvalho Chehab 
9430c0d06caSMauro Carvalho Chehab /*
9440c0d06caSMauro Carvalho Chehab  * em28xx_i2c_register()
9450c0d06caSMauro Carvalho Chehab  * register i2c bus
9460c0d06caSMauro Carvalho Chehab  */
947a3ea4bf9SFrank Schaefer int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
948a3ea4bf9SFrank Schaefer 			enum em28xx_i2c_algo_type algo_type)
9490c0d06caSMauro Carvalho Chehab {
9500c0d06caSMauro Carvalho Chehab 	int retval;
9510c0d06caSMauro Carvalho Chehab 
9520c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
9530c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
9540c0d06caSMauro Carvalho Chehab 
955aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
956aab3125cSMauro Carvalho Chehab 		return -ENODEV;
957aab3125cSMauro Carvalho Chehab 
958aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus] = em28xx_adap_template;
95929b05e22SMauro Carvalho Chehab 	dev->i2c_adap[bus].dev.parent = &dev->intf->dev;
96029b05e22SMauro Carvalho Chehab 	strcpy(dev->i2c_adap[bus].name, dev_name(&dev->intf->dev));
961aab3125cSMauro Carvalho Chehab 
962aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].bus = bus;
963a3ea4bf9SFrank Schaefer 	dev->i2c_bus[bus].algo_type = algo_type;
964aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].dev = dev;
965aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus];
966aab3125cSMauro Carvalho Chehab 
967aab3125cSMauro Carvalho Chehab 	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
9680c0d06caSMauro Carvalho Chehab 	if (retval < 0) {
96929b05e22SMauro Carvalho Chehab 		dev_err(&dev->intf->dev,
970ce8591ffSMauro Carvalho Chehab 			"%s: i2c_add_adapter failed! retval [%d]\n",
9710c0d06caSMauro Carvalho Chehab 			__func__, retval);
9720c0d06caSMauro Carvalho Chehab 		return retval;
9730c0d06caSMauro Carvalho Chehab 	}
9740c0d06caSMauro Carvalho Chehab 
975aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus] = em28xx_client_template;
976aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].adapter = &dev->i2c_adap[bus];
9770c0d06caSMauro Carvalho Chehab 
978aab3125cSMauro Carvalho Chehab 	/* Up to now, all eeproms are at bus 0 */
979aab3125cSMauro Carvalho Chehab 	if (!bus) {
980aab3125cSMauro Carvalho Chehab 		retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
9810c0d06caSMauro Carvalho Chehab 		if ((retval < 0) && (retval != -ENODEV)) {
98229b05e22SMauro Carvalho Chehab 			dev_err(&dev->intf->dev,
983ce8591ffSMauro Carvalho Chehab 				"%s: em28xx_i2_eeprom failed! retval [%d]\n",
9840c0d06caSMauro Carvalho Chehab 				__func__, retval);
9850c0d06caSMauro Carvalho Chehab 		}
986aab3125cSMauro Carvalho Chehab 	}
9870c0d06caSMauro Carvalho Chehab 
9880c0d06caSMauro Carvalho Chehab 	if (i2c_scan)
989aab3125cSMauro Carvalho Chehab 		em28xx_do_i2c_scan(dev, bus);
9900c0d06caSMauro Carvalho Chehab 
9910c0d06caSMauro Carvalho Chehab 	return 0;
9920c0d06caSMauro Carvalho Chehab }
9930c0d06caSMauro Carvalho Chehab 
9940c0d06caSMauro Carvalho Chehab /*
9950c0d06caSMauro Carvalho Chehab  * em28xx_i2c_unregister()
9960c0d06caSMauro Carvalho Chehab  * unregister i2c_bus
9970c0d06caSMauro Carvalho Chehab  */
998aab3125cSMauro Carvalho Chehab int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus)
9990c0d06caSMauro Carvalho Chehab {
1000aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
1001aab3125cSMauro Carvalho Chehab 		return -ENODEV;
1002aab3125cSMauro Carvalho Chehab 
1003aab3125cSMauro Carvalho Chehab 	i2c_del_adapter(&dev->i2c_adap[bus]);
10040c0d06caSMauro Carvalho Chehab 	return 0;
10050c0d06caSMauro Carvalho Chehab }
1006