xref: /openbmc/linux/drivers/media/usb/em28xx/em28xx-i2c.c (revision 8314d40233f3790e4cfa704087bb2a43c18144d7)
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 
25*8314d402SMauro Carvalho Chehab #include "em28xx.h"
26*8314d402SMauro 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 
470c0d06caSMauro Carvalho Chehab /*
48f5ae371aSFrank Schaefer  * em2800_i2c_send_bytes()
49f5ae371aSFrank Schaefer  * send up to 4 bytes to the em2800 i2c device
500c0d06caSMauro Carvalho Chehab  */
51f5ae371aSFrank Schaefer static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
520c0d06caSMauro Carvalho Chehab {
53d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
540c0d06caSMauro Carvalho Chehab 	int ret;
55a6bad040SFrank Schaefer 	u8 b2[6];
56f5ae371aSFrank Schaefer 
57f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
58f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
59f5ae371aSFrank Schaefer 
600c0d06caSMauro Carvalho Chehab 	BUG_ON(len < 1 || len > 4);
610c0d06caSMauro Carvalho Chehab 	b2[5] = 0x80 + len - 1;
620c0d06caSMauro Carvalho Chehab 	b2[4] = addr;
630c0d06caSMauro Carvalho Chehab 	b2[3] = buf[0];
640c0d06caSMauro Carvalho Chehab 	if (len > 1)
650c0d06caSMauro Carvalho Chehab 		b2[2] = buf[1];
660c0d06caSMauro Carvalho Chehab 	if (len > 2)
670c0d06caSMauro Carvalho Chehab 		b2[1] = buf[2];
680c0d06caSMauro Carvalho Chehab 	if (len > 3)
690c0d06caSMauro Carvalho Chehab 		b2[0] = buf[3];
700c0d06caSMauro Carvalho Chehab 
712fcc82d8SFrank Schaefer 	/* trigger write */
720c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
730c0d06caSMauro Carvalho Chehab 	if (ret != 2 + len) {
74*8314d402SMauro Carvalho Chehab 		pr_warn("failed to trigger write to i2c address 0x%x (error=%i)\n",
75d230d5adSFrank Schaefer 			    addr, ret);
7645f04e82SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
770c0d06caSMauro Carvalho Chehab 	}
782fcc82d8SFrank Schaefer 	/* wait for completion */
794b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
800c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
814b83626aSMauro Carvalho Chehab 		if (ret == 0x80 + len - 1)
820c0d06caSMauro Carvalho Chehab 			return len;
834b83626aSMauro Carvalho Chehab 		if (ret == 0x94 + len - 1) {
84d845fb3aSMauro Carvalho Chehab 			if (i2c_debug == 1)
85*8314d402SMauro Carvalho Chehab 				pr_warn("R05 returned 0x%02x: I2C ACK error\n",
86d845fb3aSMauro Carvalho Chehab 					    ret);
87e63b009dSMauro Carvalho Chehab 			return -ENXIO;
884b83626aSMauro Carvalho Chehab 		}
894b83626aSMauro Carvalho Chehab 		if (ret < 0) {
90*8314d402SMauro Carvalho Chehab 			pr_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
91d230d5adSFrank Schaefer 				    ret);
9245f04e82SFrank Schaefer 			return ret;
9345f04e82SFrank Schaefer 		}
940c0d06caSMauro Carvalho Chehab 		msleep(5);
950c0d06caSMauro Carvalho Chehab 	}
9650f0a9dfSMauro Carvalho Chehab 	if (i2c_debug)
97*8314d402SMauro Carvalho Chehab 		pr_warn("write to i2c device at 0x%x timed out\n", addr);
98e63b009dSMauro Carvalho Chehab 	return -ETIMEDOUT;
990c0d06caSMauro Carvalho Chehab }
1000c0d06caSMauro Carvalho Chehab 
1010c0d06caSMauro Carvalho Chehab /*
1020c0d06caSMauro Carvalho Chehab  * em2800_i2c_recv_bytes()
1032fcc82d8SFrank Schaefer  * read up to 4 bytes from the em2800 i2c device
1040c0d06caSMauro Carvalho Chehab  */
105a6bad040SFrank Schaefer static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
1060c0d06caSMauro Carvalho Chehab {
107d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
1082fcc82d8SFrank Schaefer 	u8 buf2[4];
1090c0d06caSMauro Carvalho Chehab 	int ret;
1102fcc82d8SFrank Schaefer 	int i;
111f5ae371aSFrank Schaefer 
112f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
113f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
114f5ae371aSFrank Schaefer 
1152fcc82d8SFrank Schaefer 	/* trigger read */
1162fcc82d8SFrank Schaefer 	buf2[1] = 0x84 + len - 1;
1172fcc82d8SFrank Schaefer 	buf2[0] = addr;
1182fcc82d8SFrank Schaefer 	ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
1192fcc82d8SFrank Schaefer 	if (ret != 2) {
120*8314d402SMauro Carvalho Chehab 		pr_warn("failed to trigger read from i2c address 0x%x (error=%i)\n",
121d230d5adSFrank Schaefer 			    addr, ret);
1222fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1232fcc82d8SFrank Schaefer 	}
1242fcc82d8SFrank Schaefer 
1252fcc82d8SFrank Schaefer 	/* wait for completion */
1264b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
1272fcc82d8SFrank Schaefer 		ret = dev->em28xx_read_reg(dev, 0x05);
1284b83626aSMauro Carvalho Chehab 		if (ret == 0x84 + len - 1)
1292fcc82d8SFrank Schaefer 			break;
1304b83626aSMauro Carvalho Chehab 		if (ret == 0x94 + len - 1) {
131d845fb3aSMauro Carvalho Chehab 			if (i2c_debug == 1)
132*8314d402SMauro Carvalho Chehab 				pr_warn("R05 returned 0x%02x: I2C ACK error\n",
133d845fb3aSMauro Carvalho Chehab 					    ret);
134e63b009dSMauro Carvalho Chehab 			return -ENXIO;
1354b83626aSMauro Carvalho Chehab 		}
1364b83626aSMauro Carvalho Chehab 		if (ret < 0) {
137*8314d402SMauro Carvalho Chehab 			pr_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
138d230d5adSFrank Schaefer 				    ret);
1390c0d06caSMauro Carvalho Chehab 			return ret;
1400c0d06caSMauro Carvalho Chehab 		}
1412fcc82d8SFrank Schaefer 		msleep(5);
1422fcc82d8SFrank Schaefer 	}
14350f0a9dfSMauro Carvalho Chehab 	if (ret != 0x84 + len - 1) {
14450f0a9dfSMauro Carvalho Chehab 		if (i2c_debug)
145*8314d402SMauro Carvalho Chehab 			pr_warn("read from i2c device at 0x%x timed out\n",
14650f0a9dfSMauro Carvalho Chehab 				    addr);
14750f0a9dfSMauro Carvalho Chehab 	}
1482fcc82d8SFrank Schaefer 
1492fcc82d8SFrank Schaefer 	/* get the received message */
1502fcc82d8SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
1512fcc82d8SFrank Schaefer 	if (ret != len) {
152*8314d402SMauro Carvalho Chehab 		pr_warn("reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
153d230d5adSFrank Schaefer 			    addr, ret);
1542fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1552fcc82d8SFrank Schaefer 	}
1562fcc82d8SFrank Schaefer 	for (i = 0; i < len; i++)
1572fcc82d8SFrank Schaefer 		buf[i] = buf2[len - 1 - i];
1582fcc82d8SFrank Schaefer 
1590c0d06caSMauro Carvalho Chehab 	return ret;
1600c0d06caSMauro Carvalho Chehab }
1612fcc82d8SFrank Schaefer 
1622fcc82d8SFrank Schaefer /*
1632fcc82d8SFrank Schaefer  * em2800_i2c_check_for_device()
1642fcc82d8SFrank Schaefer  * check if there is an i2c device at the supplied address
1652fcc82d8SFrank Schaefer  */
1662fcc82d8SFrank Schaefer static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
1672fcc82d8SFrank Schaefer {
1682fcc82d8SFrank Schaefer 	u8 buf;
1692fcc82d8SFrank Schaefer 	int ret;
1702fcc82d8SFrank Schaefer 
1712fcc82d8SFrank Schaefer 	ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1);
1722fcc82d8SFrank Schaefer 	if (ret == 1)
1732fcc82d8SFrank Schaefer 		return 0;
1742fcc82d8SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
1750c0d06caSMauro Carvalho Chehab }
1760c0d06caSMauro Carvalho Chehab 
1770c0d06caSMauro Carvalho Chehab /*
1780c0d06caSMauro Carvalho Chehab  * em28xx_i2c_send_bytes()
1790c0d06caSMauro Carvalho Chehab  */
180a6bad040SFrank Schaefer static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
181a6bad040SFrank Schaefer 				 u16 len, int stop)
1820c0d06caSMauro Carvalho Chehab {
183d1b7213bSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM28XX_I2C_XFER_TIMEOUT);
1844b83626aSMauro Carvalho Chehab 	int ret;
1850c0d06caSMauro Carvalho Chehab 
186f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
187f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
188fa74aca3SFrank Schaefer 	/*
189fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
190fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
191fa74aca3SFrank Schaefer 	 */
192f5ae371aSFrank Schaefer 
19345f04e82SFrank Schaefer 	/* Write to i2c device */
19445f04e82SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
19545f04e82SFrank Schaefer 	if (ret != len) {
19645f04e82SFrank Schaefer 		if (ret < 0) {
197*8314d402SMauro Carvalho Chehab 			pr_warn("writing to i2c device at 0x%x failed (error=%i)\n",
198d230d5adSFrank Schaefer 				    addr, ret);
19945f04e82SFrank Schaefer 			return ret;
20045f04e82SFrank Schaefer 		} else {
201*8314d402SMauro Carvalho Chehab 			pr_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
20245f04e82SFrank Schaefer 				    len, addr, ret);
20345f04e82SFrank Schaefer 			return -EIO;
20445f04e82SFrank Schaefer 		}
20545f04e82SFrank Schaefer 	}
2060c0d06caSMauro Carvalho Chehab 
2074b83626aSMauro Carvalho Chehab 	/* wait for completion */
2084b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
2090c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
2104b83626aSMauro Carvalho Chehab 		if (ret == 0) /* success */
21145f04e82SFrank Schaefer 			return len;
2124b83626aSMauro Carvalho Chehab 		if (ret == 0x10) {
213d845fb3aSMauro Carvalho Chehab 			if (i2c_debug == 1)
214*8314d402SMauro Carvalho Chehab 				pr_warn("I2C ACK error on writing to addr 0x%02x\n",
215d845fb3aSMauro Carvalho Chehab 					    addr);
216e63b009dSMauro Carvalho Chehab 			return -ENXIO;
2174b83626aSMauro Carvalho Chehab 		}
2184b83626aSMauro Carvalho Chehab 		if (ret < 0) {
219*8314d402SMauro Carvalho Chehab 			pr_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
220d230d5adSFrank Schaefer 				    ret);
22145f04e82SFrank Schaefer 			return ret;
2220c0d06caSMauro Carvalho Chehab 		}
22345f04e82SFrank Schaefer 		msleep(5);
224fa74aca3SFrank Schaefer 		/*
225fa74aca3SFrank Schaefer 		 * NOTE: do we really have to wait for success ?
226fa74aca3SFrank Schaefer 		 * Never seen anything else than 0x00 or 0x10
227fa74aca3SFrank Schaefer 		 * (even with high payload) ...
228fa74aca3SFrank Schaefer 		 */
22945f04e82SFrank Schaefer 	}
230123a17d1SFrank Schaefer 
231123a17d1SFrank Schaefer 	if (ret == 0x02 || ret == 0x04) {
232123a17d1SFrank Schaefer 		/* NOTE: these errors seem to be related to clock stretching */
23350f0a9dfSMauro Carvalho Chehab 		if (i2c_debug)
234*8314d402SMauro Carvalho Chehab 			pr_warn("write to i2c device at 0x%x timed out (status=%i)\n",
23550f0a9dfSMauro Carvalho Chehab 				    addr, ret);
236e63b009dSMauro Carvalho Chehab 		return -ETIMEDOUT;
2370c0d06caSMauro Carvalho Chehab 	}
2380c0d06caSMauro Carvalho Chehab 
239*8314d402SMauro Carvalho Chehab 	pr_warn("write to i2c device at 0x%x failed with unknown error (status=%i)\n",
240123a17d1SFrank Schaefer 		    addr, ret);
241123a17d1SFrank Schaefer 	return -EIO;
242123a17d1SFrank Schaefer }
243123a17d1SFrank Schaefer 
2440c0d06caSMauro Carvalho Chehab /*
2450c0d06caSMauro Carvalho Chehab  * em28xx_i2c_recv_bytes()
2460c0d06caSMauro Carvalho Chehab  * read a byte from the i2c device
2470c0d06caSMauro Carvalho Chehab  */
248a6bad040SFrank Schaefer static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
2490c0d06caSMauro Carvalho Chehab {
2500c0d06caSMauro Carvalho Chehab 	int ret;
251f5ae371aSFrank Schaefer 
252f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
253f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
254fa74aca3SFrank Schaefer 	/*
255fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
256fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
257fa74aca3SFrank Schaefer 	 */
258f5ae371aSFrank Schaefer 
25945f04e82SFrank Schaefer 	/* Read data from i2c device */
2600c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
2610c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
262*8314d402SMauro Carvalho Chehab 		pr_warn("reading from i2c device at 0x%x failed (error=%i)\n",
2637f6301d1SFrank Schaefer 			    addr, ret);
26445f04e82SFrank Schaefer 		return ret;
26545f04e82SFrank Schaefer 	}
266fa74aca3SFrank Schaefer 	/*
267fa74aca3SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
2687f6301d1SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
2697f6301d1SFrank Schaefer 	 * specified slave address before AND no device is present at the
2707f6301d1SFrank Schaefer 	 * requested slave address.
271e63b009dSMauro Carvalho Chehab 	 * Anyway, the next check will fail with -ENXIO in this case, so avoid
2727f6301d1SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
2737f6301d1SFrank Schaefer 	 */
27445f04e82SFrank Schaefer 
27545f04e82SFrank Schaefer 	/* Check success of the i2c operation */
27645f04e82SFrank Schaefer 	ret = dev->em28xx_read_reg(dev, 0x05);
2774b83626aSMauro Carvalho Chehab 	if (ret == 0) /* success */
2784b83626aSMauro Carvalho Chehab 		return len;
27945f04e82SFrank Schaefer 	if (ret < 0) {
280*8314d402SMauro Carvalho Chehab 		pr_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
281d230d5adSFrank Schaefer 			    ret);
2820c0d06caSMauro Carvalho Chehab 		return ret;
2830c0d06caSMauro Carvalho Chehab 	}
284d845fb3aSMauro Carvalho Chehab 	if (ret == 0x10) {
285d845fb3aSMauro Carvalho Chehab 		if (i2c_debug == 1)
286*8314d402SMauro Carvalho Chehab 			pr_warn("I2C ACK error on writing to addr 0x%02x\n",
287d845fb3aSMauro Carvalho Chehab 				    addr);
288e63b009dSMauro Carvalho Chehab 		return -ENXIO;
289d845fb3aSMauro Carvalho Chehab 	}
2904b83626aSMauro Carvalho Chehab 
291123a17d1SFrank Schaefer 	if (ret == 0x02 || ret == 0x04) {
292123a17d1SFrank Schaefer 		/* NOTE: these errors seem to be related to clock stretching */
293123a17d1SFrank Schaefer 		if (i2c_debug)
294*8314d402SMauro Carvalho Chehab 			pr_warn("write to i2c device at 0x%x timed out (status=%i)\n",
295123a17d1SFrank Schaefer 				    addr, ret);
296e63b009dSMauro Carvalho Chehab 		return -ETIMEDOUT;
29745f04e82SFrank Schaefer 	}
2980c0d06caSMauro Carvalho Chehab 
299*8314d402SMauro Carvalho Chehab 	pr_warn("write to i2c device at 0x%x failed with unknown error (status=%i)\n",
300123a17d1SFrank Schaefer 		    addr, ret);
301123a17d1SFrank Schaefer 	return -EIO;
302123a17d1SFrank Schaefer }
303123a17d1SFrank Schaefer 
3040c0d06caSMauro Carvalho Chehab /*
3050c0d06caSMauro Carvalho Chehab  * em28xx_i2c_check_for_device()
3060c0d06caSMauro Carvalho Chehab  * check if there is a i2c_device at the supplied address
3070c0d06caSMauro Carvalho Chehab  */
308a6bad040SFrank Schaefer static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
3090c0d06caSMauro Carvalho Chehab {
3100c0d06caSMauro Carvalho Chehab 	int ret;
31145f04e82SFrank Schaefer 	u8 buf;
3120c0d06caSMauro Carvalho Chehab 
31345f04e82SFrank Schaefer 	ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1);
31445f04e82SFrank Schaefer 	if (ret == 1)
3150c0d06caSMauro Carvalho Chehab 		return 0;
31645f04e82SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
3170c0d06caSMauro Carvalho Chehab }
3180c0d06caSMauro Carvalho Chehab 
3190c0d06caSMauro Carvalho Chehab /*
320a3ea4bf9SFrank Schaefer  * em25xx_bus_B_send_bytes
321a3ea4bf9SFrank Schaefer  * write bytes to the i2c device
322a3ea4bf9SFrank Schaefer  */
323a3ea4bf9SFrank Schaefer static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
324a3ea4bf9SFrank Schaefer 				   u16 len)
325a3ea4bf9SFrank Schaefer {
326a3ea4bf9SFrank Schaefer 	int ret;
327a3ea4bf9SFrank Schaefer 
328a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
329a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
330a3ea4bf9SFrank Schaefer 	/*
331a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
332a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
333a3ea4bf9SFrank Schaefer 	 */
334a3ea4bf9SFrank Schaefer 
335a3ea4bf9SFrank Schaefer 	/* Set register and write value */
336a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len);
337a3ea4bf9SFrank Schaefer 	if (ret != len) {
338a3ea4bf9SFrank Schaefer 		if (ret < 0) {
339*8314d402SMauro Carvalho Chehab 			pr_warn("writing to i2c device at 0x%x failed (error=%i)\n",
340a3ea4bf9SFrank Schaefer 				    addr, ret);
341a3ea4bf9SFrank Schaefer 			return ret;
342a3ea4bf9SFrank Schaefer 		} else {
343*8314d402SMauro Carvalho Chehab 			pr_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
344a3ea4bf9SFrank Schaefer 				    len, addr, ret);
345a3ea4bf9SFrank Schaefer 			return -EIO;
346a3ea4bf9SFrank Schaefer 		}
347a3ea4bf9SFrank Schaefer 	}
348a3ea4bf9SFrank Schaefer 	/* Check success */
349a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
350a3ea4bf9SFrank Schaefer 	/*
351a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
352a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
353a3ea4bf9SFrank Schaefer 	 */
354a3ea4bf9SFrank Schaefer 	if (!ret)
355a3ea4bf9SFrank Schaefer 		return len;
356d845fb3aSMauro Carvalho Chehab 	else if (ret > 0) {
357d845fb3aSMauro Carvalho Chehab 		if (i2c_debug == 1)
358*8314d402SMauro Carvalho Chehab 			pr_warn("Bus B R08 returned 0x%02x: I2C ACK error\n",
359d845fb3aSMauro Carvalho Chehab 				    ret);
360e63b009dSMauro Carvalho Chehab 		return -ENXIO;
361d845fb3aSMauro Carvalho Chehab 	}
362a3ea4bf9SFrank Schaefer 
363a3ea4bf9SFrank Schaefer 	return ret;
364a3ea4bf9SFrank Schaefer 	/*
365a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
366a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
367a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
368a3ea4bf9SFrank Schaefer 	 */
369a3ea4bf9SFrank Schaefer }
370a3ea4bf9SFrank Schaefer 
371a3ea4bf9SFrank Schaefer /*
372a3ea4bf9SFrank Schaefer  * em25xx_bus_B_recv_bytes
373a3ea4bf9SFrank Schaefer  * read bytes from the i2c device
374a3ea4bf9SFrank Schaefer  */
375a3ea4bf9SFrank Schaefer static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf,
376a3ea4bf9SFrank Schaefer 				   u16 len)
377a3ea4bf9SFrank Schaefer {
378a3ea4bf9SFrank Schaefer 	int ret;
379a3ea4bf9SFrank Schaefer 
380a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
381a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
382a3ea4bf9SFrank Schaefer 	/*
383a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
384a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
385a3ea4bf9SFrank Schaefer 	 */
386a3ea4bf9SFrank Schaefer 
387a3ea4bf9SFrank Schaefer 	/* Read value */
388a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len);
389a3ea4bf9SFrank Schaefer 	if (ret < 0) {
390*8314d402SMauro Carvalho Chehab 		pr_warn("reading from i2c device at 0x%x failed (error=%i)\n",
391a3ea4bf9SFrank Schaefer 			    addr, ret);
392a3ea4bf9SFrank Schaefer 		return ret;
393a3ea4bf9SFrank Schaefer 	}
394a3ea4bf9SFrank Schaefer 	/*
395a3ea4bf9SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
396a3ea4bf9SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
397a3ea4bf9SFrank Schaefer 	 * specified slave address before AND no device is present at the
398a3ea4bf9SFrank Schaefer 	 * requested slave address.
399e63b009dSMauro Carvalho Chehab 	 * Anyway, the next check will fail with -ENXIO in this case, so avoid
400a3ea4bf9SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
401a3ea4bf9SFrank Schaefer 	 */
402a3ea4bf9SFrank Schaefer 
403a3ea4bf9SFrank Schaefer 	/* Check success */
404a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
405a3ea4bf9SFrank Schaefer 	/*
406a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
407a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
408a3ea4bf9SFrank Schaefer 	 */
409a3ea4bf9SFrank Schaefer 	if (!ret)
410a3ea4bf9SFrank Schaefer 		return len;
411d845fb3aSMauro Carvalho Chehab 	else if (ret > 0) {
412d845fb3aSMauro Carvalho Chehab 		if (i2c_debug == 1)
413*8314d402SMauro Carvalho Chehab 			pr_warn("Bus B R08 returned 0x%02x: I2C ACK error\n",
414d845fb3aSMauro Carvalho Chehab 				    ret);
415e63b009dSMauro Carvalho Chehab 		return -ENXIO;
416d845fb3aSMauro Carvalho Chehab 	}
417a3ea4bf9SFrank Schaefer 
418a3ea4bf9SFrank Schaefer 	return ret;
419a3ea4bf9SFrank Schaefer 	/*
420a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
421a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
422a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
423a3ea4bf9SFrank Schaefer 	 */
424a3ea4bf9SFrank Schaefer }
425a3ea4bf9SFrank Schaefer 
426a3ea4bf9SFrank Schaefer /*
427a3ea4bf9SFrank Schaefer  * em25xx_bus_B_check_for_device()
428a3ea4bf9SFrank Schaefer  * check if there is a i2c device at the supplied address
429a3ea4bf9SFrank Schaefer  */
430a3ea4bf9SFrank Schaefer static int em25xx_bus_B_check_for_device(struct em28xx *dev, u16 addr)
431a3ea4bf9SFrank Schaefer {
432a3ea4bf9SFrank Schaefer 	u8 buf;
433a3ea4bf9SFrank Schaefer 	int ret;
434a3ea4bf9SFrank Schaefer 
435a3ea4bf9SFrank Schaefer 	ret = em25xx_bus_B_recv_bytes(dev, addr, &buf, 1);
436a3ea4bf9SFrank Schaefer 	if (ret < 0)
437a3ea4bf9SFrank Schaefer 		return ret;
438a3ea4bf9SFrank Schaefer 
439a3ea4bf9SFrank Schaefer 	return 0;
440a3ea4bf9SFrank Schaefer 	/*
441a3ea4bf9SFrank Schaefer 	 * NOTE: With chips which do not support this operation,
442a3ea4bf9SFrank Schaefer 	 * it seems to succeed ALWAYS ! (even if no device connected)
443a3ea4bf9SFrank Schaefer 	 */
444a3ea4bf9SFrank Schaefer }
445a3ea4bf9SFrank Schaefer 
446a3ea4bf9SFrank Schaefer static inline int i2c_check_for_device(struct em28xx_i2c_bus *i2c_bus, u16 addr)
447a3ea4bf9SFrank Schaefer {
448a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
449a3ea4bf9SFrank Schaefer 	int rc = -EOPNOTSUPP;
450a3ea4bf9SFrank Schaefer 
451a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
452a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_check_for_device(dev, addr);
453a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
454a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_check_for_device(dev, addr);
455a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
456a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_check_for_device(dev, addr);
457a3ea4bf9SFrank Schaefer 	return rc;
458a3ea4bf9SFrank Schaefer }
459a3ea4bf9SFrank Schaefer 
460a3ea4bf9SFrank Schaefer static inline int i2c_recv_bytes(struct em28xx_i2c_bus *i2c_bus,
461a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg)
462a3ea4bf9SFrank Schaefer {
463a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
464a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
46550f0a9dfSMauro Carvalho Chehab 	int rc = -EOPNOTSUPP;
466a3ea4bf9SFrank Schaefer 
467a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
468a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
469a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
470a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
471a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
472a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len);
473a3ea4bf9SFrank Schaefer 	return rc;
474a3ea4bf9SFrank Schaefer }
475a3ea4bf9SFrank Schaefer 
476a3ea4bf9SFrank Schaefer static inline int i2c_send_bytes(struct em28xx_i2c_bus *i2c_bus,
477a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg, int stop)
478a3ea4bf9SFrank Schaefer {
479a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
480a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
48150f0a9dfSMauro Carvalho Chehab 	int rc = -EOPNOTSUPP;
482a3ea4bf9SFrank Schaefer 
483a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
484a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop);
485a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
486a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_send_bytes(dev, addr, msg.buf, msg.len);
487a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
488a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_send_bytes(dev, addr, msg.buf, msg.len);
489a3ea4bf9SFrank Schaefer 	return rc;
490a3ea4bf9SFrank Schaefer }
491a3ea4bf9SFrank Schaefer 
492a3ea4bf9SFrank Schaefer /*
4930c0d06caSMauro Carvalho Chehab  * em28xx_i2c_xfer()
4940c0d06caSMauro Carvalho Chehab  * the main i2c transfer function
4950c0d06caSMauro Carvalho Chehab  */
4960c0d06caSMauro Carvalho Chehab static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
4970c0d06caSMauro Carvalho Chehab 			   struct i2c_msg msgs[], int num)
4980c0d06caSMauro Carvalho Chehab {
499aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
500aab3125cSMauro Carvalho Chehab 	struct em28xx *dev = i2c_bus->dev;
501aab3125cSMauro Carvalho Chehab 	unsigned bus = i2c_bus->bus;
502a3ea4bf9SFrank Schaefer 	int addr, rc, i;
5033190fbeeSMauro Carvalho Chehab 	u8 reg;
5040c0d06caSMauro Carvalho Chehab 
505cc5c5d20SShuah Khan 	/* prevent i2c xfer attempts after device is disconnected
506cc5c5d20SShuah Khan 	   some fe's try to do i2c writes/reads from their release
507cc5c5d20SShuah Khan 	   interfaces when called in disconnect path */
508cc5c5d20SShuah Khan 	if (dev->disconnected)
509cc5c5d20SShuah Khan 		return -ENODEV;
510cc5c5d20SShuah Khan 
511e44c153bSDan Carpenter 	if (!rt_mutex_trylock(&dev->i2c_bus_lock))
512e44c153bSDan Carpenter 		return -EAGAIN;
513aab3125cSMauro Carvalho Chehab 
514aab3125cSMauro Carvalho Chehab 	/* Switch I2C bus if needed */
515a3ea4bf9SFrank Schaefer 	if (bus != dev->cur_i2c_bus &&
516a3ea4bf9SFrank Schaefer 	    i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) {
517aab3125cSMauro Carvalho Chehab 		if (bus == 1)
5183190fbeeSMauro Carvalho Chehab 			reg = EM2874_I2C_SECONDARY_BUS_SELECT;
519aab3125cSMauro Carvalho Chehab 		else
5203190fbeeSMauro Carvalho Chehab 			reg = 0;
5213190fbeeSMauro Carvalho Chehab 		em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg,
5223190fbeeSMauro Carvalho Chehab 				      EM2874_I2C_SECONDARY_BUS_SELECT);
523aab3125cSMauro Carvalho Chehab 		dev->cur_i2c_bus = bus;
524aab3125cSMauro Carvalho Chehab 	}
525aab3125cSMauro Carvalho Chehab 
526aab3125cSMauro Carvalho Chehab 	if (num <= 0) {
527aab3125cSMauro Carvalho Chehab 		rt_mutex_unlock(&dev->i2c_bus_lock);
5280c0d06caSMauro Carvalho Chehab 		return 0;
529aab3125cSMauro Carvalho Chehab 	}
5300c0d06caSMauro Carvalho Chehab 	for (i = 0; i < num; i++) {
5310c0d06caSMauro Carvalho Chehab 		addr = msgs[i].addr << 1;
53250f0a9dfSMauro Carvalho Chehab 		if (i2c_debug > 1)
533d7a80eaaSFrank Schaefer 			printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:",
534d7a80eaaSFrank Schaefer 			       dev->name, __func__ ,
5350c0d06caSMauro Carvalho Chehab 			       (msgs[i].flags & I2C_M_RD) ? "read" : "write",
536d7a80eaaSFrank Schaefer 			       i == num - 1 ? "stop" : "nonstop",
537d7a80eaaSFrank Schaefer 			       addr, msgs[i].len);
538e63b009dSMauro Carvalho Chehab 		if (!msgs[i].len) {
539e63b009dSMauro Carvalho Chehab 			/*
540e63b009dSMauro Carvalho Chehab 			 * no len: check only for device presence
541e63b009dSMauro Carvalho Chehab 			 * This code is only called during device probe.
542e63b009dSMauro Carvalho Chehab 			 */
543a3ea4bf9SFrank Schaefer 			rc = i2c_check_for_device(i2c_bus, addr);
54450f0a9dfSMauro Carvalho Chehab 			if (rc < 0) {
545e63b009dSMauro Carvalho Chehab 				if (rc == -ENXIO) {
54650f0a9dfSMauro Carvalho Chehab 					if (i2c_debug > 1)
54750f0a9dfSMauro Carvalho Chehab 						printk(KERN_CONT " no device\n");
54850f0a9dfSMauro Carvalho Chehab 					rc = -ENODEV;
54950f0a9dfSMauro Carvalho Chehab 				} else {
55050f0a9dfSMauro Carvalho Chehab 					if (i2c_debug > 1)
55150f0a9dfSMauro Carvalho Chehab 						printk(KERN_CONT " ERROR: %i\n", rc);
55250f0a9dfSMauro Carvalho Chehab 				}
553aab3125cSMauro Carvalho Chehab 				rt_mutex_unlock(&dev->i2c_bus_lock);
55450f0a9dfSMauro Carvalho Chehab 				return rc;
5550c0d06caSMauro Carvalho Chehab 			}
5560c0d06caSMauro Carvalho Chehab 		} else if (msgs[i].flags & I2C_M_RD) {
5570c0d06caSMauro Carvalho Chehab 			/* read bytes */
558a3ea4bf9SFrank Schaefer 			rc = i2c_recv_bytes(i2c_bus, msgs[i]);
55950f0a9dfSMauro Carvalho Chehab 
56050f0a9dfSMauro Carvalho Chehab 			if (i2c_debug > 1 && rc >= 0)
56150f0a9dfSMauro Carvalho Chehab 				printk(KERN_CONT " %*ph",
56250f0a9dfSMauro Carvalho Chehab 				       msgs[i].len, msgs[i].buf);
5630c0d06caSMauro Carvalho Chehab 		} else {
56450f0a9dfSMauro Carvalho Chehab 			if (i2c_debug > 1)
56550f0a9dfSMauro Carvalho Chehab 				printk(KERN_CONT " %*ph",
56650f0a9dfSMauro Carvalho Chehab 				       msgs[i].len, msgs[i].buf);
56750f0a9dfSMauro Carvalho Chehab 
5680c0d06caSMauro Carvalho Chehab 			/* write bytes */
569a3ea4bf9SFrank Schaefer 			rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1);
5700c0d06caSMauro Carvalho Chehab 		}
57145f04e82SFrank Schaefer 		if (rc < 0) {
57250f0a9dfSMauro Carvalho Chehab 			if (i2c_debug > 1)
57350f0a9dfSMauro Carvalho Chehab 				printk(KERN_CONT " ERROR: %i\n", rc);
574aab3125cSMauro Carvalho Chehab 			rt_mutex_unlock(&dev->i2c_bus_lock);
57545f04e82SFrank Schaefer 			return rc;
57645f04e82SFrank Schaefer 		}
57750f0a9dfSMauro Carvalho Chehab 		if (i2c_debug > 1)
57850f0a9dfSMauro Carvalho Chehab 			printk(KERN_CONT "\n");
5790c0d06caSMauro Carvalho Chehab 	}
5800c0d06caSMauro Carvalho Chehab 
581aab3125cSMauro Carvalho Chehab 	rt_mutex_unlock(&dev->i2c_bus_lock);
5820c0d06caSMauro Carvalho Chehab 	return num;
5830c0d06caSMauro Carvalho Chehab }
5840c0d06caSMauro Carvalho Chehab 
585fa74aca3SFrank Schaefer /*
586fa74aca3SFrank Schaefer  * based on linux/sunrpc/svcauth.h and linux/hash.h
5870c0d06caSMauro Carvalho Chehab  * The original hash function returns a different value, if arch is x86_64
5880c0d06caSMauro Carvalho Chehab  * or i386.
5890c0d06caSMauro Carvalho Chehab  */
5900c0d06caSMauro Carvalho Chehab static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
5910c0d06caSMauro Carvalho Chehab {
5920c0d06caSMauro Carvalho Chehab 	unsigned long hash = 0;
5930c0d06caSMauro Carvalho Chehab 	unsigned long l = 0;
5940c0d06caSMauro Carvalho Chehab 	int len = 0;
5950c0d06caSMauro Carvalho Chehab 	unsigned char c;
596fdf1bc9fSMauro Carvalho Chehab 
5970c0d06caSMauro Carvalho Chehab 	do {
5980c0d06caSMauro Carvalho Chehab 		if (len == length) {
5990c0d06caSMauro Carvalho Chehab 			c = (char)len;
6000c0d06caSMauro Carvalho Chehab 			len = -1;
6010c0d06caSMauro Carvalho Chehab 		} else
6020c0d06caSMauro Carvalho Chehab 			c = *buf++;
6030c0d06caSMauro Carvalho Chehab 		l = (l << 8) | c;
6040c0d06caSMauro Carvalho Chehab 		len++;
6050c0d06caSMauro Carvalho Chehab 		if ((len & (32 / 8 - 1)) == 0)
6060c0d06caSMauro Carvalho Chehab 			hash = ((hash^l) * 0x9e370001UL);
6070c0d06caSMauro Carvalho Chehab 	} while (len);
6080c0d06caSMauro Carvalho Chehab 
6090c0d06caSMauro Carvalho Chehab 	return (hash >> (32 - bits)) & 0xffffffffUL;
6100c0d06caSMauro Carvalho Chehab }
6110c0d06caSMauro Carvalho Chehab 
612fa74aca3SFrank Schaefer /*
613fa74aca3SFrank Schaefer  * Helper function to read data blocks from i2c clients with 8 or 16 bit
614fa74aca3SFrank Schaefer  * address width, 8 bit register width and auto incrementation been activated
615fa74aca3SFrank Schaefer  */
616aab3125cSMauro Carvalho Chehab static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
617aab3125cSMauro Carvalho Chehab 				 bool addr_w16, u16 len, u8 *data)
618d832c5b2SFrank Schaefer {
619d832c5b2SFrank Schaefer 	int remain = len, rsize, rsize_max, ret;
620d832c5b2SFrank Schaefer 	u8 buf[2];
621d832c5b2SFrank Schaefer 
622d832c5b2SFrank Schaefer 	/* Sanity check */
623d832c5b2SFrank Schaefer 	if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1))
624d832c5b2SFrank Schaefer 		return -EINVAL;
625d832c5b2SFrank Schaefer 	/* Select address */
626d832c5b2SFrank Schaefer 	buf[0] = addr >> 8;
627d832c5b2SFrank Schaefer 	buf[1] = addr & 0xff;
628aab3125cSMauro Carvalho Chehab 	ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16);
629d832c5b2SFrank Schaefer 	if (ret < 0)
630d832c5b2SFrank Schaefer 		return ret;
631d832c5b2SFrank Schaefer 	/* Read data */
632d832c5b2SFrank Schaefer 	if (dev->board.is_em2800)
633d832c5b2SFrank Schaefer 		rsize_max = 4;
634d832c5b2SFrank Schaefer 	else
635d832c5b2SFrank Schaefer 		rsize_max = 64;
636d832c5b2SFrank Schaefer 	while (remain > 0) {
637d832c5b2SFrank Schaefer 		if (remain > rsize_max)
638d832c5b2SFrank Schaefer 			rsize = rsize_max;
639d832c5b2SFrank Schaefer 		else
640d832c5b2SFrank Schaefer 			rsize = remain;
641d832c5b2SFrank Schaefer 
642aab3125cSMauro Carvalho Chehab 		ret = i2c_master_recv(&dev->i2c_client[bus], data, rsize);
643d832c5b2SFrank Schaefer 		if (ret < 0)
644d832c5b2SFrank Schaefer 			return ret;
645d832c5b2SFrank Schaefer 
646d832c5b2SFrank Schaefer 		remain -= rsize;
647d832c5b2SFrank Schaefer 		data += rsize;
648d832c5b2SFrank Schaefer 	}
649d832c5b2SFrank Schaefer 
650d832c5b2SFrank Schaefer 	return len;
651d832c5b2SFrank Schaefer }
652d832c5b2SFrank Schaefer 
653aab3125cSMauro Carvalho Chehab static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
654aab3125cSMauro Carvalho Chehab 			     u8 **eedata, u16 *eedata_len)
6550c0d06caSMauro Carvalho Chehab {
656510e884cSFrank Schaefer 	const u16 len = 256;
657fa74aca3SFrank Schaefer 	/*
658fa74aca3SFrank Schaefer 	 * FIXME common length/size for bytes to read, to display, hash
659510e884cSFrank Schaefer 	 * calculation and returned device dataset. Simplifies the code a lot,
660fa74aca3SFrank Schaefer 	 * but we might have to deal with multiple sizes in the future !
661fa74aca3SFrank Schaefer 	 */
66250f0a9dfSMauro Carvalho Chehab 	int err;
663510e884cSFrank Schaefer 	struct em28xx_eeprom *dev_config;
664510e884cSFrank Schaefer 	u8 buf, *data;
6650c0d06caSMauro Carvalho Chehab 
666a217968fSFrank Schaefer 	*eedata = NULL;
667510e884cSFrank Schaefer 	*eedata_len = 0;
668a217968fSFrank Schaefer 
669aab3125cSMauro Carvalho Chehab 	/* EEPROM is always on i2c bus 0 on all known devices. */
670aab3125cSMauro Carvalho Chehab 
671aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].addr = 0xa0 >> 1;
6720c0d06caSMauro Carvalho Chehab 
6730c0d06caSMauro Carvalho Chehab 	/* Check if board has eeprom */
674aab3125cSMauro Carvalho Chehab 	err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
6750c0d06caSMauro Carvalho Chehab 	if (err < 0) {
676*8314d402SMauro Carvalho Chehab 		pr_info("board has no eeprom\n");
6770c0d06caSMauro Carvalho Chehab 		return -ENODEV;
6780c0d06caSMauro Carvalho Chehab 	}
6790c0d06caSMauro Carvalho Chehab 
680a217968fSFrank Schaefer 	data = kzalloc(len, GFP_KERNEL);
681a217968fSFrank Schaefer 	if (data == NULL)
682a217968fSFrank Schaefer 		return -ENOMEM;
683a217968fSFrank Schaefer 
684d832c5b2SFrank Schaefer 	/* Read EEPROM content */
685aab3125cSMauro Carvalho Chehab 	err = em28xx_i2c_read_block(dev, bus, 0x0000,
686aab3125cSMauro Carvalho Chehab 				    dev->eeprom_addrwidth_16bit,
687a217968fSFrank Schaefer 				    len, data);
688d832c5b2SFrank Schaefer 	if (err != len) {
689*8314d402SMauro Carvalho Chehab 		pr_err("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 */
69550f0a9dfSMauro Carvalho Chehab 		print_hex_dump(KERN_INFO, "eeprom ", DUMP_PREFIX_OFFSET,
69650f0a9dfSMauro Carvalho Chehab 			       16, 1, data, len, true);
69750f0a9dfSMauro Carvalho Chehab 
69887b52439SFrank Schaefer 		if (dev->eeprom_addrwidth_16bit)
699*8314d402SMauro Carvalho Chehab 			pr_info("eeprom %06x: ... (skipped)\n", 256);
70087b52439SFrank Schaefer 	}
7010c0d06caSMauro Carvalho Chehab 
70287b52439SFrank Schaefer 	if (dev->eeprom_addrwidth_16bit &&
703a217968fSFrank Schaefer 	    data[0] == 0x26 && data[3] == 0x00) {
70487b52439SFrank Schaefer 		/* new eeprom format; size 4-64kb */
705510e884cSFrank Schaefer 		u16 mc_start;
706510e884cSFrank Schaefer 		u16 hwconf_offset;
707510e884cSFrank Schaefer 
708a217968fSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
709510e884cSFrank Schaefer 		mc_start = (data[1] << 8) + 4;	/* usually 0x0004 */
710510e884cSFrank Schaefer 
711*8314d402SMauro Carvalho Chehab 		pr_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
712510e884cSFrank Schaefer 			    data[0], data[1], data[2], data[3], dev->hash);
713*8314d402SMauro Carvalho Chehab 		pr_info("EEPROM info:\n");
714*8314d402SMauro Carvalho Chehab 		pr_info("\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n",
715510e884cSFrank Schaefer 			    mc_start, data[2]);
716fa74aca3SFrank Schaefer 		/*
717fa74aca3SFrank Schaefer 		 * boot configuration (address 0x0002):
71887b52439SFrank Schaefer 		 * [0]   microcode download speed: 1 = 400 kHz; 0 = 100 kHz
71987b52439SFrank Schaefer 		 * [1]   always selects 12 kb RAM
72087b52439SFrank Schaefer 		 * [2]   USB device speed: 1 = force Full Speed; 0 = auto detect
72187b52439SFrank Schaefer 		 * [4]   1 = force fast mode and no suspend for device testing
72287b52439SFrank Schaefer 		 * [5:7] USB PHY tuning registers; determined by device
72387b52439SFrank Schaefer 		 *       characterization
72487b52439SFrank Schaefer 		 */
72587b52439SFrank Schaefer 
726fa74aca3SFrank Schaefer 		/*
727fa74aca3SFrank Schaefer 		 * Read hardware config dataset offset from address
728fa74aca3SFrank Schaefer 		 * (microcode start + 46)
729fa74aca3SFrank Schaefer 		 */
730aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2,
731aab3125cSMauro Carvalho Chehab 					    data);
732510e884cSFrank Schaefer 		if (err != 2) {
733*8314d402SMauro Carvalho Chehab 			pr_err("failed to read hardware configuration data from eeprom (err=%d)\n",
734510e884cSFrank Schaefer 				      err);
735510e884cSFrank Schaefer 			goto error;
736510e884cSFrank Schaefer 		}
73787b52439SFrank Schaefer 
738510e884cSFrank Schaefer 		/* Calculate hardware config dataset start address */
739510e884cSFrank Schaefer 		hwconf_offset = mc_start + data[0] + (data[1] << 8);
740510e884cSFrank Schaefer 
741510e884cSFrank Schaefer 		/* Read hardware config dataset */
742fa74aca3SFrank Schaefer 		/*
743fa74aca3SFrank Schaefer 		 * NOTE: the microcode copy can be multiple pages long, but
744510e884cSFrank Schaefer 		 * we assume the hardware config dataset is the same as in
745510e884cSFrank Schaefer 		 * the old eeprom and not longer than 256 bytes.
746510e884cSFrank Schaefer 		 * tveeprom is currently also limited to 256 bytes.
747510e884cSFrank Schaefer 		 */
748aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len,
749aab3125cSMauro Carvalho Chehab 					    data);
750510e884cSFrank Schaefer 		if (err != len) {
751*8314d402SMauro Carvalho Chehab 			pr_err("failed to read hardware configuration data from eeprom (err=%d)\n",
752510e884cSFrank Schaefer 				      err);
753510e884cSFrank Schaefer 			goto error;
754510e884cSFrank Schaefer 		}
755510e884cSFrank Schaefer 
756510e884cSFrank Schaefer 		/* Verify hardware config dataset */
757510e884cSFrank Schaefer 		/* NOTE: not all devices provide this type of dataset */
758510e884cSFrank Schaefer 		if (data[0] != 0x1a || data[1] != 0xeb ||
759a217968fSFrank Schaefer 		    data[2] != 0x67 || data[3] != 0x95) {
760*8314d402SMauro Carvalho Chehab 			pr_info("\tno hardware configuration dataset found in eeprom\n");
761510e884cSFrank Schaefer 			kfree(data);
762510e884cSFrank Schaefer 			return 0;
763510e884cSFrank Schaefer 		}
764510e884cSFrank Schaefer 
765510e884cSFrank Schaefer 		/* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */
766510e884cSFrank Schaefer 
767510e884cSFrank Schaefer 	} else if (!dev->eeprom_addrwidth_16bit &&
768510e884cSFrank Schaefer 		   data[0] == 0x1a && data[1] == 0xeb &&
769510e884cSFrank Schaefer 		   data[2] == 0x67 && data[3] == 0x95) {
770510e884cSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
771*8314d402SMauro Carvalho Chehab 		pr_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
772510e884cSFrank Schaefer 			    data[0], data[1], data[2], data[3], dev->hash);
773*8314d402SMauro Carvalho Chehab 		pr_info("EEPROM info:\n");
774510e884cSFrank Schaefer 	} else {
775*8314d402SMauro Carvalho Chehab 		pr_info("unknown eeprom format or eeprom corrupted !\n");
776510e884cSFrank Schaefer 		err = -ENODEV;
777510e884cSFrank Schaefer 		goto error;
778f55eacbeSFrank Schaefer 	}
779f55eacbeSFrank Schaefer 
780a217968fSFrank Schaefer 	*eedata = data;
781510e884cSFrank Schaefer 	*eedata_len = len;
78232bf7c6cSAlban Browaeys 	dev_config = (void *)*eedata;
783a217968fSFrank Schaefer 
784510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
7850c0d06caSMauro Carvalho Chehab 	case 0:
786*8314d402SMauro Carvalho Chehab 		pr_info("\tNo audio on board.\n");
7870c0d06caSMauro Carvalho Chehab 		break;
7880c0d06caSMauro Carvalho Chehab 	case 1:
789*8314d402SMauro Carvalho Chehab 		pr_info("\tAC97 audio (5 sample rates)\n");
7900c0d06caSMauro Carvalho Chehab 		break;
7910c0d06caSMauro Carvalho Chehab 	case 2:
792687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
793*8314d402SMauro Carvalho Chehab 			pr_info("\tI2S audio, sample rate=32k\n");
794687ff8b0SFrank Schaefer 		else
795*8314d402SMauro Carvalho Chehab 			pr_info("\tI2S audio, 3 sample rates\n");
7960c0d06caSMauro Carvalho Chehab 		break;
7970c0d06caSMauro Carvalho Chehab 	case 3:
798687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
799*8314d402SMauro Carvalho Chehab 			pr_info("\tI2S audio, 3 sample rates\n");
800687ff8b0SFrank Schaefer 		else
801*8314d402SMauro Carvalho Chehab 			pr_info("\tI2S audio, 5 sample rates\n");
8020c0d06caSMauro Carvalho Chehab 		break;
8030c0d06caSMauro Carvalho Chehab 	}
8040c0d06caSMauro Carvalho Chehab 
805510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 3)
806*8314d402SMauro Carvalho Chehab 		pr_info("\tUSB Remote wakeup capable\n");
8070c0d06caSMauro Carvalho Chehab 
808510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 2)
809*8314d402SMauro Carvalho Chehab 		pr_info("\tUSB Self power capable\n");
8100c0d06caSMauro Carvalho Chehab 
811510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) & 0x3) {
8120c0d06caSMauro Carvalho Chehab 	case 0:
813*8314d402SMauro Carvalho Chehab 		pr_info("\t500mA max power\n");
8140c0d06caSMauro Carvalho Chehab 		break;
8150c0d06caSMauro Carvalho Chehab 	case 1:
816*8314d402SMauro Carvalho Chehab 		pr_info("\t400mA max power\n");
8170c0d06caSMauro Carvalho Chehab 		break;
8180c0d06caSMauro Carvalho Chehab 	case 2:
819*8314d402SMauro Carvalho Chehab 		pr_info("\t300mA max power\n");
8200c0d06caSMauro Carvalho Chehab 		break;
8210c0d06caSMauro Carvalho Chehab 	case 3:
822*8314d402SMauro Carvalho Chehab 		pr_info("\t200mA max power\n");
8230c0d06caSMauro Carvalho Chehab 		break;
8240c0d06caSMauro Carvalho Chehab 	}
825*8314d402SMauro Carvalho Chehab 	pr_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
826510e884cSFrank Schaefer 		    dev_config->string_idx_table,
827510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string1),
828510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string2),
829510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string3));
8300c0d06caSMauro Carvalho Chehab 
8310c0d06caSMauro Carvalho Chehab 	return 0;
832510e884cSFrank Schaefer 
833510e884cSFrank Schaefer error:
834510e884cSFrank Schaefer 	kfree(data);
835510e884cSFrank Schaefer 	return err;
8360c0d06caSMauro Carvalho Chehab }
8370c0d06caSMauro Carvalho Chehab 
8380c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
8390c0d06caSMauro Carvalho Chehab 
8400c0d06caSMauro Carvalho Chehab /*
8410c0d06caSMauro Carvalho Chehab  * functionality()
8420c0d06caSMauro Carvalho Chehab  */
843aab3125cSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *i2c_adap)
8440c0d06caSMauro Carvalho Chehab {
845aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
846aab3125cSMauro Carvalho Chehab 
847a3ea4bf9SFrank Schaefer 	if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) ||
848a3ea4bf9SFrank Schaefer 	    (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) {
849a3ea4bf9SFrank Schaefer 		return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
850a3ea4bf9SFrank Schaefer 	} else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)  {
851a3ea4bf9SFrank Schaefer 		return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) &
852a3ea4bf9SFrank Schaefer 			~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
853a3ea4bf9SFrank Schaefer 	}
854a3ea4bf9SFrank Schaefer 
855a3ea4bf9SFrank Schaefer 	WARN(1, "Unknown i2c bus algorithm.\n");
856a3ea4bf9SFrank Schaefer 	return 0;
8570c0d06caSMauro Carvalho Chehab }
8580c0d06caSMauro Carvalho Chehab 
85978f2c50bSJulia Lawall static const struct i2c_algorithm em28xx_algo = {
8600c0d06caSMauro Carvalho Chehab 	.master_xfer   = em28xx_i2c_xfer,
8610c0d06caSMauro Carvalho Chehab 	.functionality = functionality,
8620c0d06caSMauro Carvalho Chehab };
8630c0d06caSMauro Carvalho Chehab 
8640c0d06caSMauro Carvalho Chehab static struct i2c_adapter em28xx_adap_template = {
8650c0d06caSMauro Carvalho Chehab 	.owner = THIS_MODULE,
8660c0d06caSMauro Carvalho Chehab 	.name = "em28xx",
8670c0d06caSMauro Carvalho Chehab 	.algo = &em28xx_algo,
8680c0d06caSMauro Carvalho Chehab };
8690c0d06caSMauro Carvalho Chehab 
8700c0d06caSMauro Carvalho Chehab static struct i2c_client em28xx_client_template = {
8710c0d06caSMauro Carvalho Chehab 	.name = "em28xx internal",
8720c0d06caSMauro Carvalho Chehab };
8730c0d06caSMauro Carvalho Chehab 
8740c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
8750c0d06caSMauro Carvalho Chehab 
8760c0d06caSMauro Carvalho Chehab /*
8770c0d06caSMauro Carvalho Chehab  * i2c_devs
8780c0d06caSMauro Carvalho Chehab  * incomplete list of known devices
8790c0d06caSMauro Carvalho Chehab  */
8800c0d06caSMauro Carvalho Chehab static char *i2c_devs[128] = {
8819aa785b1SWilson Michaels        [0x1c >> 1] = "lgdt330x",
8820b3966e4SFrank Schaefer 	[0x3e >> 1] = "remote IR sensor",
8830c0d06caSMauro Carvalho Chehab 	[0x4a >> 1] = "saa7113h",
8840c0d06caSMauro Carvalho Chehab 	[0x52 >> 1] = "drxk",
8850c0d06caSMauro Carvalho Chehab 	[0x60 >> 1] = "remote IR sensor",
8860c0d06caSMauro Carvalho Chehab 	[0x8e >> 1] = "remote IR sensor",
8870c0d06caSMauro Carvalho Chehab 	[0x86 >> 1] = "tda9887",
8880c0d06caSMauro Carvalho Chehab 	[0x80 >> 1] = "msp34xx",
8890c0d06caSMauro Carvalho Chehab 	[0x88 >> 1] = "msp34xx",
8900c0d06caSMauro Carvalho Chehab 	[0xa0 >> 1] = "eeprom",
8910c0d06caSMauro Carvalho Chehab 	[0xb0 >> 1] = "tda9874",
8920c0d06caSMauro Carvalho Chehab 	[0xb8 >> 1] = "tvp5150a",
8930c0d06caSMauro Carvalho Chehab 	[0xba >> 1] = "webcam sensor or tvp5150a",
8940c0d06caSMauro Carvalho Chehab 	[0xc0 >> 1] = "tuner (analog)",
8950c0d06caSMauro Carvalho Chehab 	[0xc2 >> 1] = "tuner (analog)",
8960c0d06caSMauro Carvalho Chehab 	[0xc4 >> 1] = "tuner (analog)",
8970c0d06caSMauro Carvalho Chehab 	[0xc6 >> 1] = "tuner (analog)",
8980c0d06caSMauro Carvalho Chehab };
8990c0d06caSMauro Carvalho Chehab 
9000c0d06caSMauro Carvalho Chehab /*
9010c0d06caSMauro Carvalho Chehab  * do_i2c_scan()
9020c0d06caSMauro Carvalho Chehab  * check i2c address range for devices
9030c0d06caSMauro Carvalho Chehab  */
904aab3125cSMauro Carvalho Chehab void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus)
9050c0d06caSMauro Carvalho Chehab {
9060c0d06caSMauro Carvalho Chehab 	u8 i2c_devicelist[128];
9070c0d06caSMauro Carvalho Chehab 	unsigned char buf;
9080c0d06caSMauro Carvalho Chehab 	int i, rc;
9090c0d06caSMauro Carvalho Chehab 
9100c0d06caSMauro Carvalho Chehab 	memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
9110c0d06caSMauro Carvalho Chehab 
9120c0d06caSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
913aab3125cSMauro Carvalho Chehab 		dev->i2c_client[bus].addr = i;
914aab3125cSMauro Carvalho Chehab 		rc = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
9150c0d06caSMauro Carvalho Chehab 		if (rc < 0)
9160c0d06caSMauro Carvalho Chehab 			continue;
9170c0d06caSMauro Carvalho Chehab 		i2c_devicelist[i] = i;
918*8314d402SMauro Carvalho Chehab 		pr_info("found i2c device @ 0x%x on bus %d [%s]\n",
919aab3125cSMauro Carvalho Chehab 			    i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???");
9200c0d06caSMauro Carvalho Chehab 	}
9210c0d06caSMauro Carvalho Chehab 
922aab3125cSMauro Carvalho Chehab 	if (bus == dev->def_i2c_bus)
9230c0d06caSMauro Carvalho Chehab 		dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
9240c0d06caSMauro Carvalho Chehab 						ARRAY_SIZE(i2c_devicelist), 32);
9250c0d06caSMauro Carvalho Chehab }
9260c0d06caSMauro Carvalho Chehab 
9270c0d06caSMauro Carvalho Chehab /*
9280c0d06caSMauro Carvalho Chehab  * em28xx_i2c_register()
9290c0d06caSMauro Carvalho Chehab  * register i2c bus
9300c0d06caSMauro Carvalho Chehab  */
931a3ea4bf9SFrank Schaefer int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
932a3ea4bf9SFrank Schaefer 			enum em28xx_i2c_algo_type algo_type)
9330c0d06caSMauro Carvalho Chehab {
9340c0d06caSMauro Carvalho Chehab 	int retval;
9350c0d06caSMauro Carvalho Chehab 
9360c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
9370c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
9380c0d06caSMauro Carvalho Chehab 
939aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
940aab3125cSMauro Carvalho Chehab 		return -ENODEV;
941aab3125cSMauro Carvalho Chehab 
942aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus] = em28xx_adap_template;
943aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].dev.parent = &dev->udev->dev;
944aab3125cSMauro Carvalho Chehab 	strcpy(dev->i2c_adap[bus].name, dev->name);
945aab3125cSMauro Carvalho Chehab 
946aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].bus = bus;
947a3ea4bf9SFrank Schaefer 	dev->i2c_bus[bus].algo_type = algo_type;
948aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].dev = dev;
949aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus];
950aab3125cSMauro Carvalho Chehab 
951aab3125cSMauro Carvalho Chehab 	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
9520c0d06caSMauro Carvalho Chehab 	if (retval < 0) {
953*8314d402SMauro Carvalho Chehab 		pr_err("%s: i2c_add_adapter failed! retval [%d]\n",
9540c0d06caSMauro Carvalho Chehab 			      __func__, retval);
9550c0d06caSMauro Carvalho Chehab 		return retval;
9560c0d06caSMauro Carvalho Chehab 	}
9570c0d06caSMauro Carvalho Chehab 
958aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus] = em28xx_client_template;
959aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].adapter = &dev->i2c_adap[bus];
9600c0d06caSMauro Carvalho Chehab 
961aab3125cSMauro Carvalho Chehab 	/* Up to now, all eeproms are at bus 0 */
962aab3125cSMauro Carvalho Chehab 	if (!bus) {
963aab3125cSMauro Carvalho Chehab 		retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
9640c0d06caSMauro Carvalho Chehab 		if ((retval < 0) && (retval != -ENODEV)) {
965*8314d402SMauro Carvalho Chehab 			pr_err("%s: em28xx_i2_eeprom failed! retval [%d]\n",
9660c0d06caSMauro Carvalho Chehab 				      __func__, retval);
9670c0d06caSMauro Carvalho Chehab 
9680c0d06caSMauro Carvalho Chehab 			return retval;
9690c0d06caSMauro Carvalho Chehab 		}
970aab3125cSMauro Carvalho Chehab 	}
9710c0d06caSMauro Carvalho Chehab 
9720c0d06caSMauro Carvalho Chehab 	if (i2c_scan)
973aab3125cSMauro Carvalho Chehab 		em28xx_do_i2c_scan(dev, bus);
9740c0d06caSMauro Carvalho Chehab 
9750c0d06caSMauro Carvalho Chehab 	return 0;
9760c0d06caSMauro Carvalho Chehab }
9770c0d06caSMauro Carvalho Chehab 
9780c0d06caSMauro Carvalho Chehab /*
9790c0d06caSMauro Carvalho Chehab  * em28xx_i2c_unregister()
9800c0d06caSMauro Carvalho Chehab  * unregister i2c_bus
9810c0d06caSMauro Carvalho Chehab  */
982aab3125cSMauro Carvalho Chehab int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus)
9830c0d06caSMauro Carvalho Chehab {
984aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
985aab3125cSMauro Carvalho Chehab 		return -ENODEV;
986aab3125cSMauro Carvalho Chehab 
987aab3125cSMauro Carvalho Chehab 	i2c_del_adapter(&dev->i2c_adap[bus]);
9880c0d06caSMauro Carvalho Chehab 	return 0;
9890c0d06caSMauro Carvalho Chehab }
990