xref: /openbmc/linux/drivers/media/usb/em28xx/em28xx-i2c.c (revision 687ff8b0c489e8bb3a4a3da291e830fa7cfafe22)
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>
290c0d06caSMauro Carvalho Chehab 
300c0d06caSMauro Carvalho Chehab #include "em28xx.h"
310c0d06caSMauro Carvalho Chehab #include "tuner-xc2028.h"
320c0d06caSMauro Carvalho Chehab #include <media/v4l2-common.h>
330c0d06caSMauro Carvalho Chehab #include <media/tuner.h>
340c0d06caSMauro Carvalho Chehab 
350c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
360c0d06caSMauro Carvalho Chehab 
370c0d06caSMauro Carvalho Chehab static unsigned int i2c_scan;
380c0d06caSMauro Carvalho Chehab module_param(i2c_scan, int, 0444);
390c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
400c0d06caSMauro Carvalho Chehab 
410c0d06caSMauro Carvalho Chehab static unsigned int i2c_debug;
420c0d06caSMauro Carvalho Chehab module_param(i2c_debug, int, 0644);
430c0d06caSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
440c0d06caSMauro Carvalho Chehab 
450c0d06caSMauro Carvalho Chehab /*
46f5ae371aSFrank Schaefer  * em2800_i2c_send_bytes()
47f5ae371aSFrank Schaefer  * send up to 4 bytes to the em2800 i2c device
480c0d06caSMauro Carvalho Chehab  */
49f5ae371aSFrank Schaefer static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
500c0d06caSMauro Carvalho Chehab {
510c0d06caSMauro Carvalho Chehab 	int ret;
520c0d06caSMauro Carvalho Chehab 	int write_timeout;
53a6bad040SFrank Schaefer 	u8 b2[6];
54f5ae371aSFrank Schaefer 
55f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
56f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
57f5ae371aSFrank Schaefer 
580c0d06caSMauro Carvalho Chehab 	BUG_ON(len < 1 || len > 4);
590c0d06caSMauro Carvalho Chehab 	b2[5] = 0x80 + len - 1;
600c0d06caSMauro Carvalho Chehab 	b2[4] = addr;
610c0d06caSMauro Carvalho Chehab 	b2[3] = buf[0];
620c0d06caSMauro Carvalho Chehab 	if (len > 1)
630c0d06caSMauro Carvalho Chehab 		b2[2] = buf[1];
640c0d06caSMauro Carvalho Chehab 	if (len > 2)
650c0d06caSMauro Carvalho Chehab 		b2[1] = buf[2];
660c0d06caSMauro Carvalho Chehab 	if (len > 3)
670c0d06caSMauro Carvalho Chehab 		b2[0] = buf[3];
680c0d06caSMauro Carvalho Chehab 
692fcc82d8SFrank Schaefer 	/* trigger write */
700c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
710c0d06caSMauro Carvalho Chehab 	if (ret != 2 + len) {
72d230d5adSFrank Schaefer 		em28xx_warn("failed to trigger write to i2c address 0x%x (error=%i)\n",
73d230d5adSFrank Schaefer 			    addr, ret);
7445f04e82SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
750c0d06caSMauro Carvalho Chehab 	}
762fcc82d8SFrank Schaefer 	/* wait for completion */
772fcc82d8SFrank Schaefer 	for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0;
780c0d06caSMauro Carvalho Chehab 	     write_timeout -= 5) {
790c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
8045f04e82SFrank Schaefer 		if (ret == 0x80 + len - 1) {
810c0d06caSMauro Carvalho Chehab 			return len;
8245f04e82SFrank Schaefer 		} else if (ret == 0x94 + len - 1) {
8345f04e82SFrank Schaefer 			return -ENODEV;
8445f04e82SFrank Schaefer 		} else if (ret < 0) {
85d230d5adSFrank Schaefer 			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
86d230d5adSFrank Schaefer 				    ret);
8745f04e82SFrank Schaefer 			return ret;
8845f04e82SFrank Schaefer 		}
890c0d06caSMauro Carvalho Chehab 		msleep(5);
900c0d06caSMauro Carvalho Chehab 	}
9145f04e82SFrank Schaefer 	em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
920c0d06caSMauro Carvalho Chehab 	return -EIO;
930c0d06caSMauro Carvalho Chehab }
940c0d06caSMauro Carvalho Chehab 
950c0d06caSMauro Carvalho Chehab /*
960c0d06caSMauro Carvalho Chehab  * em2800_i2c_recv_bytes()
972fcc82d8SFrank Schaefer  * read up to 4 bytes from the em2800 i2c device
980c0d06caSMauro Carvalho Chehab  */
99a6bad040SFrank Schaefer static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len)
1000c0d06caSMauro Carvalho Chehab {
1012fcc82d8SFrank Schaefer 	u8 buf2[4];
1020c0d06caSMauro Carvalho Chehab 	int ret;
1032fcc82d8SFrank Schaefer 	int read_timeout;
1042fcc82d8SFrank Schaefer 	int i;
105f5ae371aSFrank Schaefer 
106f5ae371aSFrank Schaefer 	if (len < 1 || len > 4)
107f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
108f5ae371aSFrank Schaefer 
1092fcc82d8SFrank Schaefer 	/* trigger read */
1102fcc82d8SFrank Schaefer 	buf2[1] = 0x84 + len - 1;
1112fcc82d8SFrank Schaefer 	buf2[0] = addr;
1122fcc82d8SFrank Schaefer 	ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2);
1132fcc82d8SFrank Schaefer 	if (ret != 2) {
114d230d5adSFrank Schaefer 		em28xx_warn("failed to trigger read from i2c address 0x%x (error=%i)\n",
115d230d5adSFrank Schaefer 			    addr, ret);
1162fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1172fcc82d8SFrank Schaefer 	}
1182fcc82d8SFrank Schaefer 
1192fcc82d8SFrank Schaefer 	/* wait for completion */
1202fcc82d8SFrank Schaefer 	for (read_timeout = EM2800_I2C_XFER_TIMEOUT; read_timeout > 0;
1212fcc82d8SFrank Schaefer 	     read_timeout -= 5) {
1222fcc82d8SFrank Schaefer 		ret = dev->em28xx_read_reg(dev, 0x05);
1232fcc82d8SFrank Schaefer 		if (ret == 0x84 + len - 1) {
1242fcc82d8SFrank Schaefer 			break;
1252fcc82d8SFrank Schaefer 		} else if (ret == 0x94 + len - 1) {
1262fcc82d8SFrank Schaefer 			return -ENODEV;
1272fcc82d8SFrank Schaefer 		} else if (ret < 0) {
128d230d5adSFrank Schaefer 			em28xx_warn("failed to get i2c transfer status from bridge register (error=%i)\n",
129d230d5adSFrank Schaefer 				    ret);
1300c0d06caSMauro Carvalho Chehab 			return ret;
1310c0d06caSMauro Carvalho Chehab 		}
1322fcc82d8SFrank Schaefer 		msleep(5);
1332fcc82d8SFrank Schaefer 	}
1342fcc82d8SFrank Schaefer 	if (ret != 0x84 + len - 1)
1352fcc82d8SFrank Schaefer 		em28xx_warn("read from i2c device at 0x%x timed out\n", addr);
1362fcc82d8SFrank Schaefer 
1372fcc82d8SFrank Schaefer 	/* get the received message */
1382fcc82d8SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len);
1392fcc82d8SFrank Schaefer 	if (ret != len) {
140d230d5adSFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed: couldn't get the received message from the bridge (error=%i)\n",
141d230d5adSFrank Schaefer 			    addr, ret);
1422fcc82d8SFrank Schaefer 		return (ret < 0) ? ret : -EIO;
1432fcc82d8SFrank Schaefer 	}
1442fcc82d8SFrank Schaefer 	for (i = 0; i < len; i++)
1452fcc82d8SFrank Schaefer 		buf[i] = buf2[len - 1 - i];
1462fcc82d8SFrank Schaefer 
1470c0d06caSMauro Carvalho Chehab 	return ret;
1480c0d06caSMauro Carvalho Chehab }
1492fcc82d8SFrank Schaefer 
1502fcc82d8SFrank Schaefer /*
1512fcc82d8SFrank Schaefer  * em2800_i2c_check_for_device()
1522fcc82d8SFrank Schaefer  * check if there is an i2c device at the supplied address
1532fcc82d8SFrank Schaefer  */
1542fcc82d8SFrank Schaefer static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr)
1552fcc82d8SFrank Schaefer {
1562fcc82d8SFrank Schaefer 	u8 buf;
1572fcc82d8SFrank Schaefer 	int ret;
1582fcc82d8SFrank Schaefer 
1592fcc82d8SFrank Schaefer 	ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1);
1602fcc82d8SFrank Schaefer 	if (ret == 1)
1612fcc82d8SFrank Schaefer 		return 0;
1622fcc82d8SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
1630c0d06caSMauro Carvalho Chehab }
1640c0d06caSMauro Carvalho Chehab 
1650c0d06caSMauro Carvalho Chehab /*
1660c0d06caSMauro Carvalho Chehab  * em28xx_i2c_send_bytes()
1670c0d06caSMauro Carvalho Chehab  */
168a6bad040SFrank Schaefer static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
169a6bad040SFrank Schaefer 				 u16 len, int stop)
1700c0d06caSMauro Carvalho Chehab {
1710c0d06caSMauro Carvalho Chehab 	int write_timeout, ret;
1720c0d06caSMauro Carvalho Chehab 
173f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
174f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
175fa74aca3SFrank Schaefer 	/*
176fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
177fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
178fa74aca3SFrank Schaefer 	 */
179f5ae371aSFrank Schaefer 
18045f04e82SFrank Schaefer 	/* Write to i2c device */
18145f04e82SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
18245f04e82SFrank Schaefer 	if (ret != len) {
18345f04e82SFrank Schaefer 		if (ret < 0) {
184d230d5adSFrank Schaefer 			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
185d230d5adSFrank Schaefer 				    addr, ret);
18645f04e82SFrank Schaefer 			return ret;
18745f04e82SFrank Schaefer 		} else {
188d230d5adSFrank Schaefer 			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
18945f04e82SFrank Schaefer 				    len, addr, ret);
19045f04e82SFrank Schaefer 			return -EIO;
19145f04e82SFrank Schaefer 		}
19245f04e82SFrank Schaefer 	}
1930c0d06caSMauro Carvalho Chehab 
19445f04e82SFrank Schaefer 	/* Check success of the i2c operation */
1952fcc82d8SFrank Schaefer 	for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0;
1960c0d06caSMauro Carvalho Chehab 	     write_timeout -= 5) {
1970c0d06caSMauro Carvalho Chehab 		ret = dev->em28xx_read_reg(dev, 0x05);
19845f04e82SFrank Schaefer 		if (ret == 0) { /* success */
19945f04e82SFrank Schaefer 			return len;
20045f04e82SFrank Schaefer 		} else if (ret == 0x10) {
20145f04e82SFrank Schaefer 			return -ENODEV;
20245f04e82SFrank Schaefer 		} else if (ret < 0) {
203d230d5adSFrank Schaefer 			em28xx_warn("failed to read i2c transfer status from bridge (error=%i)\n",
204d230d5adSFrank Schaefer 				    ret);
20545f04e82SFrank Schaefer 			return ret;
2060c0d06caSMauro Carvalho Chehab 		}
20745f04e82SFrank Schaefer 		msleep(5);
208fa74aca3SFrank Schaefer 		/*
209fa74aca3SFrank Schaefer 		 * NOTE: do we really have to wait for success ?
210fa74aca3SFrank Schaefer 		 * Never seen anything else than 0x00 or 0x10
211fa74aca3SFrank Schaefer 		 * (even with high payload) ...
212fa74aca3SFrank Schaefer 		 */
21345f04e82SFrank Schaefer 	}
21445f04e82SFrank Schaefer 	em28xx_warn("write to i2c device at 0x%x timed out\n", addr);
21545f04e82SFrank Schaefer 	return -EIO;
2160c0d06caSMauro Carvalho Chehab }
2170c0d06caSMauro Carvalho Chehab 
2180c0d06caSMauro Carvalho Chehab /*
2190c0d06caSMauro Carvalho Chehab  * em28xx_i2c_recv_bytes()
2200c0d06caSMauro Carvalho Chehab  * read a byte from the i2c device
2210c0d06caSMauro Carvalho Chehab  */
222a6bad040SFrank Schaefer static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len)
2230c0d06caSMauro Carvalho Chehab {
2240c0d06caSMauro Carvalho Chehab 	int ret;
225f5ae371aSFrank Schaefer 
226f5ae371aSFrank Schaefer 	if (len < 1 || len > 64)
227f5ae371aSFrank Schaefer 		return -EOPNOTSUPP;
228fa74aca3SFrank Schaefer 	/*
229fa74aca3SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
230fa74aca3SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
231fa74aca3SFrank Schaefer 	 */
232f5ae371aSFrank Schaefer 
23345f04e82SFrank Schaefer 	/* Read data from i2c device */
2340c0d06caSMauro Carvalho Chehab 	ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
2350c0d06caSMauro Carvalho Chehab 	if (ret < 0) {
2367f6301d1SFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
2377f6301d1SFrank Schaefer 			    addr, ret);
23845f04e82SFrank Schaefer 		return ret;
23945f04e82SFrank Schaefer 	}
240fa74aca3SFrank Schaefer 	/*
241fa74aca3SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
2427f6301d1SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
2437f6301d1SFrank Schaefer 	 * specified slave address before AND no device is present at the
2447f6301d1SFrank Schaefer 	 * requested slave address.
2457f6301d1SFrank Schaefer 	 * Anyway, the next check will fail with -ENODEV in this case, so avoid
2467f6301d1SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
2477f6301d1SFrank Schaefer 	 */
24845f04e82SFrank Schaefer 
24945f04e82SFrank Schaefer 	/* Check success of the i2c operation */
25045f04e82SFrank Schaefer 	ret = dev->em28xx_read_reg(dev, 0x05);
25145f04e82SFrank Schaefer 	if (ret < 0) {
252d230d5adSFrank Schaefer 		em28xx_warn("failed to read i2c transfer status from bridge (error=%i)\n",
253d230d5adSFrank Schaefer 			    ret);
2540c0d06caSMauro Carvalho Chehab 		return ret;
2550c0d06caSMauro Carvalho Chehab 	}
25645f04e82SFrank Schaefer 	if (ret > 0) {
25745f04e82SFrank Schaefer 		if (ret == 0x10) {
2580c0d06caSMauro Carvalho Chehab 			return -ENODEV;
25945f04e82SFrank Schaefer 		} else {
26045f04e82SFrank Schaefer 			em28xx_warn("unknown i2c error (status=%i)\n", ret);
26145f04e82SFrank Schaefer 			return -EIO;
26245f04e82SFrank Schaefer 		}
26345f04e82SFrank Schaefer 	}
26445f04e82SFrank Schaefer 	return len;
2650c0d06caSMauro Carvalho Chehab }
2660c0d06caSMauro Carvalho Chehab 
2670c0d06caSMauro Carvalho Chehab /*
2680c0d06caSMauro Carvalho Chehab  * em28xx_i2c_check_for_device()
2690c0d06caSMauro Carvalho Chehab  * check if there is a i2c_device at the supplied address
2700c0d06caSMauro Carvalho Chehab  */
271a6bad040SFrank Schaefer static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr)
2720c0d06caSMauro Carvalho Chehab {
2730c0d06caSMauro Carvalho Chehab 	int ret;
27445f04e82SFrank Schaefer 	u8 buf;
2750c0d06caSMauro Carvalho Chehab 
27645f04e82SFrank Schaefer 	ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1);
27745f04e82SFrank Schaefer 	if (ret == 1)
2780c0d06caSMauro Carvalho Chehab 		return 0;
27945f04e82SFrank Schaefer 	return (ret < 0) ? ret : -EIO;
2800c0d06caSMauro Carvalho Chehab }
2810c0d06caSMauro Carvalho Chehab 
2820c0d06caSMauro Carvalho Chehab /*
283a3ea4bf9SFrank Schaefer  * em25xx_bus_B_send_bytes
284a3ea4bf9SFrank Schaefer  * write bytes to the i2c device
285a3ea4bf9SFrank Schaefer  */
286a3ea4bf9SFrank Schaefer static int em25xx_bus_B_send_bytes(struct em28xx *dev, u16 addr, u8 *buf,
287a3ea4bf9SFrank Schaefer 				   u16 len)
288a3ea4bf9SFrank Schaefer {
289a3ea4bf9SFrank Schaefer 	int ret;
290a3ea4bf9SFrank Schaefer 
291a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
292a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
293a3ea4bf9SFrank Schaefer 	/*
294a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
295a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
296a3ea4bf9SFrank Schaefer 	 */
297a3ea4bf9SFrank Schaefer 
298a3ea4bf9SFrank Schaefer 	/* Set register and write value */
299a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_write_regs_req(dev, 0x06, addr, buf, len);
300a3ea4bf9SFrank Schaefer 	if (ret != len) {
301a3ea4bf9SFrank Schaefer 		if (ret < 0) {
302a3ea4bf9SFrank Schaefer 			em28xx_warn("writing to i2c device at 0x%x failed (error=%i)\n",
303a3ea4bf9SFrank Schaefer 				    addr, ret);
304a3ea4bf9SFrank Schaefer 			return ret;
305a3ea4bf9SFrank Schaefer 		} else {
306a3ea4bf9SFrank Schaefer 			em28xx_warn("%i bytes write to i2c device at 0x%x requested, but %i bytes written\n",
307a3ea4bf9SFrank Schaefer 				    len, addr, ret);
308a3ea4bf9SFrank Schaefer 			return -EIO;
309a3ea4bf9SFrank Schaefer 		}
310a3ea4bf9SFrank Schaefer 	}
311a3ea4bf9SFrank Schaefer 	/* Check success */
312a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
313a3ea4bf9SFrank Schaefer 	/*
314a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
315a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
316a3ea4bf9SFrank Schaefer 	 */
317a3ea4bf9SFrank Schaefer 	if (!ret)
318a3ea4bf9SFrank Schaefer 		return len;
319a3ea4bf9SFrank Schaefer 	else if (ret > 0)
320a3ea4bf9SFrank Schaefer 		return -ENODEV;
321a3ea4bf9SFrank Schaefer 
322a3ea4bf9SFrank Schaefer 	return ret;
323a3ea4bf9SFrank Schaefer 	/*
324a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
325a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
326a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
327a3ea4bf9SFrank Schaefer 	 */
328a3ea4bf9SFrank Schaefer }
329a3ea4bf9SFrank Schaefer 
330a3ea4bf9SFrank Schaefer /*
331a3ea4bf9SFrank Schaefer  * em25xx_bus_B_recv_bytes
332a3ea4bf9SFrank Schaefer  * read bytes from the i2c device
333a3ea4bf9SFrank Schaefer  */
334a3ea4bf9SFrank Schaefer static int em25xx_bus_B_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf,
335a3ea4bf9SFrank Schaefer 				   u16 len)
336a3ea4bf9SFrank Schaefer {
337a3ea4bf9SFrank Schaefer 	int ret;
338a3ea4bf9SFrank Schaefer 
339a3ea4bf9SFrank Schaefer 	if (len < 1 || len > 64)
340a3ea4bf9SFrank Schaefer 		return -EOPNOTSUPP;
341a3ea4bf9SFrank Schaefer 	/*
342a3ea4bf9SFrank Schaefer 	 * NOTE: limited by the USB ctrl message constraints
343a3ea4bf9SFrank Schaefer 	 * Zero length reads always succeed, even if no device is connected
344a3ea4bf9SFrank Schaefer 	 */
345a3ea4bf9SFrank Schaefer 
346a3ea4bf9SFrank Schaefer 	/* Read value */
347a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req_len(dev, 0x06, addr, buf, len);
348a3ea4bf9SFrank Schaefer 	if (ret < 0) {
349a3ea4bf9SFrank Schaefer 		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)\n",
350a3ea4bf9SFrank Schaefer 			    addr, ret);
351a3ea4bf9SFrank Schaefer 		return ret;
352a3ea4bf9SFrank Schaefer 	}
353a3ea4bf9SFrank Schaefer 	/*
354a3ea4bf9SFrank Schaefer 	 * NOTE: some devices with two i2c busses have the bad habit to return 0
355a3ea4bf9SFrank Schaefer 	 * bytes if we are on bus B AND there was no write attempt to the
356a3ea4bf9SFrank Schaefer 	 * specified slave address before AND no device is present at the
357a3ea4bf9SFrank Schaefer 	 * requested slave address.
358a3ea4bf9SFrank Schaefer 	 * Anyway, the next check will fail with -ENODEV in this case, so avoid
359a3ea4bf9SFrank Schaefer 	 * spamming the system log on device probing and do nothing here.
360a3ea4bf9SFrank Schaefer 	 */
361a3ea4bf9SFrank Schaefer 
362a3ea4bf9SFrank Schaefer 	/* Check success */
363a3ea4bf9SFrank Schaefer 	ret = dev->em28xx_read_reg_req(dev, 0x08, 0x0000);
364a3ea4bf9SFrank Schaefer 	/*
365a3ea4bf9SFrank Schaefer 	 * NOTE: the only error we've seen so far is
366a3ea4bf9SFrank Schaefer 	 * 0x01 when the slave device is not present
367a3ea4bf9SFrank Schaefer 	 */
368a3ea4bf9SFrank Schaefer 	if (!ret)
369a3ea4bf9SFrank Schaefer 		return len;
370a3ea4bf9SFrank Schaefer 	else if (ret > 0)
371a3ea4bf9SFrank Schaefer 		return -ENODEV;
372a3ea4bf9SFrank Schaefer 
373a3ea4bf9SFrank Schaefer 	return ret;
374a3ea4bf9SFrank Schaefer 	/*
375a3ea4bf9SFrank Schaefer 	 * NOTE: With chip types (other chip IDs) which actually don't support
376a3ea4bf9SFrank Schaefer 	 * this operation, it seems to succeed ALWAYS ! (even if there is no
377a3ea4bf9SFrank Schaefer 	 * slave device or even no second i2c bus provided)
378a3ea4bf9SFrank Schaefer 	 */
379a3ea4bf9SFrank Schaefer }
380a3ea4bf9SFrank Schaefer 
381a3ea4bf9SFrank Schaefer /*
382a3ea4bf9SFrank Schaefer  * em25xx_bus_B_check_for_device()
383a3ea4bf9SFrank Schaefer  * check if there is a i2c device at the supplied address
384a3ea4bf9SFrank Schaefer  */
385a3ea4bf9SFrank Schaefer static int em25xx_bus_B_check_for_device(struct em28xx *dev, u16 addr)
386a3ea4bf9SFrank Schaefer {
387a3ea4bf9SFrank Schaefer 	u8 buf;
388a3ea4bf9SFrank Schaefer 	int ret;
389a3ea4bf9SFrank Schaefer 
390a3ea4bf9SFrank Schaefer 	ret = em25xx_bus_B_recv_bytes(dev, addr, &buf, 1);
391a3ea4bf9SFrank Schaefer 	if (ret < 0)
392a3ea4bf9SFrank Schaefer 		return ret;
393a3ea4bf9SFrank Schaefer 
394a3ea4bf9SFrank Schaefer 	return 0;
395a3ea4bf9SFrank Schaefer 	/*
396a3ea4bf9SFrank Schaefer 	 * NOTE: With chips which do not support this operation,
397a3ea4bf9SFrank Schaefer 	 * it seems to succeed ALWAYS ! (even if no device connected)
398a3ea4bf9SFrank Schaefer 	 */
399a3ea4bf9SFrank Schaefer }
400a3ea4bf9SFrank Schaefer 
401a3ea4bf9SFrank Schaefer static inline int i2c_check_for_device(struct em28xx_i2c_bus *i2c_bus, u16 addr)
402a3ea4bf9SFrank Schaefer {
403a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
404a3ea4bf9SFrank Schaefer 	int rc = -EOPNOTSUPP;
405a3ea4bf9SFrank Schaefer 
406a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
407a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_check_for_device(dev, addr);
408a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
409a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_check_for_device(dev, addr);
410a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
411a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_check_for_device(dev, addr);
412a3ea4bf9SFrank Schaefer 	if (rc == -ENODEV) {
413a3ea4bf9SFrank Schaefer 		if (i2c_debug)
414a3ea4bf9SFrank Schaefer 			printk(" no device\n");
415a3ea4bf9SFrank Schaefer 	}
416a3ea4bf9SFrank Schaefer 	return rc;
417a3ea4bf9SFrank Schaefer }
418a3ea4bf9SFrank Schaefer 
419a3ea4bf9SFrank Schaefer static inline int i2c_recv_bytes(struct em28xx_i2c_bus *i2c_bus,
420a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg)
421a3ea4bf9SFrank Schaefer {
422a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
423a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
424a3ea4bf9SFrank Schaefer 	int byte, rc = -EOPNOTSUPP;
425a3ea4bf9SFrank Schaefer 
426a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
427a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
428a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
429a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_recv_bytes(dev, addr, msg.buf, msg.len);
430a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
431a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_recv_bytes(dev, addr, msg.buf, msg.len);
432a3ea4bf9SFrank Schaefer 	if (i2c_debug) {
433a3ea4bf9SFrank Schaefer 		for (byte = 0; byte < msg.len; byte++)
434a3ea4bf9SFrank Schaefer 			printk(" %02x", msg.buf[byte]);
435a3ea4bf9SFrank Schaefer 	}
436a3ea4bf9SFrank Schaefer 	return rc;
437a3ea4bf9SFrank Schaefer }
438a3ea4bf9SFrank Schaefer 
439a3ea4bf9SFrank Schaefer static inline int i2c_send_bytes(struct em28xx_i2c_bus *i2c_bus,
440a3ea4bf9SFrank Schaefer 				 struct i2c_msg msg, int stop)
441a3ea4bf9SFrank Schaefer {
442a3ea4bf9SFrank Schaefer 	struct em28xx *dev = i2c_bus->dev;
443a3ea4bf9SFrank Schaefer 	u16 addr = msg.addr << 1;
444a3ea4bf9SFrank Schaefer 	int byte, rc = -EOPNOTSUPP;
445a3ea4bf9SFrank Schaefer 
446a3ea4bf9SFrank Schaefer 	if (i2c_debug) {
447a3ea4bf9SFrank Schaefer 		for (byte = 0; byte < msg.len; byte++)
448a3ea4bf9SFrank Schaefer 			printk(" %02x", msg.buf[byte]);
449a3ea4bf9SFrank Schaefer 	}
450a3ea4bf9SFrank Schaefer 	if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX)
451a3ea4bf9SFrank Schaefer 		rc = em28xx_i2c_send_bytes(dev, addr, msg.buf, msg.len, stop);
452a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)
453a3ea4bf9SFrank Schaefer 		rc = em2800_i2c_send_bytes(dev, addr, msg.buf, msg.len);
454a3ea4bf9SFrank Schaefer 	else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)
455a3ea4bf9SFrank Schaefer 		rc = em25xx_bus_B_send_bytes(dev, addr, msg.buf, msg.len);
456a3ea4bf9SFrank Schaefer 	return rc;
457a3ea4bf9SFrank Schaefer }
458a3ea4bf9SFrank Schaefer 
459a3ea4bf9SFrank Schaefer /*
4600c0d06caSMauro Carvalho Chehab  * em28xx_i2c_xfer()
4610c0d06caSMauro Carvalho Chehab  * the main i2c transfer function
4620c0d06caSMauro Carvalho Chehab  */
4630c0d06caSMauro Carvalho Chehab static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
4640c0d06caSMauro Carvalho Chehab 			   struct i2c_msg msgs[], int num)
4650c0d06caSMauro Carvalho Chehab {
466aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
467aab3125cSMauro Carvalho Chehab 	struct em28xx *dev = i2c_bus->dev;
468aab3125cSMauro Carvalho Chehab 	unsigned bus = i2c_bus->bus;
469a3ea4bf9SFrank Schaefer 	int addr, rc, i;
4703190fbeeSMauro Carvalho Chehab 	u8 reg;
4710c0d06caSMauro Carvalho Chehab 
472aab3125cSMauro Carvalho Chehab 	rc = rt_mutex_trylock(&dev->i2c_bus_lock);
473aab3125cSMauro Carvalho Chehab 	if (rc < 0)
474aab3125cSMauro Carvalho Chehab 		return rc;
475aab3125cSMauro Carvalho Chehab 
476aab3125cSMauro Carvalho Chehab 	/* Switch I2C bus if needed */
477a3ea4bf9SFrank Schaefer 	if (bus != dev->cur_i2c_bus &&
478a3ea4bf9SFrank Schaefer 	    i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) {
479aab3125cSMauro Carvalho Chehab 		if (bus == 1)
4803190fbeeSMauro Carvalho Chehab 			reg = EM2874_I2C_SECONDARY_BUS_SELECT;
481aab3125cSMauro Carvalho Chehab 		else
4823190fbeeSMauro Carvalho Chehab 			reg = 0;
4833190fbeeSMauro Carvalho Chehab 		em28xx_write_reg_bits(dev, EM28XX_R06_I2C_CLK, reg,
4843190fbeeSMauro Carvalho Chehab 				      EM2874_I2C_SECONDARY_BUS_SELECT);
485aab3125cSMauro Carvalho Chehab 		dev->cur_i2c_bus = bus;
486aab3125cSMauro Carvalho Chehab 	}
487aab3125cSMauro Carvalho Chehab 
488aab3125cSMauro Carvalho Chehab 	if (num <= 0) {
489aab3125cSMauro Carvalho Chehab 		rt_mutex_unlock(&dev->i2c_bus_lock);
4900c0d06caSMauro Carvalho Chehab 		return 0;
491aab3125cSMauro Carvalho Chehab 	}
4920c0d06caSMauro Carvalho Chehab 	for (i = 0; i < num; i++) {
4930c0d06caSMauro Carvalho Chehab 		addr = msgs[i].addr << 1;
494d90f0677SFrank Schaefer 		if (i2c_debug)
495d7a80eaaSFrank Schaefer 			printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:",
496d7a80eaaSFrank Schaefer 			       dev->name, __func__ ,
4970c0d06caSMauro Carvalho Chehab 			       (msgs[i].flags & I2C_M_RD) ? "read" : "write",
498d7a80eaaSFrank Schaefer 			       i == num - 1 ? "stop" : "nonstop",
499d7a80eaaSFrank Schaefer 			       addr, msgs[i].len);
5000c0d06caSMauro Carvalho Chehab 		if (!msgs[i].len) { /* no len: check only for device presence */
501a3ea4bf9SFrank Schaefer 			rc = i2c_check_for_device(i2c_bus, addr);
50245f04e82SFrank Schaefer 			if (rc == -ENODEV) {
503aab3125cSMauro Carvalho Chehab 				rt_mutex_unlock(&dev->i2c_bus_lock);
5040c0d06caSMauro Carvalho Chehab 				return rc;
5050c0d06caSMauro Carvalho Chehab 			}
5060c0d06caSMauro Carvalho Chehab 		} else if (msgs[i].flags & I2C_M_RD) {
5070c0d06caSMauro Carvalho Chehab 			/* read bytes */
508a3ea4bf9SFrank Schaefer 			rc = i2c_recv_bytes(i2c_bus, msgs[i]);
5090c0d06caSMauro Carvalho Chehab 		} else {
5100c0d06caSMauro Carvalho Chehab 			/* write bytes */
511a3ea4bf9SFrank Schaefer 			rc = i2c_send_bytes(i2c_bus, msgs[i], i == num - 1);
5120c0d06caSMauro Carvalho Chehab 		}
51345f04e82SFrank Schaefer 		if (rc < 0) {
514d90f0677SFrank Schaefer 			if (i2c_debug)
51545f04e82SFrank Schaefer 				printk(" ERROR: %i\n", rc);
516aab3125cSMauro Carvalho Chehab 			rt_mutex_unlock(&dev->i2c_bus_lock);
51745f04e82SFrank Schaefer 			return rc;
51845f04e82SFrank Schaefer 		}
519d90f0677SFrank Schaefer 		if (i2c_debug)
5200c0d06caSMauro Carvalho Chehab 			printk("\n");
5210c0d06caSMauro Carvalho Chehab 	}
5220c0d06caSMauro Carvalho Chehab 
523aab3125cSMauro Carvalho Chehab 	rt_mutex_unlock(&dev->i2c_bus_lock);
5240c0d06caSMauro Carvalho Chehab 	return num;
5250c0d06caSMauro Carvalho Chehab }
5260c0d06caSMauro Carvalho Chehab 
527fa74aca3SFrank Schaefer /*
528fa74aca3SFrank Schaefer  * based on linux/sunrpc/svcauth.h and linux/hash.h
5290c0d06caSMauro Carvalho Chehab  * The original hash function returns a different value, if arch is x86_64
5300c0d06caSMauro Carvalho Chehab  * or i386.
5310c0d06caSMauro Carvalho Chehab  */
5320c0d06caSMauro Carvalho Chehab static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
5330c0d06caSMauro Carvalho Chehab {
5340c0d06caSMauro Carvalho Chehab 	unsigned long hash = 0;
5350c0d06caSMauro Carvalho Chehab 	unsigned long l = 0;
5360c0d06caSMauro Carvalho Chehab 	int len = 0;
5370c0d06caSMauro Carvalho Chehab 	unsigned char c;
5380c0d06caSMauro Carvalho Chehab 	do {
5390c0d06caSMauro Carvalho Chehab 		if (len == length) {
5400c0d06caSMauro Carvalho Chehab 			c = (char)len;
5410c0d06caSMauro Carvalho Chehab 			len = -1;
5420c0d06caSMauro Carvalho Chehab 		} else
5430c0d06caSMauro Carvalho Chehab 			c = *buf++;
5440c0d06caSMauro Carvalho Chehab 		l = (l << 8) | c;
5450c0d06caSMauro Carvalho Chehab 		len++;
5460c0d06caSMauro Carvalho Chehab 		if ((len & (32 / 8 - 1)) == 0)
5470c0d06caSMauro Carvalho Chehab 			hash = ((hash^l) * 0x9e370001UL);
5480c0d06caSMauro Carvalho Chehab 	} while (len);
5490c0d06caSMauro Carvalho Chehab 
5500c0d06caSMauro Carvalho Chehab 	return (hash >> (32 - bits)) & 0xffffffffUL;
5510c0d06caSMauro Carvalho Chehab }
5520c0d06caSMauro Carvalho Chehab 
553fa74aca3SFrank Schaefer /*
554fa74aca3SFrank Schaefer  * Helper function to read data blocks from i2c clients with 8 or 16 bit
555fa74aca3SFrank Schaefer  * address width, 8 bit register width and auto incrementation been activated
556fa74aca3SFrank Schaefer  */
557aab3125cSMauro Carvalho Chehab static int em28xx_i2c_read_block(struct em28xx *dev, unsigned bus, u16 addr,
558aab3125cSMauro Carvalho Chehab 				 bool addr_w16, u16 len, u8 *data)
559d832c5b2SFrank Schaefer {
560d832c5b2SFrank Schaefer 	int remain = len, rsize, rsize_max, ret;
561d832c5b2SFrank Schaefer 	u8 buf[2];
562d832c5b2SFrank Schaefer 
563d832c5b2SFrank Schaefer 	/* Sanity check */
564d832c5b2SFrank Schaefer 	if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1))
565d832c5b2SFrank Schaefer 		return -EINVAL;
566d832c5b2SFrank Schaefer 	/* Select address */
567d832c5b2SFrank Schaefer 	buf[0] = addr >> 8;
568d832c5b2SFrank Schaefer 	buf[1] = addr & 0xff;
569aab3125cSMauro Carvalho Chehab 	ret = i2c_master_send(&dev->i2c_client[bus], buf + !addr_w16, 1 + addr_w16);
570d832c5b2SFrank Schaefer 	if (ret < 0)
571d832c5b2SFrank Schaefer 		return ret;
572d832c5b2SFrank Schaefer 	/* Read data */
573d832c5b2SFrank Schaefer 	if (dev->board.is_em2800)
574d832c5b2SFrank Schaefer 		rsize_max = 4;
575d832c5b2SFrank Schaefer 	else
576d832c5b2SFrank Schaefer 		rsize_max = 64;
577d832c5b2SFrank Schaefer 	while (remain > 0) {
578d832c5b2SFrank Schaefer 		if (remain > rsize_max)
579d832c5b2SFrank Schaefer 			rsize = rsize_max;
580d832c5b2SFrank Schaefer 		else
581d832c5b2SFrank Schaefer 			rsize = remain;
582d832c5b2SFrank Schaefer 
583aab3125cSMauro Carvalho Chehab 		ret = i2c_master_recv(&dev->i2c_client[bus], data, rsize);
584d832c5b2SFrank Schaefer 		if (ret < 0)
585d832c5b2SFrank Schaefer 			return ret;
586d832c5b2SFrank Schaefer 
587d832c5b2SFrank Schaefer 		remain -= rsize;
588d832c5b2SFrank Schaefer 		data += rsize;
589d832c5b2SFrank Schaefer 	}
590d832c5b2SFrank Schaefer 
591d832c5b2SFrank Schaefer 	return len;
592d832c5b2SFrank Schaefer }
593d832c5b2SFrank Schaefer 
594aab3125cSMauro Carvalho Chehab static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned bus,
595aab3125cSMauro Carvalho Chehab 			     u8 **eedata, u16 *eedata_len)
5960c0d06caSMauro Carvalho Chehab {
597510e884cSFrank Schaefer 	const u16 len = 256;
598fa74aca3SFrank Schaefer 	/*
599fa74aca3SFrank Schaefer 	 * FIXME common length/size for bytes to read, to display, hash
600510e884cSFrank Schaefer 	 * calculation and returned device dataset. Simplifies the code a lot,
601fa74aca3SFrank Schaefer 	 * but we might have to deal with multiple sizes in the future !
602fa74aca3SFrank Schaefer 	 */
603d832c5b2SFrank Schaefer 	int i, err;
604510e884cSFrank Schaefer 	struct em28xx_eeprom *dev_config;
605510e884cSFrank Schaefer 	u8 buf, *data;
6060c0d06caSMauro Carvalho Chehab 
607a217968fSFrank Schaefer 	*eedata = NULL;
608510e884cSFrank Schaefer 	*eedata_len = 0;
609a217968fSFrank Schaefer 
610aab3125cSMauro Carvalho Chehab 	/* EEPROM is always on i2c bus 0 on all known devices. */
611aab3125cSMauro Carvalho Chehab 
612aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].addr = 0xa0 >> 1;
6130c0d06caSMauro Carvalho Chehab 
6140c0d06caSMauro Carvalho Chehab 	/* Check if board has eeprom */
615aab3125cSMauro Carvalho Chehab 	err = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
6160c0d06caSMauro Carvalho Chehab 	if (err < 0) {
61712d7ce18SFrank Schaefer 		em28xx_info("board has no eeprom\n");
6180c0d06caSMauro Carvalho Chehab 		return -ENODEV;
6190c0d06caSMauro Carvalho Chehab 	}
6200c0d06caSMauro Carvalho Chehab 
621a217968fSFrank Schaefer 	data = kzalloc(len, GFP_KERNEL);
622a217968fSFrank Schaefer 	if (data == NULL)
623a217968fSFrank Schaefer 		return -ENOMEM;
624a217968fSFrank Schaefer 
625d832c5b2SFrank Schaefer 	/* Read EEPROM content */
626aab3125cSMauro Carvalho Chehab 	err = em28xx_i2c_read_block(dev, bus, 0x0000,
627aab3125cSMauro Carvalho Chehab 				    dev->eeprom_addrwidth_16bit,
628a217968fSFrank Schaefer 				    len, data);
629d832c5b2SFrank Schaefer 	if (err != len) {
63012d7ce18SFrank Schaefer 		em28xx_errdev("failed to read eeprom (err=%d)\n", err);
631510e884cSFrank Schaefer 		goto error;
6320c0d06caSMauro Carvalho Chehab 	}
63390271964SFrank Schaefer 
63487b52439SFrank Schaefer 	/* Display eeprom content */
6350c0d06caSMauro Carvalho Chehab 	for (i = 0; i < len; i++) {
63687b52439SFrank Schaefer 		if (0 == (i % 16)) {
63787b52439SFrank Schaefer 			if (dev->eeprom_addrwidth_16bit)
63887b52439SFrank Schaefer 				em28xx_info("i2c eeprom %04x:", i);
63987b52439SFrank Schaefer 			else
64012d7ce18SFrank Schaefer 				em28xx_info("i2c eeprom %02x:", i);
64187b52439SFrank Schaefer 		}
642a217968fSFrank Schaefer 		printk(" %02x", data[i]);
6430c0d06caSMauro Carvalho Chehab 		if (15 == (i % 16))
6440c0d06caSMauro Carvalho Chehab 			printk("\n");
6450c0d06caSMauro Carvalho Chehab 	}
646510e884cSFrank Schaefer 	if (dev->eeprom_addrwidth_16bit)
647510e884cSFrank Schaefer 		em28xx_info("i2c eeprom %04x: ... (skipped)\n", i);
6480c0d06caSMauro Carvalho Chehab 
64987b52439SFrank Schaefer 	if (dev->eeprom_addrwidth_16bit &&
650a217968fSFrank Schaefer 	    data[0] == 0x26 && data[3] == 0x00) {
65187b52439SFrank Schaefer 		/* new eeprom format; size 4-64kb */
652510e884cSFrank Schaefer 		u16 mc_start;
653510e884cSFrank Schaefer 		u16 hwconf_offset;
654510e884cSFrank Schaefer 
655a217968fSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
656510e884cSFrank Schaefer 		mc_start = (data[1] << 8) + 4;	/* usually 0x0004 */
657510e884cSFrank Schaefer 
658d230d5adSFrank Schaefer 		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
659510e884cSFrank Schaefer 			    data[0], data[1], data[2], data[3], dev->hash);
660510e884cSFrank Schaefer 		em28xx_info("EEPROM info:\n");
661d230d5adSFrank Schaefer 		em28xx_info("\tmicrocode start address = 0x%04x, boot configuration = 0x%02x\n",
662510e884cSFrank Schaefer 			    mc_start, data[2]);
663fa74aca3SFrank Schaefer 		/*
664fa74aca3SFrank Schaefer 		 * boot configuration (address 0x0002):
66587b52439SFrank Schaefer 		 * [0]   microcode download speed: 1 = 400 kHz; 0 = 100 kHz
66687b52439SFrank Schaefer 		 * [1]   always selects 12 kb RAM
66787b52439SFrank Schaefer 		 * [2]   USB device speed: 1 = force Full Speed; 0 = auto detect
66887b52439SFrank Schaefer 		 * [4]   1 = force fast mode and no suspend for device testing
66987b52439SFrank Schaefer 		 * [5:7] USB PHY tuning registers; determined by device
67087b52439SFrank Schaefer 		 *       characterization
67187b52439SFrank Schaefer 		 */
67287b52439SFrank Schaefer 
673fa74aca3SFrank Schaefer 		/*
674fa74aca3SFrank Schaefer 		 * Read hardware config dataset offset from address
675fa74aca3SFrank Schaefer 		 * (microcode start + 46)
676fa74aca3SFrank Schaefer 		 */
677aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, mc_start + 46, 1, 2,
678aab3125cSMauro Carvalho Chehab 					    data);
679510e884cSFrank Schaefer 		if (err != 2) {
680510e884cSFrank Schaefer 			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
681510e884cSFrank Schaefer 				      err);
682510e884cSFrank Schaefer 			goto error;
683510e884cSFrank Schaefer 		}
68487b52439SFrank Schaefer 
685510e884cSFrank Schaefer 		/* Calculate hardware config dataset start address */
686510e884cSFrank Schaefer 		hwconf_offset = mc_start + data[0] + (data[1] << 8);
687510e884cSFrank Schaefer 
688510e884cSFrank Schaefer 		/* Read hardware config dataset */
689fa74aca3SFrank Schaefer 		/*
690fa74aca3SFrank Schaefer 		 * NOTE: the microcode copy can be multiple pages long, but
691510e884cSFrank Schaefer 		 * we assume the hardware config dataset is the same as in
692510e884cSFrank Schaefer 		 * the old eeprom and not longer than 256 bytes.
693510e884cSFrank Schaefer 		 * tveeprom is currently also limited to 256 bytes.
694510e884cSFrank Schaefer 		 */
695aab3125cSMauro Carvalho Chehab 		err = em28xx_i2c_read_block(dev, bus, hwconf_offset, 1, len,
696aab3125cSMauro Carvalho Chehab 					    data);
697510e884cSFrank Schaefer 		if (err != len) {
698510e884cSFrank Schaefer 			em28xx_errdev("failed to read hardware configuration data from eeprom (err=%d)\n",
699510e884cSFrank Schaefer 				      err);
700510e884cSFrank Schaefer 			goto error;
701510e884cSFrank Schaefer 		}
702510e884cSFrank Schaefer 
703510e884cSFrank Schaefer 		/* Verify hardware config dataset */
704510e884cSFrank Schaefer 		/* NOTE: not all devices provide this type of dataset */
705510e884cSFrank Schaefer 		if (data[0] != 0x1a || data[1] != 0xeb ||
706a217968fSFrank Schaefer 		    data[2] != 0x67 || data[3] != 0x95) {
707510e884cSFrank Schaefer 			em28xx_info("\tno hardware configuration dataset found in eeprom\n");
708510e884cSFrank Schaefer 			kfree(data);
709510e884cSFrank Schaefer 			return 0;
710510e884cSFrank Schaefer 		}
711510e884cSFrank Schaefer 
712510e884cSFrank Schaefer 		/* TODO: decrypt eeprom data for camera bridges (em25xx, em276x+) */
713510e884cSFrank Schaefer 
714510e884cSFrank Schaefer 	} else if (!dev->eeprom_addrwidth_16bit &&
715510e884cSFrank Schaefer 		   data[0] == 0x1a && data[1] == 0xeb &&
716510e884cSFrank Schaefer 		   data[2] == 0x67 && data[3] == 0x95) {
717510e884cSFrank Schaefer 		dev->hash = em28xx_hash_mem(data, len, 32);
718d230d5adSFrank Schaefer 		em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n",
719510e884cSFrank Schaefer 			    data[0], data[1], data[2], data[3], dev->hash);
720510e884cSFrank Schaefer 		em28xx_info("EEPROM info:\n");
721510e884cSFrank Schaefer 	} else {
72287b52439SFrank Schaefer 		em28xx_info("unknown eeprom format or eeprom corrupted !\n");
723510e884cSFrank Schaefer 		err = -ENODEV;
724510e884cSFrank Schaefer 		goto error;
725f55eacbeSFrank Schaefer 	}
726f55eacbeSFrank Schaefer 
727a217968fSFrank Schaefer 	*eedata = data;
728510e884cSFrank Schaefer 	*eedata_len = len;
72932bf7c6cSAlban Browaeys 	dev_config = (void *)*eedata;
730a217968fSFrank Schaefer 
731510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) >> 4 & 0x3) {
7320c0d06caSMauro Carvalho Chehab 	case 0:
73312d7ce18SFrank Schaefer 		em28xx_info("\tNo audio on board.\n");
7340c0d06caSMauro Carvalho Chehab 		break;
7350c0d06caSMauro Carvalho Chehab 	case 1:
73612d7ce18SFrank Schaefer 		em28xx_info("\tAC97 audio (5 sample rates)\n");
7370c0d06caSMauro Carvalho Chehab 		break;
7380c0d06caSMauro Carvalho Chehab 	case 2:
739*687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
74012d7ce18SFrank Schaefer 			em28xx_info("\tI2S audio, sample rate=32k\n");
741*687ff8b0SFrank Schaefer 		else
742*687ff8b0SFrank Schaefer 			em28xx_info("\tI2S audio, 3 sample rates\n");
7430c0d06caSMauro Carvalho Chehab 		break;
7440c0d06caSMauro Carvalho Chehab 	case 3:
745*687ff8b0SFrank Schaefer 		if (dev->chip_id < CHIP_ID_EM2860)
74612d7ce18SFrank Schaefer 			em28xx_info("\tI2S audio, 3 sample rates\n");
747*687ff8b0SFrank Schaefer 		else
748*687ff8b0SFrank Schaefer 			em28xx_info("\tI2S audio, 5 sample rates\n");
7490c0d06caSMauro Carvalho Chehab 		break;
7500c0d06caSMauro Carvalho Chehab 	}
7510c0d06caSMauro Carvalho Chehab 
752510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 3)
75312d7ce18SFrank Schaefer 		em28xx_info("\tUSB Remote wakeup capable\n");
7540c0d06caSMauro Carvalho Chehab 
755510e884cSFrank Schaefer 	if (le16_to_cpu(dev_config->chip_conf) & 1 << 2)
75612d7ce18SFrank Schaefer 		em28xx_info("\tUSB Self power capable\n");
7570c0d06caSMauro Carvalho Chehab 
758510e884cSFrank Schaefer 	switch (le16_to_cpu(dev_config->chip_conf) & 0x3) {
7590c0d06caSMauro Carvalho Chehab 	case 0:
76012d7ce18SFrank Schaefer 		em28xx_info("\t500mA max power\n");
7610c0d06caSMauro Carvalho Chehab 		break;
7620c0d06caSMauro Carvalho Chehab 	case 1:
76312d7ce18SFrank Schaefer 		em28xx_info("\t400mA max power\n");
7640c0d06caSMauro Carvalho Chehab 		break;
7650c0d06caSMauro Carvalho Chehab 	case 2:
76612d7ce18SFrank Schaefer 		em28xx_info("\t300mA max power\n");
7670c0d06caSMauro Carvalho Chehab 		break;
7680c0d06caSMauro Carvalho Chehab 	case 3:
76912d7ce18SFrank Schaefer 		em28xx_info("\t200mA max power\n");
7700c0d06caSMauro Carvalho Chehab 		break;
7710c0d06caSMauro Carvalho Chehab 	}
77212d7ce18SFrank Schaefer 	em28xx_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
773510e884cSFrank Schaefer 		    dev_config->string_idx_table,
774510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string1),
775510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string2),
776510e884cSFrank Schaefer 		    le16_to_cpu(dev_config->string3));
7770c0d06caSMauro Carvalho Chehab 
7780c0d06caSMauro Carvalho Chehab 	return 0;
779510e884cSFrank Schaefer 
780510e884cSFrank Schaefer error:
781510e884cSFrank Schaefer 	kfree(data);
782510e884cSFrank Schaefer 	return err;
7830c0d06caSMauro Carvalho Chehab }
7840c0d06caSMauro Carvalho Chehab 
7850c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
7860c0d06caSMauro Carvalho Chehab 
7870c0d06caSMauro Carvalho Chehab /*
7880c0d06caSMauro Carvalho Chehab  * functionality()
7890c0d06caSMauro Carvalho Chehab  */
790aab3125cSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *i2c_adap)
7910c0d06caSMauro Carvalho Chehab {
792aab3125cSMauro Carvalho Chehab 	struct em28xx_i2c_bus *i2c_bus = i2c_adap->algo_data;
793aab3125cSMauro Carvalho Chehab 
794a3ea4bf9SFrank Schaefer 	if ((i2c_bus->algo_type == EM28XX_I2C_ALGO_EM28XX) ||
795a3ea4bf9SFrank Schaefer 	    (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM25XX_BUS_B)) {
796a3ea4bf9SFrank Schaefer 		return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
797a3ea4bf9SFrank Schaefer 	} else if (i2c_bus->algo_type == EM28XX_I2C_ALGO_EM2800)  {
798a3ea4bf9SFrank Schaefer 		return (I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL) &
799a3ea4bf9SFrank Schaefer 			~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA;
800a3ea4bf9SFrank Schaefer 	}
801a3ea4bf9SFrank Schaefer 
802a3ea4bf9SFrank Schaefer 	WARN(1, "Unknown i2c bus algorithm.\n");
803a3ea4bf9SFrank Schaefer 	return 0;
8040c0d06caSMauro Carvalho Chehab }
8050c0d06caSMauro Carvalho Chehab 
8060c0d06caSMauro Carvalho Chehab static struct i2c_algorithm em28xx_algo = {
8070c0d06caSMauro Carvalho Chehab 	.master_xfer   = em28xx_i2c_xfer,
8080c0d06caSMauro Carvalho Chehab 	.functionality = functionality,
8090c0d06caSMauro Carvalho Chehab };
8100c0d06caSMauro Carvalho Chehab 
8110c0d06caSMauro Carvalho Chehab static struct i2c_adapter em28xx_adap_template = {
8120c0d06caSMauro Carvalho Chehab 	.owner = THIS_MODULE,
8130c0d06caSMauro Carvalho Chehab 	.name = "em28xx",
8140c0d06caSMauro Carvalho Chehab 	.algo = &em28xx_algo,
8150c0d06caSMauro Carvalho Chehab };
8160c0d06caSMauro Carvalho Chehab 
8170c0d06caSMauro Carvalho Chehab static struct i2c_client em28xx_client_template = {
8180c0d06caSMauro Carvalho Chehab 	.name = "em28xx internal",
8190c0d06caSMauro Carvalho Chehab };
8200c0d06caSMauro Carvalho Chehab 
8210c0d06caSMauro Carvalho Chehab /* ----------------------------------------------------------- */
8220c0d06caSMauro Carvalho Chehab 
8230c0d06caSMauro Carvalho Chehab /*
8240c0d06caSMauro Carvalho Chehab  * i2c_devs
8250c0d06caSMauro Carvalho Chehab  * incomplete list of known devices
8260c0d06caSMauro Carvalho Chehab  */
8270c0d06caSMauro Carvalho Chehab static char *i2c_devs[128] = {
8280b3966e4SFrank Schaefer 	[0x3e >> 1] = "remote IR sensor",
8290c0d06caSMauro Carvalho Chehab 	[0x4a >> 1] = "saa7113h",
8300c0d06caSMauro Carvalho Chehab 	[0x52 >> 1] = "drxk",
8310c0d06caSMauro Carvalho Chehab 	[0x60 >> 1] = "remote IR sensor",
8320c0d06caSMauro Carvalho Chehab 	[0x8e >> 1] = "remote IR sensor",
8330c0d06caSMauro Carvalho Chehab 	[0x86 >> 1] = "tda9887",
8340c0d06caSMauro Carvalho Chehab 	[0x80 >> 1] = "msp34xx",
8350c0d06caSMauro Carvalho Chehab 	[0x88 >> 1] = "msp34xx",
8360c0d06caSMauro Carvalho Chehab 	[0xa0 >> 1] = "eeprom",
8370c0d06caSMauro Carvalho Chehab 	[0xb0 >> 1] = "tda9874",
8380c0d06caSMauro Carvalho Chehab 	[0xb8 >> 1] = "tvp5150a",
8390c0d06caSMauro Carvalho Chehab 	[0xba >> 1] = "webcam sensor or tvp5150a",
8400c0d06caSMauro Carvalho Chehab 	[0xc0 >> 1] = "tuner (analog)",
8410c0d06caSMauro Carvalho Chehab 	[0xc2 >> 1] = "tuner (analog)",
8420c0d06caSMauro Carvalho Chehab 	[0xc4 >> 1] = "tuner (analog)",
8430c0d06caSMauro Carvalho Chehab 	[0xc6 >> 1] = "tuner (analog)",
8440c0d06caSMauro Carvalho Chehab };
8450c0d06caSMauro Carvalho Chehab 
8460c0d06caSMauro Carvalho Chehab /*
8470c0d06caSMauro Carvalho Chehab  * do_i2c_scan()
8480c0d06caSMauro Carvalho Chehab  * check i2c address range for devices
8490c0d06caSMauro Carvalho Chehab  */
850aab3125cSMauro Carvalho Chehab void em28xx_do_i2c_scan(struct em28xx *dev, unsigned bus)
8510c0d06caSMauro Carvalho Chehab {
8520c0d06caSMauro Carvalho Chehab 	u8 i2c_devicelist[128];
8530c0d06caSMauro Carvalho Chehab 	unsigned char buf;
8540c0d06caSMauro Carvalho Chehab 	int i, rc;
8550c0d06caSMauro Carvalho Chehab 
8560c0d06caSMauro Carvalho Chehab 	memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
8570c0d06caSMauro Carvalho Chehab 
8580c0d06caSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
859aab3125cSMauro Carvalho Chehab 		dev->i2c_client[bus].addr = i;
860aab3125cSMauro Carvalho Chehab 		rc = i2c_master_recv(&dev->i2c_client[bus], &buf, 0);
8610c0d06caSMauro Carvalho Chehab 		if (rc < 0)
8620c0d06caSMauro Carvalho Chehab 			continue;
8630c0d06caSMauro Carvalho Chehab 		i2c_devicelist[i] = i;
864aab3125cSMauro Carvalho Chehab 		em28xx_info("found i2c device @ 0x%x on bus %d [%s]\n",
865aab3125cSMauro Carvalho Chehab 			    i << 1, bus, i2c_devs[i] ? i2c_devs[i] : "???");
8660c0d06caSMauro Carvalho Chehab 	}
8670c0d06caSMauro Carvalho Chehab 
868aab3125cSMauro Carvalho Chehab 	if (bus == dev->def_i2c_bus)
8690c0d06caSMauro Carvalho Chehab 		dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
8700c0d06caSMauro Carvalho Chehab 						ARRAY_SIZE(i2c_devicelist), 32);
8710c0d06caSMauro Carvalho Chehab }
8720c0d06caSMauro Carvalho Chehab 
8730c0d06caSMauro Carvalho Chehab /*
8740c0d06caSMauro Carvalho Chehab  * em28xx_i2c_register()
8750c0d06caSMauro Carvalho Chehab  * register i2c bus
8760c0d06caSMauro Carvalho Chehab  */
877a3ea4bf9SFrank Schaefer int em28xx_i2c_register(struct em28xx *dev, unsigned bus,
878a3ea4bf9SFrank Schaefer 			enum em28xx_i2c_algo_type algo_type)
8790c0d06caSMauro Carvalho Chehab {
8800c0d06caSMauro Carvalho Chehab 	int retval;
8810c0d06caSMauro Carvalho Chehab 
8820c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
8830c0d06caSMauro Carvalho Chehab 	BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
8840c0d06caSMauro Carvalho Chehab 
885aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
886aab3125cSMauro Carvalho Chehab 		return -ENODEV;
887aab3125cSMauro Carvalho Chehab 
888aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus] = em28xx_adap_template;
889aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].dev.parent = &dev->udev->dev;
890aab3125cSMauro Carvalho Chehab 	strcpy(dev->i2c_adap[bus].name, dev->name);
891aab3125cSMauro Carvalho Chehab 
892aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].bus = bus;
893a3ea4bf9SFrank Schaefer 	dev->i2c_bus[bus].algo_type = algo_type;
894aab3125cSMauro Carvalho Chehab 	dev->i2c_bus[bus].dev = dev;
895aab3125cSMauro Carvalho Chehab 	dev->i2c_adap[bus].algo_data = &dev->i2c_bus[bus];
896aab3125cSMauro Carvalho Chehab 	i2c_set_adapdata(&dev->i2c_adap[bus], &dev->v4l2_dev);
897aab3125cSMauro Carvalho Chehab 
898aab3125cSMauro Carvalho Chehab 	retval = i2c_add_adapter(&dev->i2c_adap[bus]);
8990c0d06caSMauro Carvalho Chehab 	if (retval < 0) {
9000c0d06caSMauro Carvalho Chehab 		em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
9010c0d06caSMauro Carvalho Chehab 			__func__, retval);
9020c0d06caSMauro Carvalho Chehab 		return retval;
9030c0d06caSMauro Carvalho Chehab 	}
9040c0d06caSMauro Carvalho Chehab 
905aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus] = em28xx_client_template;
906aab3125cSMauro Carvalho Chehab 	dev->i2c_client[bus].adapter = &dev->i2c_adap[bus];
9070c0d06caSMauro Carvalho Chehab 
908aab3125cSMauro Carvalho Chehab 	/* Up to now, all eeproms are at bus 0 */
909aab3125cSMauro Carvalho Chehab 	if (!bus) {
910aab3125cSMauro Carvalho Chehab 		retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
9110c0d06caSMauro Carvalho Chehab 		if ((retval < 0) && (retval != -ENODEV)) {
9120c0d06caSMauro Carvalho Chehab 			em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
9130c0d06caSMauro Carvalho Chehab 				__func__, retval);
9140c0d06caSMauro Carvalho Chehab 
9150c0d06caSMauro Carvalho Chehab 			return retval;
9160c0d06caSMauro Carvalho Chehab 		}
917aab3125cSMauro Carvalho Chehab 	}
9180c0d06caSMauro Carvalho Chehab 
9190c0d06caSMauro Carvalho Chehab 	if (i2c_scan)
920aab3125cSMauro Carvalho Chehab 		em28xx_do_i2c_scan(dev, bus);
9210c0d06caSMauro Carvalho Chehab 
9220c0d06caSMauro Carvalho Chehab 	return 0;
9230c0d06caSMauro Carvalho Chehab }
9240c0d06caSMauro Carvalho Chehab 
9250c0d06caSMauro Carvalho Chehab /*
9260c0d06caSMauro Carvalho Chehab  * em28xx_i2c_unregister()
9270c0d06caSMauro Carvalho Chehab  * unregister i2c_bus
9280c0d06caSMauro Carvalho Chehab  */
929aab3125cSMauro Carvalho Chehab int em28xx_i2c_unregister(struct em28xx *dev, unsigned bus)
9300c0d06caSMauro Carvalho Chehab {
931aab3125cSMauro Carvalho Chehab 	if (bus >= NUM_I2C_BUSES)
932aab3125cSMauro Carvalho Chehab 		return -ENODEV;
933aab3125cSMauro Carvalho Chehab 
934aab3125cSMauro Carvalho Chehab 	i2c_del_adapter(&dev->i2c_adap[bus]);
9350c0d06caSMauro Carvalho Chehab 	return 0;
9360c0d06caSMauro Carvalho Chehab }
937