xref: /openbmc/linux/drivers/media/usb/em28xx/em28xx-i2c.c (revision 4b83626ac29a66fce15256771dd550e8c4ea2c66)
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>
29*4b83626aSMauro 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);
440c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
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 {
52*4b83626aSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM2800_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 */
78*4b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
790c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
80*4b83626aSMauro Carvalho Chehab 		if (ret == 0x80 + len - 1)
810c0d06caSMauro Carvalho Chehab 			return len;
82*4b83626aSMauro Carvalho Chehab 		if (ret == 0x94 + len - 1) {
8345f04e82SFrank Schaefer 			return -ENODEV;
84*4b83626aSMauro Carvalho Chehab 		}
85*4b83626aSMauro Carvalho Chehab 		if (ret < 0) {
86d230d5adSFrank Schaefer 			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
87d230d5adSFrank Schaefer 				    ret);
8845f04e82SFrank Schaefer 			return ret;
8945f04e82SFrank Schaefer 		}
900c0d06caSMauro Carvalho Chehab 		msleep(5);
910c0d06caSMauro Carvalho Chehab 	}
9245f04e82SFrank Schaefer 	em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
930c0d06caSMauro Carvalho Chehab 	return -EIO;
940c0d06caSMauro Carvalho Chehab }
950c0d06caSMauro Carvalho Chehab 
960c0d06caSMauro Carvalho Chehab /*
970c0d06caSMauro Carvalho Chehab  * em2800_i2c_recv_bytes()
982fcc82d8SFrank Schaefer  * read up to 4 bytes from the em2800 i2c device
990c0d06caSMauro Carvalho Chehab  */
100a6bad040SFrank Schaefer static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
1010c0d06caSMauro Carvalho Chehab {
102*4b83626aSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM2800_I2C_XFER_TIMEOUT);
1032fcc82d8SFrank Schaefer 	u8 buf2[4];
1040c0d06caSMauro Carvalho Chehab 	int ret;
1052fcc82d8SFrank Schaefer 	int i;
106f5ae371aSFrank Schaefer 
107f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
108f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
109f5ae371aSFrank Schaefer 
1102fcc82d8SFrank Schaefer 	/* trigger read */
1112fcc82d8SFrank Schaefer 	buf2[1] = 0x84 + len - 1;
1122fcc82d8SFrank Schaefer 	buf2[0] = addr;
1132fcc82d8SFrank Schaefer 	ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
1142fcc82d8SFrank Schaefer 	if (ret != 2) {
115d230d5adSFrank Schaefer 		em28xx_warn("failed to trigger read from i2c address 0x%x (error=%i)\n",
116d230d5adSFrank Schaefer 			    addr, ret);
1172fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1182fcc82d8SFrank Schaefer 	}
1192fcc82d8SFrank Schaefer 
1202fcc82d8SFrank Schaefer 	/* wait for completion */
121*4b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
1222fcc82d8SFrank Schaefer 		ret = dev->em28xx_read_reg(dev, 0x05);
123*4b83626aSMauro Carvalho Chehab 		if (ret == 0x84 + len - 1)
1242fcc82d8SFrank Schaefer 			break;
125*4b83626aSMauro Carvalho Chehab 		if (ret == 0x94 + len - 1) {
1262fcc82d8SFrank Schaefer 			return -ENODEV;
127*4b83626aSMauro Carvalho Chehab 		}
128*4b83626aSMauro Carvalho Chehab 		if (ret < 0) {
129d230d5adSFrank Schaefer 			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
130d230d5adSFrank Schaefer 				    ret);
1310c0d06caSMauro Carvalho Chehab 			return ret;
1320c0d06caSMauro Carvalho Chehab 		}
1332fcc82d8SFrank Schaefer 		msleep(5);
1342fcc82d8SFrank Schaefer 	}
1352fcc82d8SFrank Schaefer 	if (ret != 0x84 + len - 1)
1362fcc82d8SFrank Schaefer 		em28xx_warn("read from i2c device at 0x%x timed out\n", addr);
1372fcc82d8SFrank Schaefer 
1382fcc82d8SFrank Schaefer 	/* get the received message */
1392fcc82d8SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
1402fcc82d8SFrank Schaefer 	if (ret != len) {
141d230d5adSFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
142d230d5adSFrank Schaefer 			    addr, ret);
1432fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1442fcc82d8SFrank Schaefer 	}
1452fcc82d8SFrank Schaefer 	for (i = 0; i < len; i++)
1462fcc82d8SFrank Schaefer 		buf[i] = buf2[len - 1 - i];
1472fcc82d8SFrank Schaefer 
1480c0d06caSMauro Carvalho Chehab 	return ret;
1490c0d06caSMauro Carvalho Chehab }
1502fcc82d8SFrank Schaefer 
1512fcc82d8SFrank Schaefer /*
1522fcc82d8SFrank Schaefer  * em2800_i2c_check_for_device()
1532fcc82d8SFrank Schaefer  * check if there is an i2c device at the supplied address
1542fcc82d8SFrank Schaefer  */
1552fcc82d8SFrank Schaefer static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
1562fcc82d8SFrank Schaefer {
1572fcc82d8SFrank Schaefer 	u8 buf;
1582fcc82d8SFrank Schaefer 	int ret;
1592fcc82d8SFrank Schaefer 
1602fcc82d8SFrank Schaefer 	ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1);
1612fcc82d8SFrank Schaefer 	if (ret == 1)
1622fcc82d8SFrank Schaefer 		return 0;
1632fcc82d8SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
1640c0d06caSMauro Carvalho Chehab }
1650c0d06caSMauro Carvalho Chehab 
1660c0d06caSMauro Carvalho Chehab /*
1670c0d06caSMauro Carvalho Chehab  * em28xx_i2c_send_bytes()
1680c0d06caSMauro Carvalho Chehab  */
169a6bad040SFrank Schaefer static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
170a6bad040SFrank Schaefer 				 u16 len, int stop)
1710c0d06caSMauro Carvalho Chehab {
172*4b83626aSMauro Carvalho Chehab 	unsigned long timeout = jiffies + msecs_to_jiffies(EM2800_I2C_XFER_TIMEOUT);
173*4b83626aSMauro Carvalho Chehab 	int ret;
1740c0d06caSMauro Carvalho Chehab 
175f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
176f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
177fa74aca3SFrank Schaefer 	/*
178fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
179fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
180fa74aca3SFrank Schaefer 	 */
181f5ae371aSFrank Schaefer 
18245f04e82SFrank Schaefer 	/* Write to i2c device */
18345f04e82SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
18445f04e82SFrank Schaefer 	if (ret != len) {
18545f04e82SFrank Schaefer 		if (ret < 0) {
186d230d5adSFrank Schaefer 			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
187d230d5adSFrank Schaefer 				    addr, ret);
18845f04e82SFrank Schaefer 			return ret;
18945f04e82SFrank Schaefer 		} else {
190d230d5adSFrank Schaefer 			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
19145f04e82SFrank Schaefer 				    len, addr, ret);
19245f04e82SFrank Schaefer 			return -EIO;
19345f04e82SFrank Schaefer 		}
19445f04e82SFrank Schaefer 	}
1950c0d06caSMauro Carvalho Chehab 
196*4b83626aSMauro Carvalho Chehab 	/* wait for completion */
197*4b83626aSMauro Carvalho Chehab 	while (time_is_after_jiffies(timeout)) {
1980c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
199*4b83626aSMauro Carvalho Chehab 		if (ret == 0) /* success */
20045f04e82SFrank Schaefer 			return len;
201*4b83626aSMauro Carvalho Chehab 		if (ret == 0x10) {
20245f04e82SFrank Schaefer 			return -ENODEV;
203*4b83626aSMauro Carvalho Chehab 		}
204*4b83626aSMauro Carvalho Chehab 		if (ret < 0) {
205*4b83626aSMauro Carvalho Chehab 			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
206d230d5adSFrank Schaefer 				    ret);
20745f04e82SFrank Schaefer 			return ret;
2080c0d06caSMauro Carvalho Chehab 		}
20945f04e82SFrank Schaefer 		msleep(5);
210fa74aca3SFrank Schaefer 		/*
211fa74aca3SFrank Schaefer 		 * NOTE: do we really have to wait for success ?
212fa74aca3SFrank Schaefer 		 * Never seen anything else than 0x00 or 0x10
213fa74aca3SFrank Schaefer 		 * (even with high payload) ...
214fa74aca3SFrank Schaefer 		 */
21545f04e82SFrank Schaefer 	}
216*4b83626aSMauro Carvalho Chehab 
21745f04e82SFrank Schaefer 	em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
21845f04e82SFrank Schaefer 	return -EIO;
2190c0d06caSMauro Carvalho Chehab }
2200c0d06caSMauro Carvalho Chehab 
2210c0d06caSMauro Carvalho Chehab /*
2220c0d06caSMauro Carvalho Chehab  * em28xx_i2c_recv_bytes()
2230c0d06caSMauro Carvalho Chehab  * read a byte from the i2c device
2240c0d06caSMauro Carvalho Chehab  */
225a6bad040SFrank Schaefer static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
2260c0d06caSMauro Carvalho Chehab {
2270c0d06caSMauro Carvalho Chehab 	int ret;
228f5ae371aSFrank Schaefer 
229f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
230f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
231fa74aca3SFrank Schaefer 	/*
232fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
233fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
234fa74aca3SFrank Schaefer 	 */
235f5ae371aSFrank Schaefer 
23645f04e82SFrank Schaefer 	/* Read data from i2c device */
2370c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
2380c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
2397f6301d1SFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
2407f6301d1SFrank Schaefer 			    addr, ret);
24145f04e82SFrank Schaefer 		return ret;
24245f04e82SFrank Schaefer 	}
243fa74aca3SFrank Schaefer 	/*
244fa74aca3SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
2457f6301d1SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
2467f6301d1SFrank Schaefer 	 * specified slave address before AND no device is present at the
2477f6301d1SFrank Schaefer 	 * requested slave address.
2487f6301d1SFrank Schaefer 	 * Anyway, the next check will fail with -ENODEV in this case, so avoid
2497f6301d1SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
2507f6301d1SFrank Schaefer 	 */
25145f04e82SFrank Schaefer 
25245f04e82SFrank Schaefer 	/* Check success of the i2c operation */
25345f04e82SFrank Schaefer 	ret = dev->em28xx_read_reg(dev, 0x05);
254*4b83626aSMauro Carvalho Chehab 	if (ret == 0) /* success */
255*4b83626aSMauro Carvalho Chehab 		return len;
25645f04e82SFrank Schaefer 	if (ret < 0) {
257*4b83626aSMauro Carvalho Chehab 		em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
258d230d5adSFrank Schaefer 			    ret);
2590c0d06caSMauro Carvalho Chehab 		return ret;
2600c0d06caSMauro Carvalho Chehab 	}
261*4b83626aSMauro Carvalho Chehab 	if (ret == 0x10)
2620c0d06caSMauro Carvalho Chehab 		return -ENODEV;
263*4b83626aSMauro Carvalho Chehab 
26445f04e82SFrank Schaefer 	em28xx_warn("unknown i2c error (status=%i)\n", ret);
26545f04e82SFrank Schaefer 	return -EIO;
26645f04e82SFrank Schaefer }
2670c0d06caSMauro Carvalho Chehab 
2680c0d06caSMauro Carvalho Chehab /*
2690c0d06caSMauro Carvalho Chehab  * em28xx_i2c_check_for_device()
2700c0d06caSMauro Carvalho Chehab  * check if there is a i2c_device at the supplied address
2710c0d06caSMauro Carvalho Chehab  */
272a6bad040SFrank Schaefer static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
2730c0d06caSMauro Carvalho Chehab {
2740c0d06caSMauro Carvalho Chehab 	int ret;
27545f04e82SFrank Schaefer 	u8 buf;
2760c0d06caSMauro Carvalho Chehab 
27745f04e82SFrank Schaefer 	ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1);
27845f04e82SFrank Schaefer 	if (ret == 1)
2790c0d06caSMauro Carvalho Chehab 		return 0;
28045f04e82SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
2810c0d06caSMauro Carvalho Chehab }
2820c0d06caSMauro Carvalho Chehab 
2830c0d06caSMauro Carvalho Chehab /*
284a3ea4bf9SFrank Schaefer  * em25xx_bus_B_send_bytes
285a3ea4bf9SFrank Schaefer  * write bytes to the i2c device
286a3ea4bf9SFrank Schaefer  */
287a3ea4bf9SFrank Schaefer static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
288a3ea4bf9SFrank Schaefer 				   u16 len)
289a3ea4bf9SFrank Schaefer {
290a3ea4bf9SFrank Schaefer 	int ret;
291a3ea4bf9SFrank Schaefer 
292a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
293a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
294a3ea4bf9SFrank Schaefer 	/*
295a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
296a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
297a3ea4bf9SFrank Schaefer 	 */
298a3ea4bf9SFrank Schaefer 
299a3ea4bf9SFrank Schaefer 	/* Set register and write value */
300a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len);
301a3ea4bf9SFrank Schaefer 	if (ret != len) {
302a3ea4bf9SFrank Schaefer 		if (ret < 0) {
303a3ea4bf9SFrank Schaefer 			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
304a3ea4bf9SFrank Schaefer 				    addr, ret);
305a3ea4bf9SFrank Schaefer 			return ret;
306a3ea4bf9SFrank Schaefer 		} else {
307a3ea4bf9SFrank Schaefer 			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
308a3ea4bf9SFrank Schaefer 				    len, addr, ret);
309a3ea4bf9SFrank Schaefer 			return -EIO;
310a3ea4bf9SFrank Schaefer 		}
311a3ea4bf9SFrank Schaefer 	}
312a3ea4bf9SFrank Schaefer 	/* Check success */
313a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
314a3ea4bf9SFrank Schaefer 	/*
315a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
316a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
317a3ea4bf9SFrank Schaefer 	 */
318a3ea4bf9SFrank Schaefer 	if (!ret)
319a3ea4bf9SFrank Schaefer 		return len;
320a3ea4bf9SFrank Schaefer 	else if (ret > 0)
321a3ea4bf9SFrank Schaefer 		return -ENODEV;
322a3ea4bf9SFrank Schaefer 
323a3ea4bf9SFrank Schaefer 	return ret;
324a3ea4bf9SFrank Schaefer 	/*
325a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
326a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
327a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
328a3ea4bf9SFrank Schaefer 	 */
329a3ea4bf9SFrank Schaefer }
330a3ea4bf9SFrank Schaefer 
331a3ea4bf9SFrank Schaefer /*
332a3ea4bf9SFrank Schaefer  * em25xx_bus_B_recv_bytes
333a3ea4bf9SFrank Schaefer  * read bytes from the i2c device
334a3ea4bf9SFrank Schaefer  */
335a3ea4bf9SFrank Schaefer static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf,
336a3ea4bf9SFrank Schaefer 				   u16 len)
337a3ea4bf9SFrank Schaefer {
338a3ea4bf9SFrank Schaefer 	int ret;
339a3ea4bf9SFrank Schaefer 
340a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
341a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
342a3ea4bf9SFrank Schaefer 	/*
343a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
344a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
345a3ea4bf9SFrank Schaefer 	 */
346a3ea4bf9SFrank Schaefer 
347a3ea4bf9SFrank Schaefer 	/* Read value */
348a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len);
349a3ea4bf9SFrank Schaefer 	if (ret < 0) {
350a3ea4bf9SFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
351a3ea4bf9SFrank Schaefer 			    addr, ret);
352a3ea4bf9SFrank Schaefer 		return ret;
353a3ea4bf9SFrank Schaefer 	}
354a3ea4bf9SFrank Schaefer 	/*
355a3ea4bf9SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
356a3ea4bf9SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
357a3ea4bf9SFrank Schaefer 	 * specified slave address before AND no device is present at the
358a3ea4bf9SFrank Schaefer 	 * requested slave address.
359a3ea4bf9SFrank Schaefer 	 * Anyway, the next check will fail with -ENODEV in this case, so avoid
360a3ea4bf9SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
361a3ea4bf9SFrank Schaefer 	 */
362a3ea4bf9SFrank Schaefer 
363a3ea4bf9SFrank Schaefer 	/* Check success */
364a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
365a3ea4bf9SFrank Schaefer 	/*
366a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
367a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
368a3ea4bf9SFrank Schaefer 	 */
369a3ea4bf9SFrank Schaefer 	if (!ret)
370a3ea4bf9SFrank Schaefer 		return len;
371a3ea4bf9SFrank Schaefer 	else if (ret > 0)
372a3ea4bf9SFrank Schaefer 		return -ENODEV;
373a3ea4bf9SFrank Schaefer 
374a3ea4bf9SFrank Schaefer 	return ret;
375a3ea4bf9SFrank Schaefer 	/*
376a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
377a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
378a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
379a3ea4bf9SFrank Schaefer 	 */
380a3ea4bf9SFrank Schaefer }
381a3ea4bf9SFrank Schaefer 
382a3ea4bf9SFrank Schaefer /*
383a3ea4bf9SFrank Schaefer  * em25xx_bus_B_check_for_device()
384a3ea4bf9SFrank Schaefer  * check if there is a i2c device at the supplied address
385a3ea4bf9SFrank Schaefer  */
386a3ea4bf9SFrank Schaefer static int em25xx_bus_B_check_for_device(struct em28xx *dev, u16 addr)
387a3ea4bf9SFrank Schaefer {
388a3ea4bf9SFrank Schaefer 	u8 buf;
389a3ea4bf9SFrank Schaefer 	int ret;
390a3ea4bf9SFrank Schaefer 
391a3ea4bf9SFrank Schaefer 	ret = em25xx_bus_B_recv_bytes(dev, addr, &buf, 1);
392a3ea4bf9SFrank Schaefer 	if (ret < 0)
393a3ea4bf9SFrank Schaefer 		return ret;
394a3ea4bf9SFrank Schaefer 
395a3ea4bf9SFrank Schaefer 	return 0;
396a3ea4bf9SFrank Schaefer 	/*
397a3ea4bf9SFrank Schaefer 	 * NOTE: With chips which do not support this operation,
398a3ea4bf9SFrank Schaefer 	 * it seems to succeed ALWAYS ! (even if no device connected)
399a3ea4bf9SFrank Schaefer 	 */
400a3ea4bf9SFrank Schaefer }
401a3ea4bf9SFrank Schaefer 
402a3ea4bf9SFrank Schaefer static inline int i2c_check_for_device(struct em28xx_i2c_bus *i2c_bus, u16 addr)
403a3ea4bf9SFrank Schaefer {
404a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
405a3ea4bf9SFrank Schaefer 	int rc = -EOPNOTSUPP;
406a3ea4bf9SFrank Schaefer 
407a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
408a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_check_for_device(dev, addr);
409a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
410a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_check_for_device(dev, addr);
411a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
412a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_check_for_device(dev, addr);
413a3ea4bf9SFrank Schaefer 	if (rc == -ENODEV) {
414a3ea4bf9SFrank Schaefer 		if (i2c_debug)
415a3ea4bf9SFrank Schaefer 			printk(" no device\n");
416a3ea4bf9SFrank Schaefer 	}
417a3ea4bf9SFrank Schaefer 	return rc;
418a3ea4bf9SFrank Schaefer }
419a3ea4bf9SFrank Schaefer 
420a3ea4bf9SFrank Schaefer static inline int i2c_recv_bytes(struct em28xx_i2c_bus *i2c_bus,
421a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg)
422a3ea4bf9SFrank Schaefer {
423a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
424a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
425a3ea4bf9SFrank Schaefer 	int byte, rc = -EOPNOTSUPP;
426a3ea4bf9SFrank Schaefer 
427a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
428a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
429a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
430a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
431a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
432a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len);
433a3ea4bf9SFrank Schaefer 	if (i2c_debug) {
434a3ea4bf9SFrank Schaefer 		for (byte = 0; byte < msg.len; byte++)
435a3ea4bf9SFrank Schaefer 			printk(" %02x", msg.buf[byte]);
436a3ea4bf9SFrank Schaefer 	}
437a3ea4bf9SFrank Schaefer 	return rc;
438a3ea4bf9SFrank Schaefer }
439a3ea4bf9SFrank Schaefer 
440a3ea4bf9SFrank Schaefer static inline int i2c_send_bytes(struct em28xx_i2c_bus *i2c_bus,
441a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg, int stop)
442a3ea4bf9SFrank Schaefer {
443a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
444a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
445a3ea4bf9SFrank Schaefer 	int byte, rc = -EOPNOTSUPP;
446a3ea4bf9SFrank Schaefer 
447a3ea4bf9SFrank Schaefer 	if (i2c_debug) {
448a3ea4bf9SFrank Schaefer 		for (byte = 0; byte < msg.len; byte++)
449a3ea4bf9SFrank Schaefer 			printk(" %02x", msg.buf[byte]);
450a3ea4bf9SFrank Schaefer 	}
451a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
452a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop);
453a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
454a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_send_bytes(dev, addr, msg.buf, msg.len);
455a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
456a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_send_bytes(dev, addr, msg.buf, msg.len);
457a3ea4bf9SFrank Schaefer 	return rc;
458a3ea4bf9SFrank Schaefer }
459a3ea4bf9SFrank Schaefer 
460a3ea4bf9SFrank Schaefer /*
4610c0d06caSMauro Carvalho Chehab  * em28xx_i2c_xfer()
4620c0d06caSMauro Carvalho Chehab  * the main i2c transfer function
4630c0d06caSMauro Carvalho Chehab  */
4640c0d06caSMauro Carvalho Chehab static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
4650c0d06caSMauro Carvalho Chehab 			   struct i2c_msg msgs[], int num)
4660c0d06caSMauro Carvalho Chehab {
467aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
468aab3125cSMauro Carvalho Chehab 	struct em28xx *dev = i2c_bus->dev;
469aab3125cSMauro Carvalho Chehab 	unsigned bus = i2c_bus->bus;
470a3ea4bf9SFrank Schaefer 	int addr, rc, i;
4713190fbeeSMauro Carvalho Chehab 	u8 reg;
4720c0d06caSMauro Carvalho Chehab 
473aab3125cSMauro Carvalho Chehab 	rc = rt_mutex_trylock(&dev->i2c_bus_lock);
474aab3125cSMauro Carvalho Chehab 	if (rc < 0)
475aab3125cSMauro Carvalho Chehab 		return rc;
476aab3125cSMauro Carvalho Chehab 
477aab3125cSMauro Carvalho Chehab 	/* Switch I2C bus if needed */
478a3ea4bf9SFrank Schaefer 	if (bus != dev->cur_i2c_bus &&
479a3ea4bf9SFrank Schaefer 	    i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) {
480aab3125cSMauro Carvalho Chehab 		if (bus == 1)
4813190fbeeSMauro Carvalho Chehab 			reg = EM2874_I2C_SECONDARY_BUS_SELECT;
482aab3125cSMauro Carvalho Chehab 		else
4833190fbeeSMauro Carvalho Chehab 			reg = 0;
4843190fbeeSMauro Carvalho Chehab 		em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg,
4853190fbeeSMauro Carvalho Chehab 				      EM2874_I2C_SECONDARY_BUS_SELECT);
486aab3125cSMauro Carvalho Chehab 		dev->cur_i2c_bus = bus;
487aab3125cSMauro Carvalho Chehab 	}
488aab3125cSMauro Carvalho Chehab 
489aab3125cSMauro Carvalho Chehab 	if (num <= 0) {
490aab3125cSMauro Carvalho Chehab 		rt_mutex_unlock(&dev->i2c_bus_lock);
4910c0d06caSMauro Carvalho Chehab 		return 0;
492aab3125cSMauro Carvalho Chehab 	}
4930c0d06caSMauro Carvalho Chehab 	for (i = 0; i < num; i++) {
4940c0d06caSMauro Carvalho Chehab 		addr = msgs[i].addr << 1;
495d90f0677SFrank Schaefer 		if (i2c_debug)
496d7a80eaaSFrank Schaefer 			printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:",
497d7a80eaaSFrank Schaefer 			       dev->name, __func__ ,
4980c0d06caSMauro Carvalho Chehab 			       (msgs[i].flags & I2C_M_RD) ? "read" : "write",
499d7a80eaaSFrank Schaefer 			       i == num - 1 ? "stop" : "nonstop",
500d7a80eaaSFrank Schaefer 			       addr, msgs[i].len);
5010c0d06caSMauro Carvalho Chehab 		if (!msgs[i].len) { /* no len: check only for device presence */
502a3ea4bf9SFrank Schaefer 			rc = i2c_check_for_device(i2c_bus, addr);
50345f04e82SFrank Schaefer 			if (rc == -ENODEV) {
504aab3125cSMauro Carvalho Chehab 				rt_mutex_unlock(&dev->i2c_bus_lock);
5050c0d06caSMauro Carvalho Chehab 				return rc;
5060c0d06caSMauro Carvalho Chehab 			}
5070c0d06caSMauro Carvalho Chehab 		} else if (msgs[i].flags & I2C_M_RD) {
5080c0d06caSMauro Carvalho Chehab 			/* read bytes */
509a3ea4bf9SFrank Schaefer 			rc = i2c_recv_bytes(i2c_bus, msgs[i]);
5100c0d06caSMauro Carvalho Chehab 		} else {
5110c0d06caSMauro Carvalho Chehab 			/* write bytes */
512a3ea4bf9SFrank Schaefer 			rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1);
5130c0d06caSMauro Carvalho Chehab 		}
51445f04e82SFrank Schaefer 		if (rc < 0) {
515d90f0677SFrank Schaefer 			if (i2c_debug)
51645f04e82SFrank Schaefer 				printk(" ERROR: %i\n", rc);
517aab3125cSMauro Carvalho Chehab 			rt_mutex_unlock(&dev->i2c_bus_lock);
51845f04e82SFrank Schaefer 			return rc;
51945f04e82SFrank Schaefer 		}
520d90f0677SFrank Schaefer 		if (i2c_debug)
5210c0d06caSMauro Carvalho Chehab 			printk("\n");
5220c0d06caSMauro Carvalho Chehab 	}
5230c0d06caSMauro Carvalho Chehab 
524aab3125cSMauro Carvalho Chehab 	rt_mutex_unlock(&dev->i2c_bus_lock);
5250c0d06caSMauro Carvalho Chehab 	return num;
5260c0d06caSMauro Carvalho Chehab }
5270c0d06caSMauro Carvalho Chehab 
528fa74aca3SFrank Schaefer /*
529fa74aca3SFrank Schaefer  * based on linux/sunrpc/svcauth.h and linux/hash.h
5300c0d06caSMauro Carvalho Chehab  * The original hash function returns a different value, if arch is x86_64
5310c0d06caSMauro Carvalho Chehab  * or i386.
5320c0d06caSMauro Carvalho Chehab  */
5330c0d06caSMauro Carvalho Chehab static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
5340c0d06caSMauro Carvalho Chehab {
5350c0d06caSMauro Carvalho Chehab 	unsigned long hash = 0;
5360c0d06caSMauro Carvalho Chehab 	unsigned long l = 0;
5370c0d06caSMauro Carvalho Chehab 	int len = 0;
5380c0d06caSMauro Carvalho Chehab 	unsigned char c;
5390c0d06caSMauro Carvalho Chehab 	do {
5400c0d06caSMauro Carvalho Chehab 		if (len == length) {
5410c0d06caSMauro Carvalho Chehab 			c = (char)len;
5420c0d06caSMauro Carvalho Chehab 			len = -1;
5430c0d06caSMauro Carvalho Chehab 		} else
5440c0d06caSMauro Carvalho Chehab 			c = *buf++;
5450c0d06caSMauro Carvalho Chehab 		l = (l << 8) | c;
5460c0d06caSMauro Carvalho Chehab 		len++;
5470c0d06caSMauro Carvalho Chehab 		if ((len & (32 / 8 - 1)) == 0)
5480c0d06caSMauro Carvalho Chehab 			hash = ((hash^l) * 0x9e370001UL);
5490c0d06caSMauro Carvalho Chehab 	} while (len);
5500c0d06caSMauro Carvalho Chehab 
5510c0d06caSMauro Carvalho Chehab 	return (hash >> (32 - bits)) & 0xffffffffUL;
5520c0d06caSMauro Carvalho Chehab }
5530c0d06caSMauro Carvalho Chehab 
554fa74aca3SFrank Schaefer /*
555fa74aca3SFrank Schaefer  * Helper function to read data blocks from i2c clients with 8 or 16 bit
556fa74aca3SFrank Schaefer  * address width, 8 bit register width and auto incrementation been activated
557fa74aca3SFrank Schaefer  */
558aab3125cSMauro Carvalho Chehab static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
559aab3125cSMauro Carvalho Chehab 				 bool addr_w16, u16 len, u8 *data)
560d832c5b2SFrank Schaefer {
561d832c5b2SFrank Schaefer 	int remain = len, rsize, rsize_max, ret;
562d832c5b2SFrank Schaefer 	u8 buf[2];
563d832c5b2SFrank Schaefer 
564d832c5b2SFrank Schaefer 	/* Sanity check */
565d832c5b2SFrank Schaefer 	if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1))
566d832c5b2SFrank Schaefer 		return -EINVAL;
567d832c5b2SFrank Schaefer 	/* Select address */
568d832c5b2SFrank Schaefer 	buf[0] = addr >> 8;
569d832c5b2SFrank Schaefer 	buf[1] = addr & 0xff;
570aab3125cSMauro Carvalho Chehab 	ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16);
571d832c5b2SFrank Schaefer 	if (ret < 0)
572d832c5b2SFrank Schaefer 		return ret;
573d832c5b2SFrank Schaefer 	/* Read data */
574d832c5b2SFrank Schaefer 	if (dev->board.is_em2800)
575d832c5b2SFrank Schaefer 		rsize_max = 4;
576d832c5b2SFrank Schaefer 	else
577d832c5b2SFrank Schaefer 		rsize_max = 64;
578d832c5b2SFrank Schaefer 	while (remain > 0) {
579d832c5b2SFrank Schaefer 		if (remain > rsize_max)
580d832c5b2SFrank Schaefer 			rsize = rsize_max;
581d832c5b2SFrank Schaefer 		else
582d832c5b2SFrank Schaefer 			rsize = remain;
583d832c5b2SFrank Schaefer 
584aab3125cSMauro Carvalho Chehab 		ret = i2c_master_recv(&dev->i2c_client[bus], data, rsize);
585d832c5b2SFrank Schaefer 		if (ret < 0)
586d832c5b2SFrank Schaefer 			return ret;
587d832c5b2SFrank Schaefer 
588d832c5b2SFrank Schaefer 		remain -= rsize;
589d832c5b2SFrank Schaefer 		data += rsize;
590d832c5b2SFrank Schaefer 	}
591d832c5b2SFrank Schaefer 
592d832c5b2SFrank Schaefer 	return len;
593d832c5b2SFrank Schaefer }
594d832c5b2SFrank Schaefer 
595aab3125cSMauro Carvalho Chehab static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
596aab3125cSMauro Carvalho Chehab 			     u8 **eedata, u16 *eedata_len)
5970c0d06caSMauro Carvalho Chehab {
598510e884cSFrank Schaefer 	const u16 len = 256;
599fa74aca3SFrank Schaefer 	/*
600fa74aca3SFrank Schaefer 	 * FIXME common length/size for bytes to read, to display, hash
601510e884cSFrank Schaefer 	 * calculation and returned device dataset. Simplifies the code a lot,
602fa74aca3SFrank Schaefer 	 * but we might have to deal with multiple sizes in the future !
603fa74aca3SFrank Schaefer 	 */
604d832c5b2SFrank Schaefer 	int i, err;
605510e884cSFrank Schaefer 	struct em28xx_eeprom *dev_config;
606510e884cSFrank Schaefer 	u8 buf, *data;
6070c0d06caSMauro Carvalho Chehab 
608a217968fSFrank Schaefer 	*eedata = NULL;
609510e884cSFrank Schaefer 	*eedata_len = 0;
610a217968fSFrank Schaefer 
611aab3125cSMauro Carvalho Chehab 	/* EEPROM is always on i2c bus 0 on all known devices. */
612aab3125cSMauro Carvalho Chehab 
613aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].addr = 0xa0 >> 1;
6140c0d06caSMauro Carvalho Chehab 
6150c0d06caSMauro Carvalho Chehab 	/* Check if board has eeprom */
616aab3125cSMauro Carvalho Chehab 	err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
6170c0d06caSMauro Carvalho Chehab 	if (err < 0) {
61812d7ce18SFrank Schaefer 		em28xx_info("board has no eeprom\n");
6190c0d06caSMauro Carvalho Chehab 		return -ENODEV;
6200c0d06caSMauro Carvalho Chehab 	}
6210c0d06caSMauro Carvalho Chehab 
622a217968fSFrank Schaefer 	data = kzalloc(len, GFP_KERNEL);
623a217968fSFrank Schaefer 	if (data == NULL)
624a217968fSFrank Schaefer 		return -ENOMEM;
625a217968fSFrank Schaefer 
626d832c5b2SFrank Schaefer 	/* Read EEPROM content */
627aab3125cSMauro Carvalho Chehab 	err = em28xx_i2c_read_block(dev, bus, 0x0000,
628aab3125cSMauro Carvalho Chehab 				    dev->eeprom_addrwidth_16bit,
629a217968fSFrank Schaefer 				    len, data);
630d832c5b2SFrank Schaefer 	if (err != len) {
63112d7ce18SFrank Schaefer 		em28xx_errdev("failed to read eeprom (err=%d)\n", err);
632510e884cSFrank Schaefer 		goto error;
6330c0d06caSMauro Carvalho Chehab 	}
63490271964SFrank Schaefer 
63587b52439SFrank Schaefer 	/* Display eeprom content */
6360c0d06caSMauro Carvalho Chehab 	for (i = 0; i < len; i++) {
63787b52439SFrank Schaefer 		if (0 == (i % 16)) {
63887b52439SFrank Schaefer 			if (dev->eeprom_addrwidth_16bit)
63987b52439SFrank Schaefer 				em28xx_info("i2c eeprom %04x:", i);
64087b52439SFrank Schaefer 			else
64112d7ce18SFrank Schaefer 				em28xx_info("i2c eeprom %02x:", i);
64287b52439SFrank Schaefer 		}
643a217968fSFrank Schaefer 		printk(" %02x", data[i]);
6440c0d06caSMauro Carvalho Chehab 		if (15 == (i % 16))
6450c0d06caSMauro Carvalho Chehab 			printk("\n");
6460c0d06caSMauro Carvalho Chehab 	}
647510e884cSFrank Schaefer 	if (dev->eeprom_addrwidth_16bit)
648510e884cSFrank Schaefer 		em28xx_info("i2c eeprom %04x: ... (skipped)\n", i);
6490c0d06caSMauro Carvalho Chehab 
65087b52439SFrank Schaefer 	if (dev->eeprom_addrwidth_16bit &&
651a217968fSFrank Schaefer 	    data[0] == 0x26 && data[3] == 0x00) {
65287b52439SFrank Schaefer 		/* new eeprom format; size 4-64kb */
653510e884cSFrank Schaefer 		u16 mc_start;
654510e884cSFrank Schaefer 		u16 hwconf_offset;
655510e884cSFrank Schaefer 
656a217968fSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
657510e884cSFrank Schaefer 		mc_start = (data[1] << 8) + 4;	/* usually 0x0004 */
658510e884cSFrank Schaefer 
659d230d5adSFrank Schaefer 		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
660510e884cSFrank Schaefer 			    data[0], data[1], data[2], data[3], dev->hash);
661510e884cSFrank Schaefer 		em28xx_info("EEPROM info:\n");
662d230d5adSFrank Schaefer 		em28xx_info("\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n",
663510e884cSFrank Schaefer 			    mc_start, data[2]);
664fa74aca3SFrank Schaefer 		/*
665fa74aca3SFrank Schaefer 		 * boot configuration (address 0x0002):
66687b52439SFrank Schaefer 		 * [0]   microcode download speed: 1 = 400 kHz; 0 = 100 kHz
66787b52439SFrank Schaefer 		 * [1]   always selects 12 kb RAM
66887b52439SFrank Schaefer 		 * [2]   USB device speed: 1 = force Full Speed; 0 = auto detect
66987b52439SFrank Schaefer 		 * [4]   1 = force fast mode and no suspend for device testing
67087b52439SFrank Schaefer 		 * [5:7] USB PHY tuning registers; determined by device
67187b52439SFrank Schaefer 		 *       characterization
67287b52439SFrank Schaefer 		 */
67387b52439SFrank Schaefer 
674fa74aca3SFrank Schaefer 		/*
675fa74aca3SFrank Schaefer 		 * Read hardware config dataset offset from address
676fa74aca3SFrank Schaefer 		 * (microcode start + 46)
677fa74aca3SFrank Schaefer 		 */
678aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2,
679aab3125cSMauro Carvalho Chehab 					    data);
680510e884cSFrank Schaefer 		if (err != 2) {
681510e884cSFrank Schaefer 			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
682510e884cSFrank Schaefer 				      err);
683510e884cSFrank Schaefer 			goto error;
684510e884cSFrank Schaefer 		}
68587b52439SFrank Schaefer 
686510e884cSFrank Schaefer 		/* Calculate hardware config dataset start address */
687510e884cSFrank Schaefer 		hwconf_offset = mc_start + data[0] + (data[1] << 8);
688510e884cSFrank Schaefer 
689510e884cSFrank Schaefer 		/* Read hardware config dataset */
690fa74aca3SFrank Schaefer 		/*
691fa74aca3SFrank Schaefer 		 * NOTE: the microcode copy can be multiple pages long, but
692510e884cSFrank Schaefer 		 * we assume the hardware config dataset is the same as in
693510e884cSFrank Schaefer 		 * the old eeprom and not longer than 256 bytes.
694510e884cSFrank Schaefer 		 * tveeprom is currently also limited to 256 bytes.
695510e884cSFrank Schaefer 		 */
696aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len,
697aab3125cSMauro Carvalho Chehab 					    data);
698510e884cSFrank Schaefer 		if (err != len) {
699510e884cSFrank Schaefer 			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
700510e884cSFrank Schaefer 				      err);
701510e884cSFrank Schaefer 			goto error;
702510e884cSFrank Schaefer 		}
703510e884cSFrank Schaefer 
704510e884cSFrank Schaefer 		/* Verify hardware config dataset */
705510e884cSFrank Schaefer 		/* NOTE: not all devices provide this type of dataset */
706510e884cSFrank Schaefer 		if (data[0] != 0x1a || data[1] != 0xeb ||
707a217968fSFrank Schaefer 		    data[2] != 0x67 || data[3] != 0x95) {
708510e884cSFrank Schaefer 			em28xx_info("\tno hardware configuration dataset found in eeprom\n");
709510e884cSFrank Schaefer 			kfree(data);
710510e884cSFrank Schaefer 			return 0;
711510e884cSFrank Schaefer 		}
712510e884cSFrank Schaefer 
713510e884cSFrank Schaefer 		/* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */
714510e884cSFrank Schaefer 
715510e884cSFrank Schaefer 	} else if (!dev->eeprom_addrwidth_16bit &&
716510e884cSFrank Schaefer 		   data[0] == 0x1a && data[1] == 0xeb &&
717510e884cSFrank Schaefer 		   data[2] == 0x67 && data[3] == 0x95) {
718510e884cSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
719d230d5adSFrank Schaefer 		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
720510e884cSFrank Schaefer 			    data[0], data[1], data[2], data[3], dev->hash);
721510e884cSFrank Schaefer 		em28xx_info("EEPROM info:\n");
722510e884cSFrank Schaefer 	} else {
72387b52439SFrank Schaefer 		em28xx_info("unknown eeprom format or eeprom corrupted !\n");
724510e884cSFrank Schaefer 		err = -ENODEV;
725510e884cSFrank Schaefer 		goto error;
726f55eacbeSFrank Schaefer 	}
727f55eacbeSFrank Schaefer 
728a217968fSFrank Schaefer 	*eedata = data;
729510e884cSFrank Schaefer 	*eedata_len = len;
73032bf7c6cSAlban Browaeys 	dev_config = (void *)*eedata;
731a217968fSFrank Schaefer 
732510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
7330c0d06caSMauro Carvalho Chehab 	case 0:
73412d7ce18SFrank Schaefer 		em28xx_info("\tNo audio on board.\n");
7350c0d06caSMauro Carvalho Chehab 		break;
7360c0d06caSMauro Carvalho Chehab 	case 1:
73712d7ce18SFrank Schaefer 		em28xx_info("\tAC97 audio (5 sample rates)\n");
7380c0d06caSMauro Carvalho Chehab 		break;
7390c0d06caSMauro Carvalho Chehab 	case 2:
740687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
74112d7ce18SFrank Schaefer 			em28xx_info("\tI2S audio, sample rate=32k\n");
742687ff8b0SFrank Schaefer 		else
743687ff8b0SFrank Schaefer 			em28xx_info("\tI2S audio, 3 sample rates\n");
7440c0d06caSMauro Carvalho Chehab 		break;
7450c0d06caSMauro Carvalho Chehab 	case 3:
746687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
74712d7ce18SFrank Schaefer 			em28xx_info("\tI2S audio, 3 sample rates\n");
748687ff8b0SFrank Schaefer 		else
749687ff8b0SFrank Schaefer 			em28xx_info("\tI2S audio, 5 sample rates\n");
7500c0d06caSMauro Carvalho Chehab 		break;
7510c0d06caSMauro Carvalho Chehab 	}
7520c0d06caSMauro Carvalho Chehab 
753510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 3)
75412d7ce18SFrank Schaefer 		em28xx_info("\tUSB Remote wakeup capable\n");
7550c0d06caSMauro Carvalho Chehab 
756510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 2)
75712d7ce18SFrank Schaefer 		em28xx_info("\tUSB Self power capable\n");
7580c0d06caSMauro Carvalho Chehab 
759510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) & 0x3) {
7600c0d06caSMauro Carvalho Chehab 	case 0:
76112d7ce18SFrank Schaefer 		em28xx_info("\t500mA max power\n");
7620c0d06caSMauro Carvalho Chehab 		break;
7630c0d06caSMauro Carvalho Chehab 	case 1:
76412d7ce18SFrank Schaefer 		em28xx_info("\t400mA max power\n");
7650c0d06caSMauro Carvalho Chehab 		break;
7660c0d06caSMauro Carvalho Chehab 	case 2:
76712d7ce18SFrank Schaefer 		em28xx_info("\t300mA max power\n");
7680c0d06caSMauro Carvalho Chehab 		break;
7690c0d06caSMauro Carvalho Chehab 	case 3:
77012d7ce18SFrank Schaefer 		em28xx_info("\t200mA max power\n");
7710c0d06caSMauro Carvalho Chehab 		break;
7720c0d06caSMauro Carvalho Chehab 	}
77312d7ce18SFrank Schaefer 	em28xx_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
774510e884cSFrank Schaefer 		    dev_config->string_idx_table,
775510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string1),
776510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string2),
777510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string3));
7780c0d06caSMauro Carvalho Chehab 
7790c0d06caSMauro Carvalho Chehab 	return 0;
780510e884cSFrank Schaefer 
781510e884cSFrank Schaefer error:
782510e884cSFrank Schaefer 	kfree(data);
783510e884cSFrank Schaefer 	return err;
7840c0d06caSMauro Carvalho Chehab }
7850c0d06caSMauro Carvalho Chehab 
7860c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
7870c0d06caSMauro Carvalho Chehab 
7880c0d06caSMauro Carvalho Chehab /*
7890c0d06caSMauro Carvalho Chehab  * functionality()
7900c0d06caSMauro Carvalho Chehab  */
791aab3125cSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *i2c_adap)
7920c0d06caSMauro Carvalho Chehab {
793aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
794aab3125cSMauro Carvalho Chehab 
795a3ea4bf9SFrank Schaefer 	if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) ||
796a3ea4bf9SFrank Schaefer 	    (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) {
797a3ea4bf9SFrank Schaefer 		return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
798a3ea4bf9SFrank Schaefer 	} else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)  {
799a3ea4bf9SFrank Schaefer 		return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) &
800a3ea4bf9SFrank Schaefer 			~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
801a3ea4bf9SFrank Schaefer 	}
802a3ea4bf9SFrank Schaefer 
803a3ea4bf9SFrank Schaefer 	WARN(1, "Unknown i2c bus algorithm.\n");
804a3ea4bf9SFrank Schaefer 	return 0;
8050c0d06caSMauro Carvalho Chehab }
8060c0d06caSMauro Carvalho Chehab 
8070c0d06caSMauro Carvalho Chehab static struct i2c_algorithm em28xx_algo = {
8080c0d06caSMauro Carvalho Chehab 	.master_xfer   = em28xx_i2c_xfer,
8090c0d06caSMauro Carvalho Chehab 	.functionality = functionality,
8100c0d06caSMauro Carvalho Chehab };
8110c0d06caSMauro Carvalho Chehab 
8120c0d06caSMauro Carvalho Chehab static struct i2c_adapter em28xx_adap_template = {
8130c0d06caSMauro Carvalho Chehab 	.owner = THIS_MODULE,
8140c0d06caSMauro Carvalho Chehab 	.name = "em28xx",
8150c0d06caSMauro Carvalho Chehab 	.algo = &em28xx_algo,
8160c0d06caSMauro Carvalho Chehab };
8170c0d06caSMauro Carvalho Chehab 
8180c0d06caSMauro Carvalho Chehab static struct i2c_client em28xx_client_template = {
8190c0d06caSMauro Carvalho Chehab 	.name = "em28xx internal",
8200c0d06caSMauro Carvalho Chehab };
8210c0d06caSMauro Carvalho Chehab 
8220c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
8230c0d06caSMauro Carvalho Chehab 
8240c0d06caSMauro Carvalho Chehab /*
8250c0d06caSMauro Carvalho Chehab  * i2c_devs
8260c0d06caSMauro Carvalho Chehab  * incomplete list of known devices
8270c0d06caSMauro Carvalho Chehab  */
8280c0d06caSMauro Carvalho Chehab static char *i2c_devs[128] = {
8290b3966e4SFrank Schaefer 	[0x3e >> 1] = "remote IR sensor",
8300c0d06caSMauro Carvalho Chehab 	[0x4a >> 1] = "saa7113h",
8310c0d06caSMauro Carvalho Chehab 	[0x52 >> 1] = "drxk",
8320c0d06caSMauro Carvalho Chehab 	[0x60 >> 1] = "remote IR sensor",
8330c0d06caSMauro Carvalho Chehab 	[0x8e >> 1] = "remote IR sensor",
8340c0d06caSMauro Carvalho Chehab 	[0x86 >> 1] = "tda9887",
8350c0d06caSMauro Carvalho Chehab 	[0x80 >> 1] = "msp34xx",
8360c0d06caSMauro Carvalho Chehab 	[0x88 >> 1] = "msp34xx",
8370c0d06caSMauro Carvalho Chehab 	[0xa0 >> 1] = "eeprom",
8380c0d06caSMauro Carvalho Chehab 	[0xb0 >> 1] = "tda9874",
8390c0d06caSMauro Carvalho Chehab 	[0xb8 >> 1] = "tvp5150a",
8400c0d06caSMauro Carvalho Chehab 	[0xba >> 1] = "webcam sensor or tvp5150a",
8410c0d06caSMauro Carvalho Chehab 	[0xc0 >> 1] = "tuner (analog)",
8420c0d06caSMauro Carvalho Chehab 	[0xc2 >> 1] = "tuner (analog)",
8430c0d06caSMauro Carvalho Chehab 	[0xc4 >> 1] = "tuner (analog)",
8440c0d06caSMauro Carvalho Chehab 	[0xc6 >> 1] = "tuner (analog)",
8450c0d06caSMauro Carvalho Chehab };
8460c0d06caSMauro Carvalho Chehab 
8470c0d06caSMauro Carvalho Chehab /*
8480c0d06caSMauro Carvalho Chehab  * do_i2c_scan()
8490c0d06caSMauro Carvalho Chehab  * check i2c address range for devices
8500c0d06caSMauro Carvalho Chehab  */
851aab3125cSMauro Carvalho Chehab void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus)
8520c0d06caSMauro Carvalho Chehab {
8530c0d06caSMauro Carvalho Chehab 	u8 i2c_devicelist[128];
8540c0d06caSMauro Carvalho Chehab 	unsigned char buf;
8550c0d06caSMauro Carvalho Chehab 	int i, rc;
8560c0d06caSMauro Carvalho Chehab 
8570c0d06caSMauro Carvalho Chehab 	memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
8580c0d06caSMauro Carvalho Chehab 
8590c0d06caSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
860aab3125cSMauro Carvalho Chehab 		dev->i2c_client[bus].addr = i;
861aab3125cSMauro Carvalho Chehab 		rc = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
8620c0d06caSMauro Carvalho Chehab 		if (rc < 0)
8630c0d06caSMauro Carvalho Chehab 			continue;
8640c0d06caSMauro Carvalho Chehab 		i2c_devicelist[i] = i;
865aab3125cSMauro Carvalho Chehab 		em28xx_info("found i2c device @ 0x%x on bus %d [%s]\n",
866aab3125cSMauro Carvalho Chehab 			    i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???");
8670c0d06caSMauro Carvalho Chehab 	}
8680c0d06caSMauro Carvalho Chehab 
869aab3125cSMauro Carvalho Chehab 	if (bus == dev->def_i2c_bus)
8700c0d06caSMauro Carvalho Chehab 		dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
8710c0d06caSMauro Carvalho Chehab 						ARRAY_SIZE(i2c_devicelist), 32);
8720c0d06caSMauro Carvalho Chehab }
8730c0d06caSMauro Carvalho Chehab 
8740c0d06caSMauro Carvalho Chehab /*
8750c0d06caSMauro Carvalho Chehab  * em28xx_i2c_register()
8760c0d06caSMauro Carvalho Chehab  * register i2c bus
8770c0d06caSMauro Carvalho Chehab  */
878a3ea4bf9SFrank Schaefer int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
879a3ea4bf9SFrank Schaefer 			enum em28xx_i2c_algo_type algo_type)
8800c0d06caSMauro Carvalho Chehab {
8810c0d06caSMauro Carvalho Chehab 	int retval;
8820c0d06caSMauro Carvalho Chehab 
8830c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
8840c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
8850c0d06caSMauro Carvalho Chehab 
886aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
887aab3125cSMauro Carvalho Chehab 		return -ENODEV;
888aab3125cSMauro Carvalho Chehab 
889aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus] = em28xx_adap_template;
890aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].dev.parent = &dev->udev->dev;
891aab3125cSMauro Carvalho Chehab 	strcpy(dev->i2c_adap[bus].name, dev->name);
892aab3125cSMauro Carvalho Chehab 
893aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].bus = bus;
894a3ea4bf9SFrank Schaefer 	dev->i2c_bus[bus].algo_type = algo_type;
895aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].dev = dev;
896aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus];
897aab3125cSMauro Carvalho Chehab 	i2c_set_adapdata(&dev->i2c_adap[bus], &dev->v4l2_dev);
898aab3125cSMauro Carvalho Chehab 
899aab3125cSMauro Carvalho Chehab 	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
9000c0d06caSMauro Carvalho Chehab 	if (retval < 0) {
9010c0d06caSMauro Carvalho Chehab 		em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
9020c0d06caSMauro Carvalho Chehab 			__func__, retval);
9030c0d06caSMauro Carvalho Chehab 		return retval;
9040c0d06caSMauro Carvalho Chehab 	}
9050c0d06caSMauro Carvalho Chehab 
906aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus] = em28xx_client_template;
907aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].adapter = &dev->i2c_adap[bus];
9080c0d06caSMauro Carvalho Chehab 
909aab3125cSMauro Carvalho Chehab 	/* Up to now, all eeproms are at bus 0 */
910aab3125cSMauro Carvalho Chehab 	if (!bus) {
911aab3125cSMauro Carvalho Chehab 		retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
9120c0d06caSMauro Carvalho Chehab 		if ((retval < 0) && (retval != -ENODEV)) {
9130c0d06caSMauro Carvalho Chehab 			em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
9140c0d06caSMauro Carvalho Chehab 				__func__, retval);
9150c0d06caSMauro Carvalho Chehab 
9160c0d06caSMauro Carvalho Chehab 			return retval;
9170c0d06caSMauro Carvalho Chehab 		}
918aab3125cSMauro Carvalho Chehab 	}
9190c0d06caSMauro Carvalho Chehab 
9200c0d06caSMauro Carvalho Chehab 	if (i2c_scan)
921aab3125cSMauro Carvalho Chehab 		em28xx_do_i2c_scan(dev, bus);
9220c0d06caSMauro Carvalho Chehab 
9230c0d06caSMauro Carvalho Chehab 	return 0;
9240c0d06caSMauro Carvalho Chehab }
9250c0d06caSMauro Carvalho Chehab 
9260c0d06caSMauro Carvalho Chehab /*
9270c0d06caSMauro Carvalho Chehab  * em28xx_i2c_unregister()
9280c0d06caSMauro Carvalho Chehab  * unregister i2c_bus
9290c0d06caSMauro Carvalho Chehab  */
930aab3125cSMauro Carvalho Chehab int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus)
9310c0d06caSMauro Carvalho Chehab {
932aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
933aab3125cSMauro Carvalho Chehab 		return -ENODEV;
934aab3125cSMauro Carvalho Chehab 
935aab3125cSMauro Carvalho Chehab 	i2c_del_adapter(&dev->i2c_adap[bus]);
9360c0d06caSMauro Carvalho Chehab 	return 0;
9370c0d06caSMauro Carvalho Chehab }
938