xref: /openbmc/linux/drivers/media/usb/em28xx/em28xx-i2c.c (revision d845fb3ae5b97bda8810f450030c061b49a0b91b)
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 
250c0d06caSMauro Carvalho Chehab #include <linux/module.h>
260c0d06caSMauro Carvalho Chehab #include <linux/kernel.h>
270c0d06caSMauro Carvalho Chehab #include <linux/usb.h>
280c0d06caSMauro Carvalho Chehab #include <linux/i2c.h>
294b83626aSMauro Carvalho Chehab #include <linux/jiffies.h>
300c0d06caSMauro Carvalho Chehab 
310c0d06caSMauro Carvalho Chehab #include "em28xx.h"
320c0d06caSMauro Carvalho Chehab #include "tuner-xc2028.h"
330c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h>
340c0d06caSMauro Carvalho Chehab #include <media/tuner.h>
350c0d06caSMauro Carvalho Chehab 
360c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
370c0d06caSMauro Carvalho Chehab 
380c0d06caSMauro Carvalho Chehab static unsigned int i2c_scan;
390c0d06caSMauro Carvalho Chehab module_param(i2c_scan, int, 0444);
400c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
410c0d06caSMauro Carvalho Chehab 
420c0d06caSMauro Carvalho Chehab static unsigned int i2c_debug;
430c0d06caSMauro Carvalho Chehab module_param(i2c_debug, int, 0644);
4450f0a9dfSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug, "i2c debug message level (1: normal debug, 2: show I2C transfers)");
450c0d06caSMauro Carvalho Chehab 
460c0d06caSMauro Carvalho Chehab /*
47f5ae371aSFrank Schaefer  * em2800_i2c_send_bytes()
48f5ae371aSFrank Schaefer  * send up to 4 bytes to the em2800 i2c device
490c0d06caSMauro Carvalho Chehab  */
50f5ae371aSFrank Schaefer static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
510c0d06caSMauro Carvalho Chehab {
52d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
530c0d06caSMauro Carvalho Chehab 	int ret;
54a6bad040SFrank Schaefer 	u8 b2[6];
55f5ae371aSFrank Schaefer 
56f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
57f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
58f5ae371aSFrank Schaefer 
590c0d06caSMauro Carvalho Chehab 	BUG_ON(len < 1 || len > 4);
600c0d06caSMauro Carvalho Chehab 	b2[5] = 0x80 + len - 1;
610c0d06caSMauro Carvalho Chehab 	b2[4] = addr;
620c0d06caSMauro Carvalho Chehab 	b2[3] = buf[0];
630c0d06caSMauro Carvalho Chehab 	if (len > 1)
640c0d06caSMauro Carvalho Chehab 		b2[2] = buf[1];
650c0d06caSMauro Carvalho Chehab 	if (len > 2)
660c0d06caSMauro Carvalho Chehab 		b2[1] = buf[2];
670c0d06caSMauro Carvalho Chehab 	if (len > 3)
680c0d06caSMauro Carvalho Chehab 		b2[0] = buf[3];
690c0d06caSMauro Carvalho Chehab 
702fcc82d8SFrank Schaefer 	/* trigger write */
710c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
720c0d06caSMauro Carvalho Chehab 	if (ret != 2 + len) {
73d230d5adSFrank Schaefer 		em28xx_warn("failed to trigger write to i2c address 0x%x (error=%i)\n",
74d230d5adSFrank Schaefer 			    addr, ret);
7545f04e82SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
760c0d06caSMauro Carvalho Chehab 	}
772fcc82d8SFrank Schaefer 	/* wait for completion */
784b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
790c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
804b83626aSMauro Carvalho Chehab 		if (ret == 0x80 + len - 1)
810c0d06caSMauro Carvalho Chehab 			return len;
824b83626aSMauro Carvalho Chehab 		if (ret == 0x94 + len - 1) {
83*d845fb3aSMauro Carvalho Chehab 			if (i2c_debug == 1)
84*d845fb3aSMauro Carvalho Chehab 				em28xx_warn("R05 returned 0x%02x: I2C timeout",
85*d845fb3aSMauro Carvalho Chehab 					    ret);
86e63b009dSMauro Carvalho Chehab 			return -ENXIO;
874b83626aSMauro Carvalho Chehab 		}
884b83626aSMauro Carvalho Chehab 		if (ret < 0) {
89d230d5adSFrank Schaefer 			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
90d230d5adSFrank Schaefer 				    ret);
9145f04e82SFrank Schaefer 			return ret;
9245f04e82SFrank Schaefer 		}
930c0d06caSMauro Carvalho Chehab 		msleep(5);
940c0d06caSMauro Carvalho Chehab 	}
9550f0a9dfSMauro Carvalho Chehab 	if (i2c_debug)
9645f04e82SFrank Schaefer 		em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
97e63b009dSMauro Carvalho Chehab 	return -ETIMEDOUT;
980c0d06caSMauro Carvalho Chehab }
990c0d06caSMauro Carvalho Chehab 
1000c0d06caSMauro Carvalho Chehab /*
1010c0d06caSMauro Carvalho Chehab  * em2800_i2c_recv_bytes()
1022fcc82d8SFrank Schaefer  * read up to 4 bytes from the em2800 i2c device
1030c0d06caSMauro Carvalho Chehab  */
104a6bad040SFrank Schaefer static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
1050c0d06caSMauro Carvalho Chehab {
106d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
1072fcc82d8SFrank Schaefer 	u8 buf2[4];
1080c0d06caSMauro Carvalho Chehab 	int ret;
1092fcc82d8SFrank Schaefer 	int i;
110f5ae371aSFrank Schaefer 
111f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
112f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
113f5ae371aSFrank Schaefer 
1142fcc82d8SFrank Schaefer 	/* trigger read */
1152fcc82d8SFrank Schaefer 	buf2[1] = 0x84 + len - 1;
1162fcc82d8SFrank Schaefer 	buf2[0] = addr;
1172fcc82d8SFrank Schaefer 	ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
1182fcc82d8SFrank Schaefer 	if (ret != 2) {
119d230d5adSFrank Schaefer 		em28xx_warn("failed to trigger read from i2c address 0x%x (error=%i)\n",
120d230d5adSFrank Schaefer 			    addr, ret);
1212fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1222fcc82d8SFrank Schaefer 	}
1232fcc82d8SFrank Schaefer 
1242fcc82d8SFrank Schaefer 	/* wait for completion */
1254b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
1262fcc82d8SFrank Schaefer 		ret = dev->em28xx_read_reg(dev, 0x05);
1274b83626aSMauro Carvalho Chehab 		if (ret == 0x84 + len - 1)
1282fcc82d8SFrank Schaefer 			break;
1294b83626aSMauro Carvalho Chehab 		if (ret == 0x94 + len - 1) {
130*d845fb3aSMauro Carvalho Chehab 			if (i2c_debug == 1)
131*d845fb3aSMauro Carvalho Chehab 				em28xx_warn("R05 returned 0x%02x: I2C timeout",
132*d845fb3aSMauro Carvalho Chehab 					    ret);
133e63b009dSMauro Carvalho Chehab 			return -ENXIO;
1344b83626aSMauro Carvalho Chehab 		}
1354b83626aSMauro Carvalho Chehab 		if (ret < 0) {
136d230d5adSFrank Schaefer 			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
137d230d5adSFrank Schaefer 				    ret);
1380c0d06caSMauro Carvalho Chehab 			return ret;
1390c0d06caSMauro Carvalho Chehab 		}
1402fcc82d8SFrank Schaefer 		msleep(5);
1412fcc82d8SFrank Schaefer 	}
14250f0a9dfSMauro Carvalho Chehab 	if (ret != 0x84 + len - 1) {
14350f0a9dfSMauro Carvalho Chehab 		if (i2c_debug)
14450f0a9dfSMauro Carvalho Chehab 			em28xx_warn("read from i2c device at 0x%x timed out\n",
14550f0a9dfSMauro Carvalho Chehab 				    addr);
14650f0a9dfSMauro Carvalho Chehab 	}
1472fcc82d8SFrank Schaefer 
1482fcc82d8SFrank Schaefer 	/* get the received message */
1492fcc82d8SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
1502fcc82d8SFrank Schaefer 	if (ret != len) {
151d230d5adSFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
152d230d5adSFrank Schaefer 			    addr, ret);
1532fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1542fcc82d8SFrank Schaefer 	}
1552fcc82d8SFrank Schaefer 	for (i = 0; i < len; i++)
1562fcc82d8SFrank Schaefer 		buf[i] = buf2[len - 1 - i];
1572fcc82d8SFrank Schaefer 
1580c0d06caSMauro Carvalho Chehab 	return ret;
1590c0d06caSMauro Carvalho Chehab }
1602fcc82d8SFrank Schaefer 
1612fcc82d8SFrank Schaefer /*
1622fcc82d8SFrank Schaefer  * em2800_i2c_check_for_device()
1632fcc82d8SFrank Schaefer  * check if there is an i2c device at the supplied address
1642fcc82d8SFrank Schaefer  */
1652fcc82d8SFrank Schaefer static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
1662fcc82d8SFrank Schaefer {
1672fcc82d8SFrank Schaefer 	u8 buf;
1682fcc82d8SFrank Schaefer 	int ret;
1692fcc82d8SFrank Schaefer 
1702fcc82d8SFrank Schaefer 	ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1);
1712fcc82d8SFrank Schaefer 	if (ret == 1)
1722fcc82d8SFrank Schaefer 		return 0;
1732fcc82d8SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
1740c0d06caSMauro Carvalho Chehab }
1750c0d06caSMauro Carvalho Chehab 
1760c0d06caSMauro Carvalho Chehab /*
1770c0d06caSMauro Carvalho Chehab  * em28xx_i2c_send_bytes()
1780c0d06caSMauro Carvalho Chehab  */
179a6bad040SFrank Schaefer static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
180a6bad040SFrank Schaefer 				 u16 len, int stop)
1810c0d06caSMauro Carvalho Chehab {
182d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
1834b83626aSMauro Carvalho Chehab 	int ret;
1840c0d06caSMauro Carvalho Chehab 
185f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
186f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
187fa74aca3SFrank Schaefer 	/*
188fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
189fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
190fa74aca3SFrank Schaefer 	 */
191f5ae371aSFrank Schaefer 
19245f04e82SFrank Schaefer 	/* Write to i2c device */
19345f04e82SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
19445f04e82SFrank Schaefer 	if (ret != len) {
19545f04e82SFrank Schaefer 		if (ret < 0) {
196d230d5adSFrank Schaefer 			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
197d230d5adSFrank Schaefer 				    addr, ret);
19845f04e82SFrank Schaefer 			return ret;
19945f04e82SFrank Schaefer 		} else {
200d230d5adSFrank Schaefer 			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
20145f04e82SFrank Schaefer 				    len, addr, ret);
20245f04e82SFrank Schaefer 			return -EIO;
20345f04e82SFrank Schaefer 		}
20445f04e82SFrank Schaefer 	}
2050c0d06caSMauro Carvalho Chehab 
2064b83626aSMauro Carvalho Chehab 	/* wait for completion */
2074b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
2080c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
2094b83626aSMauro Carvalho Chehab 		if (ret == 0) /* success */
21045f04e82SFrank Schaefer 			return len;
2114b83626aSMauro Carvalho Chehab 		if (ret == 0x10) {
212*d845fb3aSMauro Carvalho Chehab 			if (i2c_debug == 1)
213*d845fb3aSMauro Carvalho Chehab 				em28xx_warn("I2C transfer timeout on writing to addr 0x%02x",
214*d845fb3aSMauro Carvalho Chehab 					    addr);
215e63b009dSMauro Carvalho Chehab 			return -ENXIO;
2164b83626aSMauro Carvalho Chehab 		}
2174b83626aSMauro Carvalho Chehab 		if (ret < 0) {
2184b83626aSMauro Carvalho Chehab 			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
219d230d5adSFrank Schaefer 				    ret);
22045f04e82SFrank Schaefer 			return ret;
2210c0d06caSMauro Carvalho Chehab 		}
22245f04e82SFrank Schaefer 		msleep(5);
223fa74aca3SFrank Schaefer 		/*
224fa74aca3SFrank Schaefer 		 * NOTE: do we really have to wait for success ?
225fa74aca3SFrank Schaefer 		 * Never seen anything else than 0x00 or 0x10
226fa74aca3SFrank Schaefer 		 * (even with high payload) ...
227fa74aca3SFrank Schaefer 		 */
22845f04e82SFrank Schaefer 	}
22950f0a9dfSMauro Carvalho Chehab 	if (i2c_debug)
23050f0a9dfSMauro Carvalho Chehab 		em28xx_warn("write to i2c device at 0x%x timed out (status=%i)\n",
23150f0a9dfSMauro Carvalho Chehab 			    addr, ret);
232e63b009dSMauro Carvalho Chehab 	return -ETIMEDOUT;
2330c0d06caSMauro Carvalho Chehab }
2340c0d06caSMauro Carvalho Chehab 
2350c0d06caSMauro Carvalho Chehab /*
2360c0d06caSMauro Carvalho Chehab  * em28xx_i2c_recv_bytes()
2370c0d06caSMauro Carvalho Chehab  * read a byte from the i2c device
2380c0d06caSMauro Carvalho Chehab  */
239a6bad040SFrank Schaefer static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
2400c0d06caSMauro Carvalho Chehab {
2410c0d06caSMauro Carvalho Chehab 	int ret;
242f5ae371aSFrank Schaefer 
243f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
244f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
245fa74aca3SFrank Schaefer 	/*
246fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
247fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
248fa74aca3SFrank Schaefer 	 */
249f5ae371aSFrank Schaefer 
25045f04e82SFrank Schaefer 	/* Read data from i2c device */
2510c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
2520c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
2537f6301d1SFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
2547f6301d1SFrank Schaefer 			    addr, ret);
25545f04e82SFrank Schaefer 		return ret;
25645f04e82SFrank Schaefer 	}
257fa74aca3SFrank Schaefer 	/*
258fa74aca3SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
2597f6301d1SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
2607f6301d1SFrank Schaefer 	 * specified slave address before AND no device is present at the
2617f6301d1SFrank Schaefer 	 * requested slave address.
262e63b009dSMauro Carvalho Chehab 	 * Anyway, the next check will fail with -ENXIO in this case, so avoid
2637f6301d1SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
2647f6301d1SFrank Schaefer 	 */
26545f04e82SFrank Schaefer 
26645f04e82SFrank Schaefer 	/* Check success of the i2c operation */
26745f04e82SFrank Schaefer 	ret = dev->em28xx_read_reg(dev, 0x05);
2684b83626aSMauro Carvalho Chehab 	if (ret == 0) /* success */
2694b83626aSMauro Carvalho Chehab 		return len;
27045f04e82SFrank Schaefer 	if (ret < 0) {
2714b83626aSMauro Carvalho Chehab 		em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
272d230d5adSFrank Schaefer 			    ret);
2730c0d06caSMauro Carvalho Chehab 		return ret;
2740c0d06caSMauro Carvalho Chehab 	}
275*d845fb3aSMauro Carvalho Chehab 	if (ret == 0x10) {
276*d845fb3aSMauro Carvalho Chehab 		if (i2c_debug == 1)
277*d845fb3aSMauro Carvalho Chehab 			em28xx_warn("I2C transfer timeout on writing to addr 0x%02x",
278*d845fb3aSMauro Carvalho Chehab 				    addr);
279e63b009dSMauro Carvalho Chehab 		return -ENXIO;
280*d845fb3aSMauro Carvalho Chehab 	}
2814b83626aSMauro Carvalho Chehab 
28245f04e82SFrank Schaefer 	em28xx_warn("unknown i2c error (status=%i)\n", ret);
283e63b009dSMauro Carvalho Chehab 	return -ETIMEDOUT;
28445f04e82SFrank Schaefer }
2850c0d06caSMauro Carvalho Chehab 
2860c0d06caSMauro Carvalho Chehab /*
2870c0d06caSMauro Carvalho Chehab  * em28xx_i2c_check_for_device()
2880c0d06caSMauro Carvalho Chehab  * check if there is a i2c_device at the supplied address
2890c0d06caSMauro Carvalho Chehab  */
290a6bad040SFrank Schaefer static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
2910c0d06caSMauro Carvalho Chehab {
2920c0d06caSMauro Carvalho Chehab 	int ret;
29345f04e82SFrank Schaefer 	u8 buf;
2940c0d06caSMauro Carvalho Chehab 
29545f04e82SFrank Schaefer 	ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1);
29645f04e82SFrank Schaefer 	if (ret == 1)
2970c0d06caSMauro Carvalho Chehab 		return 0;
29845f04e82SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
2990c0d06caSMauro Carvalho Chehab }
3000c0d06caSMauro Carvalho Chehab 
3010c0d06caSMauro Carvalho Chehab /*
302a3ea4bf9SFrank Schaefer  * em25xx_bus_B_send_bytes
303a3ea4bf9SFrank Schaefer  * write bytes to the i2c device
304a3ea4bf9SFrank Schaefer  */
305a3ea4bf9SFrank Schaefer static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
306a3ea4bf9SFrank Schaefer 				   u16 len)
307a3ea4bf9SFrank Schaefer {
308a3ea4bf9SFrank Schaefer 	int ret;
309a3ea4bf9SFrank Schaefer 
310a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
311a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
312a3ea4bf9SFrank Schaefer 	/*
313a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
314a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
315a3ea4bf9SFrank Schaefer 	 */
316a3ea4bf9SFrank Schaefer 
317a3ea4bf9SFrank Schaefer 	/* Set register and write value */
318a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len);
319a3ea4bf9SFrank Schaefer 	if (ret != len) {
320a3ea4bf9SFrank Schaefer 		if (ret < 0) {
321a3ea4bf9SFrank Schaefer 			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
322a3ea4bf9SFrank Schaefer 				    addr, ret);
323a3ea4bf9SFrank Schaefer 			return ret;
324a3ea4bf9SFrank Schaefer 		} else {
325a3ea4bf9SFrank Schaefer 			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
326a3ea4bf9SFrank Schaefer 				    len, addr, ret);
327a3ea4bf9SFrank Schaefer 			return -EIO;
328a3ea4bf9SFrank Schaefer 		}
329a3ea4bf9SFrank Schaefer 	}
330a3ea4bf9SFrank Schaefer 	/* Check success */
331a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
332a3ea4bf9SFrank Schaefer 	/*
333a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
334a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
335a3ea4bf9SFrank Schaefer 	 */
336a3ea4bf9SFrank Schaefer 	if (!ret)
337a3ea4bf9SFrank Schaefer 		return len;
338*d845fb3aSMauro Carvalho Chehab 	else if (ret > 0) {
339*d845fb3aSMauro Carvalho Chehab 		if (i2c_debug == 1)
340*d845fb3aSMauro Carvalho Chehab 			em28xx_warn("Bus B R08 returned 0x%02x: I2C timeout",
341*d845fb3aSMauro Carvalho Chehab 				    ret);
342e63b009dSMauro Carvalho Chehab 		return -ENXIO;
343*d845fb3aSMauro Carvalho Chehab 	}
344a3ea4bf9SFrank Schaefer 
345a3ea4bf9SFrank Schaefer 	return ret;
346a3ea4bf9SFrank Schaefer 	/*
347a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
348a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
349a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
350a3ea4bf9SFrank Schaefer 	 */
351a3ea4bf9SFrank Schaefer }
352a3ea4bf9SFrank Schaefer 
353a3ea4bf9SFrank Schaefer /*
354a3ea4bf9SFrank Schaefer  * em25xx_bus_B_recv_bytes
355a3ea4bf9SFrank Schaefer  * read bytes from the i2c device
356a3ea4bf9SFrank Schaefer  */
357a3ea4bf9SFrank Schaefer static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf,
358a3ea4bf9SFrank Schaefer 				   u16 len)
359a3ea4bf9SFrank Schaefer {
360a3ea4bf9SFrank Schaefer 	int ret;
361a3ea4bf9SFrank Schaefer 
362a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
363a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
364a3ea4bf9SFrank Schaefer 	/*
365a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
366a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
367a3ea4bf9SFrank Schaefer 	 */
368a3ea4bf9SFrank Schaefer 
369a3ea4bf9SFrank Schaefer 	/* Read value */
370a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len);
371a3ea4bf9SFrank Schaefer 	if (ret < 0) {
372a3ea4bf9SFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
373a3ea4bf9SFrank Schaefer 			    addr, ret);
374a3ea4bf9SFrank Schaefer 		return ret;
375a3ea4bf9SFrank Schaefer 	}
376a3ea4bf9SFrank Schaefer 	/*
377a3ea4bf9SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
378a3ea4bf9SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
379a3ea4bf9SFrank Schaefer 	 * specified slave address before AND no device is present at the
380a3ea4bf9SFrank Schaefer 	 * requested slave address.
381e63b009dSMauro Carvalho Chehab 	 * Anyway, the next check will fail with -ENXIO in this case, so avoid
382a3ea4bf9SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
383a3ea4bf9SFrank Schaefer 	 */
384a3ea4bf9SFrank Schaefer 
385a3ea4bf9SFrank Schaefer 	/* Check success */
386a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
387a3ea4bf9SFrank Schaefer 	/*
388a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
389a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
390a3ea4bf9SFrank Schaefer 	 */
391a3ea4bf9SFrank Schaefer 	if (!ret)
392a3ea4bf9SFrank Schaefer 		return len;
393*d845fb3aSMauro Carvalho Chehab 	else if (ret > 0) {
394*d845fb3aSMauro Carvalho Chehab 		if (i2c_debug == 1)
395*d845fb3aSMauro Carvalho Chehab 			em28xx_warn("Bus B R08 returned 0x%02x: I2C timeout",
396*d845fb3aSMauro Carvalho Chehab 				    ret);
397e63b009dSMauro Carvalho Chehab 		return -ENXIO;
398*d845fb3aSMauro Carvalho Chehab 	}
399a3ea4bf9SFrank Schaefer 
400a3ea4bf9SFrank Schaefer 	return ret;
401a3ea4bf9SFrank Schaefer 	/*
402a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
403a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
404a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
405a3ea4bf9SFrank Schaefer 	 */
406a3ea4bf9SFrank Schaefer }
407a3ea4bf9SFrank Schaefer 
408a3ea4bf9SFrank Schaefer /*
409a3ea4bf9SFrank Schaefer  * em25xx_bus_B_check_for_device()
410a3ea4bf9SFrank Schaefer  * check if there is a i2c device at the supplied address
411a3ea4bf9SFrank Schaefer  */
412a3ea4bf9SFrank Schaefer static int em25xx_bus_B_check_for_device(struct em28xx *dev, u16 addr)
413a3ea4bf9SFrank Schaefer {
414a3ea4bf9SFrank Schaefer 	u8 buf;
415a3ea4bf9SFrank Schaefer 	int ret;
416a3ea4bf9SFrank Schaefer 
417a3ea4bf9SFrank Schaefer 	ret = em25xx_bus_B_recv_bytes(dev, addr, &buf, 1);
418a3ea4bf9SFrank Schaefer 	if (ret < 0)
419a3ea4bf9SFrank Schaefer 		return ret;
420a3ea4bf9SFrank Schaefer 
421a3ea4bf9SFrank Schaefer 	return 0;
422a3ea4bf9SFrank Schaefer 	/*
423a3ea4bf9SFrank Schaefer 	 * NOTE: With chips which do not support this operation,
424a3ea4bf9SFrank Schaefer 	 * it seems to succeed ALWAYS ! (even if no device connected)
425a3ea4bf9SFrank Schaefer 	 */
426a3ea4bf9SFrank Schaefer }
427a3ea4bf9SFrank Schaefer 
428a3ea4bf9SFrank Schaefer static inline int i2c_check_for_device(struct em28xx_i2c_bus *i2c_bus, u16 addr)
429a3ea4bf9SFrank Schaefer {
430a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
431a3ea4bf9SFrank Schaefer 	int rc = -EOPNOTSUPP;
432a3ea4bf9SFrank Schaefer 
433a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
434a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_check_for_device(dev, addr);
435a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
436a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_check_for_device(dev, addr);
437a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
438a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_check_for_device(dev, addr);
439a3ea4bf9SFrank Schaefer 	return rc;
440a3ea4bf9SFrank Schaefer }
441a3ea4bf9SFrank Schaefer 
442a3ea4bf9SFrank Schaefer static inline int i2c_recv_bytes(struct em28xx_i2c_bus *i2c_bus,
443a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg)
444a3ea4bf9SFrank Schaefer {
445a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
446a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
44750f0a9dfSMauro Carvalho Chehab 	int rc = -EOPNOTSUPP;
448a3ea4bf9SFrank Schaefer 
449a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
450a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
451a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
452a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
453a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
454a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len);
455a3ea4bf9SFrank Schaefer 	return rc;
456a3ea4bf9SFrank Schaefer }
457a3ea4bf9SFrank Schaefer 
458a3ea4bf9SFrank Schaefer static inline int i2c_send_bytes(struct em28xx_i2c_bus *i2c_bus,
459a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg, int stop)
460a3ea4bf9SFrank Schaefer {
461a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
462a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
46350f0a9dfSMauro Carvalho Chehab 	int rc = -EOPNOTSUPP;
464a3ea4bf9SFrank Schaefer 
465a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
466a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop);
467a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
468a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_send_bytes(dev, addr, msg.buf, msg.len);
469a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
470a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_send_bytes(dev, addr, msg.buf, msg.len);
471a3ea4bf9SFrank Schaefer 	return rc;
472a3ea4bf9SFrank Schaefer }
473a3ea4bf9SFrank Schaefer 
474a3ea4bf9SFrank Schaefer /*
4750c0d06caSMauro Carvalho Chehab  * em28xx_i2c_xfer()
4760c0d06caSMauro Carvalho Chehab  * the main i2c transfer function
4770c0d06caSMauro Carvalho Chehab  */
4780c0d06caSMauro Carvalho Chehab static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
4790c0d06caSMauro Carvalho Chehab 			   struct i2c_msg msgs[], int num)
4800c0d06caSMauro Carvalho Chehab {
481aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
482aab3125cSMauro Carvalho Chehab 	struct em28xx *dev = i2c_bus->dev;
483aab3125cSMauro Carvalho Chehab 	unsigned bus = i2c_bus->bus;
484a3ea4bf9SFrank Schaefer 	int addr, rc, i;
4853190fbeeSMauro Carvalho Chehab 	u8 reg;
4860c0d06caSMauro Carvalho Chehab 
487aab3125cSMauro Carvalho Chehab 	rc = rt_mutex_trylock(&dev->i2c_bus_lock);
488aab3125cSMauro Carvalho Chehab 	if (rc < 0)
489aab3125cSMauro Carvalho Chehab 		return rc;
490aab3125cSMauro Carvalho Chehab 
491aab3125cSMauro Carvalho Chehab 	/* Switch I2C bus if needed */
492a3ea4bf9SFrank Schaefer 	if (bus != dev->cur_i2c_bus &&
493a3ea4bf9SFrank Schaefer 	    i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) {
494aab3125cSMauro Carvalho Chehab 		if (bus == 1)
4953190fbeeSMauro Carvalho Chehab 			reg = EM2874_I2C_SECONDARY_BUS_SELECT;
496aab3125cSMauro Carvalho Chehab 		else
4973190fbeeSMauro Carvalho Chehab 			reg = 0;
4983190fbeeSMauro Carvalho Chehab 		em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg,
4993190fbeeSMauro Carvalho Chehab 				      EM2874_I2C_SECONDARY_BUS_SELECT);
500aab3125cSMauro Carvalho Chehab 		dev->cur_i2c_bus = bus;
501aab3125cSMauro Carvalho Chehab 	}
502aab3125cSMauro Carvalho Chehab 
503aab3125cSMauro Carvalho Chehab 	if (num <= 0) {
504aab3125cSMauro Carvalho Chehab 		rt_mutex_unlock(&dev->i2c_bus_lock);
5050c0d06caSMauro Carvalho Chehab 		return 0;
506aab3125cSMauro Carvalho Chehab 	}
5070c0d06caSMauro Carvalho Chehab 	for (i = 0; i < num; i++) {
5080c0d06caSMauro Carvalho Chehab 		addr = msgs[i].addr << 1;
50950f0a9dfSMauro Carvalho Chehab 		if (i2c_debug > 1)
510d7a80eaaSFrank Schaefer 			printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:",
511d7a80eaaSFrank Schaefer 			       dev->name, __func__ ,
5120c0d06caSMauro Carvalho Chehab 			       (msgs[i].flags & I2C_M_RD) ? "read" : "write",
513d7a80eaaSFrank Schaefer 			       i == num - 1 ? "stop" : "nonstop",
514d7a80eaaSFrank Schaefer 			       addr, msgs[i].len);
515e63b009dSMauro Carvalho Chehab 		if (!msgs[i].len) {
516e63b009dSMauro Carvalho Chehab 			/*
517e63b009dSMauro Carvalho Chehab 			 * no len: check only for device presence
518e63b009dSMauro Carvalho Chehab 			 * This code is only called during device probe.
519e63b009dSMauro Carvalho Chehab 			 */
520a3ea4bf9SFrank Schaefer 			rc = i2c_check_for_device(i2c_bus, addr);
52150f0a9dfSMauro Carvalho Chehab 			if (rc < 0) {
522e63b009dSMauro Carvalho Chehab 				if (rc == -ENXIO) {
52350f0a9dfSMauro Carvalho Chehab 					if (i2c_debug > 1)
52450f0a9dfSMauro Carvalho Chehab 						printk(KERN_CONT " no device\n");
52550f0a9dfSMauro Carvalho Chehab 					rc = -ENODEV;
52650f0a9dfSMauro Carvalho Chehab 				} else {
52750f0a9dfSMauro Carvalho Chehab 					if (i2c_debug > 1)
52850f0a9dfSMauro Carvalho Chehab 						printk(KERN_CONT " ERROR: %i\n", rc);
52950f0a9dfSMauro Carvalho Chehab 				}
530aab3125cSMauro Carvalho Chehab 				rt_mutex_unlock(&dev->i2c_bus_lock);
53150f0a9dfSMauro Carvalho Chehab 				return rc;
5320c0d06caSMauro Carvalho Chehab 			}
5330c0d06caSMauro Carvalho Chehab 		} else if (msgs[i].flags & I2C_M_RD) {
5340c0d06caSMauro Carvalho Chehab 			/* read bytes */
535a3ea4bf9SFrank Schaefer 			rc = i2c_recv_bytes(i2c_bus, msgs[i]);
53650f0a9dfSMauro Carvalho Chehab 
53750f0a9dfSMauro Carvalho Chehab 			if (i2c_debug > 1 && rc >= 0)
53850f0a9dfSMauro Carvalho Chehab 				printk(KERN_CONT " %*ph",
53950f0a9dfSMauro Carvalho Chehab 				       msgs[i].len, msgs[i].buf);
5400c0d06caSMauro Carvalho Chehab 		} else {
54150f0a9dfSMauro Carvalho Chehab 			if (i2c_debug > 1)
54250f0a9dfSMauro Carvalho Chehab 				printk(KERN_CONT " %*ph",
54350f0a9dfSMauro Carvalho Chehab 				       msgs[i].len, msgs[i].buf);
54450f0a9dfSMauro Carvalho Chehab 
5450c0d06caSMauro Carvalho Chehab 			/* write bytes */
546a3ea4bf9SFrank Schaefer 			rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1);
5470c0d06caSMauro Carvalho Chehab 		}
54845f04e82SFrank Schaefer 		if (rc < 0) {
54950f0a9dfSMauro Carvalho Chehab 			if (i2c_debug > 1)
55050f0a9dfSMauro Carvalho Chehab 				printk(KERN_CONT " ERROR: %i\n", rc);
551aab3125cSMauro Carvalho Chehab 			rt_mutex_unlock(&dev->i2c_bus_lock);
55245f04e82SFrank Schaefer 			return rc;
55345f04e82SFrank Schaefer 		}
55450f0a9dfSMauro Carvalho Chehab 		if (i2c_debug > 1)
55550f0a9dfSMauro Carvalho Chehab 			printk(KERN_CONT "\n");
5560c0d06caSMauro Carvalho Chehab 	}
5570c0d06caSMauro Carvalho Chehab 
558aab3125cSMauro Carvalho Chehab 	rt_mutex_unlock(&dev->i2c_bus_lock);
5590c0d06caSMauro Carvalho Chehab 	return num;
5600c0d06caSMauro Carvalho Chehab }
5610c0d06caSMauro Carvalho Chehab 
562fa74aca3SFrank Schaefer /*
563fa74aca3SFrank Schaefer  * based on linux/sunrpc/svcauth.h and linux/hash.h
5640c0d06caSMauro Carvalho Chehab  * The original hash function returns a different value, if arch is x86_64
5650c0d06caSMauro Carvalho Chehab  * or i386.
5660c0d06caSMauro Carvalho Chehab  */
5670c0d06caSMauro Carvalho Chehab static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
5680c0d06caSMauro Carvalho Chehab {
5690c0d06caSMauro Carvalho Chehab 	unsigned long hash = 0;
5700c0d06caSMauro Carvalho Chehab 	unsigned long l = 0;
5710c0d06caSMauro Carvalho Chehab 	int len = 0;
5720c0d06caSMauro Carvalho Chehab 	unsigned char c;
5730c0d06caSMauro Carvalho Chehab 	do {
5740c0d06caSMauro Carvalho Chehab 		if (len == length) {
5750c0d06caSMauro Carvalho Chehab 			c = (char)len;
5760c0d06caSMauro Carvalho Chehab 			len = -1;
5770c0d06caSMauro Carvalho Chehab 		} else
5780c0d06caSMauro Carvalho Chehab 			c = *buf++;
5790c0d06caSMauro Carvalho Chehab 		l = (l << 8) | c;
5800c0d06caSMauro Carvalho Chehab 		len++;
5810c0d06caSMauro Carvalho Chehab 		if ((len & (32 / 8 - 1)) == 0)
5820c0d06caSMauro Carvalho Chehab 			hash = ((hash^l) * 0x9e370001UL);
5830c0d06caSMauro Carvalho Chehab 	} while (len);
5840c0d06caSMauro Carvalho Chehab 
5850c0d06caSMauro Carvalho Chehab 	return (hash >> (32 - bits)) & 0xffffffffUL;
5860c0d06caSMauro Carvalho Chehab }
5870c0d06caSMauro Carvalho Chehab 
588fa74aca3SFrank Schaefer /*
589fa74aca3SFrank Schaefer  * Helper function to read data blocks from i2c clients with 8 or 16 bit
590fa74aca3SFrank Schaefer  * address width, 8 bit register width and auto incrementation been activated
591fa74aca3SFrank Schaefer  */
592aab3125cSMauro Carvalho Chehab static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
593aab3125cSMauro Carvalho Chehab 				 bool addr_w16, u16 len, u8 *data)
594d832c5b2SFrank Schaefer {
595d832c5b2SFrank Schaefer 	int remain = len, rsize, rsize_max, ret;
596d832c5b2SFrank Schaefer 	u8 buf[2];
597d832c5b2SFrank Schaefer 
598d832c5b2SFrank Schaefer 	/* Sanity check */
599d832c5b2SFrank Schaefer 	if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1))
600d832c5b2SFrank Schaefer 		return -EINVAL;
601d832c5b2SFrank Schaefer 	/* Select address */
602d832c5b2SFrank Schaefer 	buf[0] = addr >> 8;
603d832c5b2SFrank Schaefer 	buf[1] = addr & 0xff;
604aab3125cSMauro Carvalho Chehab 	ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16);
605d832c5b2SFrank Schaefer 	if (ret < 0)
606d832c5b2SFrank Schaefer 		return ret;
607d832c5b2SFrank Schaefer 	/* Read data */
608d832c5b2SFrank Schaefer 	if (dev->board.is_em2800)
609d832c5b2SFrank Schaefer 		rsize_max = 4;
610d832c5b2SFrank Schaefer 	else
611d832c5b2SFrank Schaefer 		rsize_max = 64;
612d832c5b2SFrank Schaefer 	while (remain > 0) {
613d832c5b2SFrank Schaefer 		if (remain > rsize_max)
614d832c5b2SFrank Schaefer 			rsize = rsize_max;
615d832c5b2SFrank Schaefer 		else
616d832c5b2SFrank Schaefer 			rsize = remain;
617d832c5b2SFrank Schaefer 
618aab3125cSMauro Carvalho Chehab 		ret = i2c_master_recv(&dev->i2c_client[bus], data, rsize);
619d832c5b2SFrank Schaefer 		if (ret < 0)
620d832c5b2SFrank Schaefer 			return ret;
621d832c5b2SFrank Schaefer 
622d832c5b2SFrank Schaefer 		remain -= rsize;
623d832c5b2SFrank Schaefer 		data += rsize;
624d832c5b2SFrank Schaefer 	}
625d832c5b2SFrank Schaefer 
626d832c5b2SFrank Schaefer 	return len;
627d832c5b2SFrank Schaefer }
628d832c5b2SFrank Schaefer 
629aab3125cSMauro Carvalho Chehab static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
630aab3125cSMauro Carvalho Chehab 			     u8 **eedata, u16 *eedata_len)
6310c0d06caSMauro Carvalho Chehab {
632510e884cSFrank Schaefer 	const u16 len = 256;
633fa74aca3SFrank Schaefer 	/*
634fa74aca3SFrank Schaefer 	 * FIXME common length/size for bytes to read, to display, hash
635510e884cSFrank Schaefer 	 * calculation and returned device dataset. Simplifies the code a lot,
636fa74aca3SFrank Schaefer 	 * but we might have to deal with multiple sizes in the future !
637fa74aca3SFrank Schaefer 	 */
63850f0a9dfSMauro Carvalho Chehab 	int err;
639510e884cSFrank Schaefer 	struct em28xx_eeprom *dev_config;
640510e884cSFrank Schaefer 	u8 buf, *data;
6410c0d06caSMauro Carvalho Chehab 
642a217968fSFrank Schaefer 	*eedata = NULL;
643510e884cSFrank Schaefer 	*eedata_len = 0;
644a217968fSFrank Schaefer 
645aab3125cSMauro Carvalho Chehab 	/* EEPROM is always on i2c bus 0 on all known devices. */
646aab3125cSMauro Carvalho Chehab 
647aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].addr = 0xa0 >> 1;
6480c0d06caSMauro Carvalho Chehab 
6490c0d06caSMauro Carvalho Chehab 	/* Check if board has eeprom */
650aab3125cSMauro Carvalho Chehab 	err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
6510c0d06caSMauro Carvalho Chehab 	if (err < 0) {
65212d7ce18SFrank Schaefer 		em28xx_info("board has no eeprom\n");
6530c0d06caSMauro Carvalho Chehab 		return -ENODEV;
6540c0d06caSMauro Carvalho Chehab 	}
6550c0d06caSMauro Carvalho Chehab 
656a217968fSFrank Schaefer 	data = kzalloc(len, GFP_KERNEL);
657a217968fSFrank Schaefer 	if (data == NULL)
658a217968fSFrank Schaefer 		return -ENOMEM;
659a217968fSFrank Schaefer 
660d832c5b2SFrank Schaefer 	/* Read EEPROM content */
661aab3125cSMauro Carvalho Chehab 	err = em28xx_i2c_read_block(dev, bus, 0x0000,
662aab3125cSMauro Carvalho Chehab 				    dev->eeprom_addrwidth_16bit,
663a217968fSFrank Schaefer 				    len, data);
664d832c5b2SFrank Schaefer 	if (err != len) {
66512d7ce18SFrank Schaefer 		em28xx_errdev("failed to read eeprom (err=%d)\n", err);
666510e884cSFrank Schaefer 		goto error;
6670c0d06caSMauro Carvalho Chehab 	}
66890271964SFrank Schaefer 
66950f0a9dfSMauro Carvalho Chehab 	if (i2c_debug) {
67087b52439SFrank Schaefer 		/* Display eeprom content */
67150f0a9dfSMauro Carvalho Chehab 		print_hex_dump(KERN_INFO, "eeprom ", DUMP_PREFIX_OFFSET,
67250f0a9dfSMauro Carvalho Chehab 			       16, 1, data, len, true);
67350f0a9dfSMauro Carvalho Chehab 
67487b52439SFrank Schaefer 		if (dev->eeprom_addrwidth_16bit)
67550f0a9dfSMauro Carvalho Chehab 			em28xx_info("eeprom %06x: ... (skipped)\n", 256);
67687b52439SFrank Schaefer 	}
6770c0d06caSMauro Carvalho Chehab 
67887b52439SFrank Schaefer 	if (dev->eeprom_addrwidth_16bit &&
679a217968fSFrank Schaefer 	    data[0] == 0x26 && data[3] == 0x00) {
68087b52439SFrank Schaefer 		/* new eeprom format; size 4-64kb */
681510e884cSFrank Schaefer 		u16 mc_start;
682510e884cSFrank Schaefer 		u16 hwconf_offset;
683510e884cSFrank Schaefer 
684a217968fSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
685510e884cSFrank Schaefer 		mc_start = (data[1] << 8) + 4;	/* usually 0x0004 */
686510e884cSFrank Schaefer 
687d230d5adSFrank Schaefer 		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
688510e884cSFrank Schaefer 			    data[0], data[1], data[2], data[3], dev->hash);
689510e884cSFrank Schaefer 		em28xx_info("EEPROM info:\n");
690d230d5adSFrank Schaefer 		em28xx_info("\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n",
691510e884cSFrank Schaefer 			    mc_start, data[2]);
692fa74aca3SFrank Schaefer 		/*
693fa74aca3SFrank Schaefer 		 * boot configuration (address 0x0002):
69487b52439SFrank Schaefer 		 * [0]   microcode download speed: 1 = 400 kHz; 0 = 100 kHz
69587b52439SFrank Schaefer 		 * [1]   always selects 12 kb RAM
69687b52439SFrank Schaefer 		 * [2]   USB device speed: 1 = force Full Speed; 0 = auto detect
69787b52439SFrank Schaefer 		 * [4]   1 = force fast mode and no suspend for device testing
69887b52439SFrank Schaefer 		 * [5:7] USB PHY tuning registers; determined by device
69987b52439SFrank Schaefer 		 *       characterization
70087b52439SFrank Schaefer 		 */
70187b52439SFrank Schaefer 
702fa74aca3SFrank Schaefer 		/*
703fa74aca3SFrank Schaefer 		 * Read hardware config dataset offset from address
704fa74aca3SFrank Schaefer 		 * (microcode start + 46)
705fa74aca3SFrank Schaefer 		 */
706aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2,
707aab3125cSMauro Carvalho Chehab 					    data);
708510e884cSFrank Schaefer 		if (err != 2) {
709510e884cSFrank Schaefer 			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
710510e884cSFrank Schaefer 				      err);
711510e884cSFrank Schaefer 			goto error;
712510e884cSFrank Schaefer 		}
71387b52439SFrank Schaefer 
714510e884cSFrank Schaefer 		/* Calculate hardware config dataset start address */
715510e884cSFrank Schaefer 		hwconf_offset = mc_start + data[0] + (data[1] << 8);
716510e884cSFrank Schaefer 
717510e884cSFrank Schaefer 		/* Read hardware config dataset */
718fa74aca3SFrank Schaefer 		/*
719fa74aca3SFrank Schaefer 		 * NOTE: the microcode copy can be multiple pages long, but
720510e884cSFrank Schaefer 		 * we assume the hardware config dataset is the same as in
721510e884cSFrank Schaefer 		 * the old eeprom and not longer than 256 bytes.
722510e884cSFrank Schaefer 		 * tveeprom is currently also limited to 256 bytes.
723510e884cSFrank Schaefer 		 */
724aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len,
725aab3125cSMauro Carvalho Chehab 					    data);
726510e884cSFrank Schaefer 		if (err != len) {
727510e884cSFrank Schaefer 			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
728510e884cSFrank Schaefer 				      err);
729510e884cSFrank Schaefer 			goto error;
730510e884cSFrank Schaefer 		}
731510e884cSFrank Schaefer 
732510e884cSFrank Schaefer 		/* Verify hardware config dataset */
733510e884cSFrank Schaefer 		/* NOTE: not all devices provide this type of dataset */
734510e884cSFrank Schaefer 		if (data[0] != 0x1a || data[1] != 0xeb ||
735a217968fSFrank Schaefer 		    data[2] != 0x67 || data[3] != 0x95) {
736510e884cSFrank Schaefer 			em28xx_info("\tno hardware configuration dataset found in eeprom\n");
737510e884cSFrank Schaefer 			kfree(data);
738510e884cSFrank Schaefer 			return 0;
739510e884cSFrank Schaefer 		}
740510e884cSFrank Schaefer 
741510e884cSFrank Schaefer 		/* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */
742510e884cSFrank Schaefer 
743510e884cSFrank Schaefer 	} else if (!dev->eeprom_addrwidth_16bit &&
744510e884cSFrank Schaefer 		   data[0] == 0x1a && data[1] == 0xeb &&
745510e884cSFrank Schaefer 		   data[2] == 0x67 && data[3] == 0x95) {
746510e884cSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
747d230d5adSFrank Schaefer 		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
748510e884cSFrank Schaefer 			    data[0], data[1], data[2], data[3], dev->hash);
749510e884cSFrank Schaefer 		em28xx_info("EEPROM info:\n");
750510e884cSFrank Schaefer 	} else {
75187b52439SFrank Schaefer 		em28xx_info("unknown eeprom format or eeprom corrupted !\n");
752510e884cSFrank Schaefer 		err = -ENODEV;
753510e884cSFrank Schaefer 		goto error;
754f55eacbeSFrank Schaefer 	}
755f55eacbeSFrank Schaefer 
756a217968fSFrank Schaefer 	*eedata = data;
757510e884cSFrank Schaefer 	*eedata_len = len;
75832bf7c6cSAlban Browaeys 	dev_config = (void *)*eedata;
759a217968fSFrank Schaefer 
760510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
7610c0d06caSMauro Carvalho Chehab 	case 0:
76212d7ce18SFrank Schaefer 		em28xx_info("\tNo audio on board.\n");
7630c0d06caSMauro Carvalho Chehab 		break;
7640c0d06caSMauro Carvalho Chehab 	case 1:
76512d7ce18SFrank Schaefer 		em28xx_info("\tAC97 audio (5 sample rates)\n");
7660c0d06caSMauro Carvalho Chehab 		break;
7670c0d06caSMauro Carvalho Chehab 	case 2:
768687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
76912d7ce18SFrank Schaefer 			em28xx_info("\tI2S audio, sample rate=32k\n");
770687ff8b0SFrank Schaefer 		else
771687ff8b0SFrank Schaefer 			em28xx_info("\tI2S audio, 3 sample rates\n");
7720c0d06caSMauro Carvalho Chehab 		break;
7730c0d06caSMauro Carvalho Chehab 	case 3:
774687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
77512d7ce18SFrank Schaefer 			em28xx_info("\tI2S audio, 3 sample rates\n");
776687ff8b0SFrank Schaefer 		else
777687ff8b0SFrank Schaefer 			em28xx_info("\tI2S audio, 5 sample rates\n");
7780c0d06caSMauro Carvalho Chehab 		break;
7790c0d06caSMauro Carvalho Chehab 	}
7800c0d06caSMauro Carvalho Chehab 
781510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 3)
78212d7ce18SFrank Schaefer 		em28xx_info("\tUSB Remote wakeup capable\n");
7830c0d06caSMauro Carvalho Chehab 
784510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 2)
78512d7ce18SFrank Schaefer 		em28xx_info("\tUSB Self power capable\n");
7860c0d06caSMauro Carvalho Chehab 
787510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) & 0x3) {
7880c0d06caSMauro Carvalho Chehab 	case 0:
78912d7ce18SFrank Schaefer 		em28xx_info("\t500mA max power\n");
7900c0d06caSMauro Carvalho Chehab 		break;
7910c0d06caSMauro Carvalho Chehab 	case 1:
79212d7ce18SFrank Schaefer 		em28xx_info("\t400mA max power\n");
7930c0d06caSMauro Carvalho Chehab 		break;
7940c0d06caSMauro Carvalho Chehab 	case 2:
79512d7ce18SFrank Schaefer 		em28xx_info("\t300mA max power\n");
7960c0d06caSMauro Carvalho Chehab 		break;
7970c0d06caSMauro Carvalho Chehab 	case 3:
79812d7ce18SFrank Schaefer 		em28xx_info("\t200mA max power\n");
7990c0d06caSMauro Carvalho Chehab 		break;
8000c0d06caSMauro Carvalho Chehab 	}
80112d7ce18SFrank Schaefer 	em28xx_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
802510e884cSFrank Schaefer 		    dev_config->string_idx_table,
803510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string1),
804510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string2),
805510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string3));
8060c0d06caSMauro Carvalho Chehab 
8070c0d06caSMauro Carvalho Chehab 	return 0;
808510e884cSFrank Schaefer 
809510e884cSFrank Schaefer error:
810510e884cSFrank Schaefer 	kfree(data);
811510e884cSFrank Schaefer 	return err;
8120c0d06caSMauro Carvalho Chehab }
8130c0d06caSMauro Carvalho Chehab 
8140c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
8150c0d06caSMauro Carvalho Chehab 
8160c0d06caSMauro Carvalho Chehab /*
8170c0d06caSMauro Carvalho Chehab  * functionality()
8180c0d06caSMauro Carvalho Chehab  */
819aab3125cSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *i2c_adap)
8200c0d06caSMauro Carvalho Chehab {
821aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
822aab3125cSMauro Carvalho Chehab 
823a3ea4bf9SFrank Schaefer 	if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) ||
824a3ea4bf9SFrank Schaefer 	    (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) {
825a3ea4bf9SFrank Schaefer 		return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
826a3ea4bf9SFrank Schaefer 	} else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)  {
827a3ea4bf9SFrank Schaefer 		return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) &
828a3ea4bf9SFrank Schaefer 			~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
829a3ea4bf9SFrank Schaefer 	}
830a3ea4bf9SFrank Schaefer 
831a3ea4bf9SFrank Schaefer 	WARN(1, "Unknown i2c bus algorithm.\n");
832a3ea4bf9SFrank Schaefer 	return 0;
8330c0d06caSMauro Carvalho Chehab }
8340c0d06caSMauro Carvalho Chehab 
8350c0d06caSMauro Carvalho Chehab static struct i2c_algorithm em28xx_algo = {
8360c0d06caSMauro Carvalho Chehab 	.master_xfer   = em28xx_i2c_xfer,
8370c0d06caSMauro Carvalho Chehab 	.functionality = functionality,
8380c0d06caSMauro Carvalho Chehab };
8390c0d06caSMauro Carvalho Chehab 
8400c0d06caSMauro Carvalho Chehab static struct i2c_adapter em28xx_adap_template = {
8410c0d06caSMauro Carvalho Chehab 	.owner = THIS_MODULE,
8420c0d06caSMauro Carvalho Chehab 	.name = "em28xx",
8430c0d06caSMauro Carvalho Chehab 	.algo = &em28xx_algo,
8440c0d06caSMauro Carvalho Chehab };
8450c0d06caSMauro Carvalho Chehab 
8460c0d06caSMauro Carvalho Chehab static struct i2c_client em28xx_client_template = {
8470c0d06caSMauro Carvalho Chehab 	.name = "em28xx internal",
8480c0d06caSMauro Carvalho Chehab };
8490c0d06caSMauro Carvalho Chehab 
8500c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
8510c0d06caSMauro Carvalho Chehab 
8520c0d06caSMauro Carvalho Chehab /*
8530c0d06caSMauro Carvalho Chehab  * i2c_devs
8540c0d06caSMauro Carvalho Chehab  * incomplete list of known devices
8550c0d06caSMauro Carvalho Chehab  */
8560c0d06caSMauro Carvalho Chehab static char *i2c_devs[128] = {
8570b3966e4SFrank Schaefer 	[0x3e >> 1] = "remote IR sensor",
8580c0d06caSMauro Carvalho Chehab 	[0x4a >> 1] = "saa7113h",
8590c0d06caSMauro Carvalho Chehab 	[0x52 >> 1] = "drxk",
8600c0d06caSMauro Carvalho Chehab 	[0x60 >> 1] = "remote IR sensor",
8610c0d06caSMauro Carvalho Chehab 	[0x8e >> 1] = "remote IR sensor",
8620c0d06caSMauro Carvalho Chehab 	[0x86 >> 1] = "tda9887",
8630c0d06caSMauro Carvalho Chehab 	[0x80 >> 1] = "msp34xx",
8640c0d06caSMauro Carvalho Chehab 	[0x88 >> 1] = "msp34xx",
8650c0d06caSMauro Carvalho Chehab 	[0xa0 >> 1] = "eeprom",
8660c0d06caSMauro Carvalho Chehab 	[0xb0 >> 1] = "tda9874",
8670c0d06caSMauro Carvalho Chehab 	[0xb8 >> 1] = "tvp5150a",
8680c0d06caSMauro Carvalho Chehab 	[0xba >> 1] = "webcam sensor or tvp5150a",
8690c0d06caSMauro Carvalho Chehab 	[0xc0 >> 1] = "tuner (analog)",
8700c0d06caSMauro Carvalho Chehab 	[0xc2 >> 1] = "tuner (analog)",
8710c0d06caSMauro Carvalho Chehab 	[0xc4 >> 1] = "tuner (analog)",
8720c0d06caSMauro Carvalho Chehab 	[0xc6 >> 1] = "tuner (analog)",
8730c0d06caSMauro Carvalho Chehab };
8740c0d06caSMauro Carvalho Chehab 
8750c0d06caSMauro Carvalho Chehab /*
8760c0d06caSMauro Carvalho Chehab  * do_i2c_scan()
8770c0d06caSMauro Carvalho Chehab  * check i2c address range for devices
8780c0d06caSMauro Carvalho Chehab  */
879aab3125cSMauro Carvalho Chehab void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus)
8800c0d06caSMauro Carvalho Chehab {
8810c0d06caSMauro Carvalho Chehab 	u8 i2c_devicelist[128];
8820c0d06caSMauro Carvalho Chehab 	unsigned char buf;
8830c0d06caSMauro Carvalho Chehab 	int i, rc;
8840c0d06caSMauro Carvalho Chehab 
8850c0d06caSMauro Carvalho Chehab 	memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
8860c0d06caSMauro Carvalho Chehab 
8870c0d06caSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
888aab3125cSMauro Carvalho Chehab 		dev->i2c_client[bus].addr = i;
889aab3125cSMauro Carvalho Chehab 		rc = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
8900c0d06caSMauro Carvalho Chehab 		if (rc < 0)
8910c0d06caSMauro Carvalho Chehab 			continue;
8920c0d06caSMauro Carvalho Chehab 		i2c_devicelist[i] = i;
893aab3125cSMauro Carvalho Chehab 		em28xx_info("found i2c device @ 0x%x on bus %d [%s]\n",
894aab3125cSMauro Carvalho Chehab 			    i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???");
8950c0d06caSMauro Carvalho Chehab 	}
8960c0d06caSMauro Carvalho Chehab 
897aab3125cSMauro Carvalho Chehab 	if (bus == dev->def_i2c_bus)
8980c0d06caSMauro Carvalho Chehab 		dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
8990c0d06caSMauro Carvalho Chehab 						ARRAY_SIZE(i2c_devicelist), 32);
9000c0d06caSMauro Carvalho Chehab }
9010c0d06caSMauro Carvalho Chehab 
9020c0d06caSMauro Carvalho Chehab /*
9030c0d06caSMauro Carvalho Chehab  * em28xx_i2c_register()
9040c0d06caSMauro Carvalho Chehab  * register i2c bus
9050c0d06caSMauro Carvalho Chehab  */
906a3ea4bf9SFrank Schaefer int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
907a3ea4bf9SFrank Schaefer 			enum em28xx_i2c_algo_type algo_type)
9080c0d06caSMauro Carvalho Chehab {
9090c0d06caSMauro Carvalho Chehab 	int retval;
9100c0d06caSMauro Carvalho Chehab 
9110c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
9120c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
9130c0d06caSMauro Carvalho Chehab 
914aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
915aab3125cSMauro Carvalho Chehab 		return -ENODEV;
916aab3125cSMauro Carvalho Chehab 
917aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus] = em28xx_adap_template;
918aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].dev.parent = &dev->udev->dev;
919aab3125cSMauro Carvalho Chehab 	strcpy(dev->i2c_adap[bus].name, dev->name);
920aab3125cSMauro Carvalho Chehab 
921aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].bus = bus;
922a3ea4bf9SFrank Schaefer 	dev->i2c_bus[bus].algo_type = algo_type;
923aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].dev = dev;
924aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus];
925aab3125cSMauro Carvalho Chehab 	i2c_set_adapdata(&dev->i2c_adap[bus], &dev->v4l2_dev);
926aab3125cSMauro Carvalho Chehab 
927aab3125cSMauro Carvalho Chehab 	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
9280c0d06caSMauro Carvalho Chehab 	if (retval < 0) {
9290c0d06caSMauro Carvalho Chehab 		em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
9300c0d06caSMauro Carvalho Chehab 			__func__, retval);
9310c0d06caSMauro Carvalho Chehab 		return retval;
9320c0d06caSMauro Carvalho Chehab 	}
9330c0d06caSMauro Carvalho Chehab 
934aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus] = em28xx_client_template;
935aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].adapter = &dev->i2c_adap[bus];
9360c0d06caSMauro Carvalho Chehab 
937aab3125cSMauro Carvalho Chehab 	/* Up to now, all eeproms are at bus 0 */
938aab3125cSMauro Carvalho Chehab 	if (!bus) {
939aab3125cSMauro Carvalho Chehab 		retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
9400c0d06caSMauro Carvalho Chehab 		if ((retval < 0) && (retval != -ENODEV)) {
9410c0d06caSMauro Carvalho Chehab 			em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
9420c0d06caSMauro Carvalho Chehab 				__func__, retval);
9430c0d06caSMauro Carvalho Chehab 
9440c0d06caSMauro Carvalho Chehab 			return retval;
9450c0d06caSMauro Carvalho Chehab 		}
946aab3125cSMauro Carvalho Chehab 	}
9470c0d06caSMauro Carvalho Chehab 
9480c0d06caSMauro Carvalho Chehab 	if (i2c_scan)
949aab3125cSMauro Carvalho Chehab 		em28xx_do_i2c_scan(dev, bus);
9500c0d06caSMauro Carvalho Chehab 
9510c0d06caSMauro Carvalho Chehab 	return 0;
9520c0d06caSMauro Carvalho Chehab }
9530c0d06caSMauro Carvalho Chehab 
9540c0d06caSMauro Carvalho Chehab /*
9550c0d06caSMauro Carvalho Chehab  * em28xx_i2c_unregister()
9560c0d06caSMauro Carvalho Chehab  * unregister i2c_bus
9570c0d06caSMauro Carvalho Chehab  */
958aab3125cSMauro Carvalho Chehab int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus)
9590c0d06caSMauro Carvalho Chehab {
960aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
961aab3125cSMauro Carvalho Chehab 		return -ENODEV;
962aab3125cSMauro Carvalho Chehab 
963aab3125cSMauro Carvalho Chehab 	i2c_del_adapter(&dev->i2c_adap[bus]);
9640c0d06caSMauro Carvalho Chehab 	return 0;
9650c0d06caSMauro Carvalho Chehab }
966