1a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
2f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab   em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
3a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
4f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
5f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab		      Markus Rechberger <mrechberger@gmail.com>
62e7c6dc3989136844eb63e05f9e4dc6608a763c6Mauro Carvalho Chehab		      Mauro Carvalho Chehab <mchehab@infradead.org>
7f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab		      Sascha Sommer <saschasommer@freenet.de>
8a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
9a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   This program is free software; you can redistribute it and/or modify
10a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   it under the terms of the GNU General Public License as published by
11a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   the Free Software Foundation; either version 2 of the License, or
12a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   (at your option) any later version.
13a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
14a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   This program is distributed in the hope that it will be useful,
15a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   but WITHOUT ANY WARRANTY; without even the implied warranty of
16a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   GNU General Public License for more details.
18a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
19a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   You should have received a copy of the GNU General Public License
20a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   along with this program; if not, write to the Free Software
21a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
23a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
24a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton#include <linux/module.h>
25a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton#include <linux/kernel.h>
26a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton#include <linux/usb.h>
27a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton#include <linux/i2c.h>
28a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
29f7abcd385cc8a5a2f75b07c8325067ea2785ba1eMauro Carvalho Chehab#include "em28xx.h"
306c362c8e58da972728a3666a0a00b9c2f1574e1fMauro Carvalho Chehab#include "tuner-xc2028.h"
315e453dc757385ec892a818e4e3b5de027987ced9Michael Krufky#include <media/v4l2-common.h>
32d5e5265315770bda46c50ecaa64e2b9790f2064cMauro Carvalho Chehab#include <media/tuner.h>
33a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
34a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* ----------------------------------------------------------- */
35a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
36ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic unsigned int i2c_scan;
37a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Mortonmodule_param(i2c_scan, int, 0444);
38a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew MortonMODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
39a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
40ff699e6bd02eb1c6d02c7c2b576c2ee6caab201cDouglas Schilling Landgrafstatic unsigned int i2c_debug;
41a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Mortonmodule_param(i2c_debug, int, 0644);
42a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew MortonMODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
43a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
446ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf
456ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf#define dprintk1(lvl, fmt, args...)			\
466ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafdo {							\
476ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	if (i2c_debug >= lvl) {				\
486ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	printk(fmt, ##args);				\
496ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf      }							\
506ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf} while (0)
516ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf
526ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf#define dprintk2(lvl, fmt, args...)			\
536ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgrafdo {							\
546ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	if (i2c_debug >= lvl) {				\
556ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf		printk(KERN_DEBUG "%s at %s: " fmt,	\
566ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf		       dev->name, __func__ , ##args);	\
576ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf      } 						\
586ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf} while (0)
59a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
60a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
61596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * em2800_i2c_send_max4()
62596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * send up to 4 bytes to the i2c device
63596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab */
643acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
65596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab				char *buf, int len)
66596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab{
67596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int ret;
68596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int write_timeout;
69596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	unsigned char b2[6];
70596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	BUG_ON(len < 1 || len > 4);
71596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	b2[5] = 0x80 + len - 1;
72596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	b2[4] = addr;
73596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	b2[3] = buf[0];
74596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	if (len > 1)
75596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		b2[2] = buf[1];
76596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	if (len > 2)
77596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		b2[1] = buf[2];
78596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	if (len > 3)
79596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		b2[0] = buf[3];
80596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab
813acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
82596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	if (ret != 2 + len) {
83beb7dd86a101263bf63a78c7c6d4da3849b35bd6Robert P. J. Day		em28xx_warn("writing to i2c device failed (error=%i)\n", ret);
84596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		return -EIO;
85596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	}
86596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
87596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	     write_timeout -= 5) {
883acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab		ret = dev->em28xx_read_reg(dev, 0x05);
89596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		if (ret == 0x80 + len - 1)
90596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			return len;
91e8e41da46dca6b33e990b48ee379503d25b4da65Markus Rechberger		msleep(5);
92596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	}
933acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	em28xx_warn("i2c write timed out\n");
94596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	return -EIO;
95596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab}
96596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab
97596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab/*
98596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * em2800_i2c_send_bytes()
99596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab */
100596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehabstatic int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf,
101596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab				 short len)
102596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab{
103596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	char *bufPtr = buf;
104596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int ret;
105596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int wrcount = 0;
106596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int count;
107596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int maxLen = 4;
1083acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	struct em28xx *dev = (struct em28xx *)data;
109596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	while (len > 0) {
110596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		count = (len > maxLen) ? maxLen : len;
111596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		ret = em2800_i2c_send_max4(dev, addr, bufPtr, count);
112596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		if (ret > 0) {
113596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			len -= count;
114596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			bufPtr += count;
115596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			wrcount += count;
116596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		} else
117596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			return (ret < 0) ? ret : -EFAULT;
118596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	}
119596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	return wrcount;
120596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab}
121596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab
122596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab/*
123596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * em2800_i2c_check_for_device()
124596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * check if there is a i2c_device at the supplied address
125596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab */
1263acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
127596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab{
128596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	char msg;
129596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int ret;
130596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int write_timeout;
131596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	msg = addr;
1323acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1);
133596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	if (ret < 0) {
1343acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab		em28xx_warn("setting i2c device address failed (error=%i)\n",
135596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			    ret);
136596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		return ret;
137596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	}
138596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	msg = 0x84;
1393acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1);
140596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	if (ret < 0) {
1413acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab		em28xx_warn("preparing i2c read failed (error=%i)\n", ret);
142596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		return ret;
143596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	}
144596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
145596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	     write_timeout -= 5) {
146d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil		unsigned reg = dev->em28xx_read_reg(dev, 0x5);
147d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil
148d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil		if (reg == 0x94)
149596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			return -ENODEV;
150d45b9b8ab43c8973a9630ac54f4ede6c3e009f9eHans Verkuil		else if (reg == 0x84)
151596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			return 0;
152e8e41da46dca6b33e990b48ee379503d25b4da65Markus Rechberger		msleep(5);
153596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	}
154596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	return -ENODEV;
155596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab}
156596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab
157596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab/*
158596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * em2800_i2c_recv_bytes()
159596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab * read from the i2c device
160596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab */
1613acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
162596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab				 char *buf, int len)
163596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab{
164596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	int ret;
165596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	/* check for the device and set i2c read address */
166596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	ret = em2800_i2c_check_for_device(dev, addr);
167596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	if (ret) {
1683acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab		em28xx_warn
169596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		    ("preparing read at i2c address 0x%x failed (error=%i)\n",
170596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		     addr, ret);
171596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		return ret;
172596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	}
1733acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len);
174596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	if (ret < 0) {
1753acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab		em28xx_warn("reading from i2c device at 0x%x failed (error=%i)",
176596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			    addr, ret);
177596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		return ret;
178596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	}
179596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	return ret;
180596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab}
181596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab
182596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab/*
1833acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_send_bytes()
184a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
1853acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf,
186596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab				 short len, int stop)
187a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
188a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	int wrcount = 0;
1893acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	struct em28xx *dev = (struct em28xx *)data;
190bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab	int write_timeout, ret;
191a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
1923acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
193a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
194bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab	/* Seems to be required after a write */
195bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab	for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
196bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab	     write_timeout -= 5) {
197bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab		ret = dev->em28xx_read_reg(dev, 0x05);
198bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab		if (!ret)
199bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab			break;
200bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab		msleep(5);
201bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab	}
202bbc70e647b04dc3df1c879089a4f6b633c1952c9Mauro Carvalho Chehab
203a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return wrcount;
204a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
205a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
206a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
2073acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_recv_bytes()
208a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * read a byte from the i2c device
209a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
2103acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
211596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab				 char *buf, int len)
212a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
213a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	int ret;
2143acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
215a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	if (ret < 0) {
2163acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab		em28xx_warn("reading i2c device failed (error=%i)\n", ret);
217a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		return ret;
218a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
2193acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	if (dev->em28xx_read_reg(dev, 0x5) != 0)
220a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		return -ENODEV;
221a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return ret;
222a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
223a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
224a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
2253acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_check_for_device()
226a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * check if there is a i2c_device at the supplied address
227a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
2283acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
229a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
230a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	int ret;
231a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
2323acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	ret = dev->em28xx_read_reg_req(dev, 2, addr);
233a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	if (ret < 0) {
2343acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab		em28xx_warn("reading from i2c device failed (error=%i)\n", ret);
235a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		return ret;
236a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
2373acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	if (dev->em28xx_read_reg(dev, 0x5) != 0)
238a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		return -ENODEV;
239a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return 0;
240a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
241a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
242a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
2433acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_xfer()
244a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * the main i2c transfer function
245a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
2463acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
247a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			   struct i2c_msg msgs[], int num)
248a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
2493acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	struct em28xx *dev = i2c_adap->algo_data;
250a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	int addr, rc, i, byte;
251a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
252a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	if (num <= 0)
253a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		return 0;
254a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	for (i = 0; i < num; i++) {
255a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		addr = msgs[i].addr << 1;
2566ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf		dprintk2(2, "%s %s addr=%x len=%d:",
257a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			 (msgs[i].flags & I2C_M_RD) ? "read" : "write",
258a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			 i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
2596ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf		if (!msgs[i].len) { /* no len: check only for device presence */
260505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab			if (dev->board.is_em2800)
261596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab				rc = em2800_i2c_check_for_device(dev, addr);
262596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			else
2633acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab				rc = em28xx_i2c_check_for_device(dev, addr);
264a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			if (rc < 0) {
2656ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf				dprintk2(2, " no device\n");
266a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton				return rc;
267a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			}
268a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
269596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab		} else if (msgs[i].flags & I2C_M_RD) {
270a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			/* read bytes */
271505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab			if (dev->board.is_em2800)
272596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab				rc = em2800_i2c_recv_bytes(dev, addr,
273596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   msgs[i].buf,
274596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   msgs[i].len);
275596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			else
2763acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab				rc = em28xx_i2c_recv_bytes(dev, addr,
277596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   msgs[i].buf,
278596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   msgs[i].len);
2796ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf			if (i2c_debug >= 2) {
2806ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf				for (byte = 0; byte < msgs[i].len; byte++)
281a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton					printk(" %02x", msgs[i].buf[byte]);
282a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			}
283a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		} else {
284a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			/* write bytes */
2856ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf			if (i2c_debug >= 2) {
286a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton				for (byte = 0; byte < msgs[i].len; byte++)
287a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton					printk(" %02x", msgs[i].buf[byte]);
288a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			}
289505b6d0b774fa4475fedbd3cebf95199c17a0086Mauro Carvalho Chehab			if (dev->board.is_em2800)
290596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab				rc = em2800_i2c_send_bytes(dev, addr,
291596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   msgs[i].buf,
292596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   msgs[i].len);
293596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab			else
2943acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab				rc = em28xx_i2c_send_bytes(dev, addr,
295596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   msgs[i].buf,
296596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   msgs[i].len,
297596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab							   i == num - 1);
298a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		}
299e8e41da46dca6b33e990b48ee379503d25b4da65Markus Rechberger		if (rc < 0)
300e8e41da46dca6b33e990b48ee379503d25b4da65Markus Rechberger			goto err;
3016ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf		if (i2c_debug >= 2)
302a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			printk("\n");
303a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
304a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
305a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return num;
3066ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraferr:
3076ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	dprintk2(2, " ERROR: %i\n", rc);
308a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return rc;
309a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
310a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
31103910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab/* based on linux/sunrpc/svcauth.h and linux/hash.h
31203910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab * The original hash function returns a different value, if arch is x86_64
31303910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab *  or i386.
31403910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab */
31503910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehabstatic inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
31603910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab{
31703910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab	unsigned long hash = 0;
31803910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab	unsigned long l = 0;
31903910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab	int len = 0;
32003910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab	unsigned char c;
32103910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab	do {
32203910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab		if (len == length) {
32303910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab			c = (char)len;
32403910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab			len = -1;
32503910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab		} else
32603910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab			c = *buf++;
32703910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab		l = (l << 8) | c;
32803910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab		len++;
32903910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab		if ((len & (32 / 8 - 1)) == 0)
33003910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab			hash = ((hash^l) * 0x9e370001UL);
33103910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab	} while (len);
33203910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab
33303910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab	return (hash >> (32 - bits)) & 0xffffffffUL;
33403910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab}
33503910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab
3363acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
337a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
338a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	unsigned char buf, *p = eedata;
3393acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	struct em28xx_eeprom *em_eeprom = (void *)eedata;
340a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	int i, err, size = len, block;
341a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
342fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	if (dev->chip_id == CHIP_ID_EM2874 ||
343fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	    dev->chip_id == CHIP_ID_EM28174 ||
344fec528b77f9be3e7ebb8d7c25888b0cf9fb8e8d6Mauro Carvalho Chehab	    dev->chip_id == CHIP_ID_EM2884) {
345a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller		/* Empia switched to a 16-bit addressable eeprom in newer
346a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller		   devices.  While we could certainly write a routine to read
347a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller		   the eeprom, there is nothing of use in there that cannot be
348a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller		   accessed through registers, and there is the risk that we
349a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller		   could corrupt the eeprom (since a 16-bit read call is
350a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller		   interpreted as a write call by 8-bit eeproms).
351a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller		*/
352a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller		return 0;
353a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller	}
354a527c9f827517a14b869511a954910d973556c8cDevin Heitmueller
355a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	dev->i2c_client.addr = 0xa0 >> 1;
356596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab
357596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	/* Check if board has eeprom */
358596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab	err = i2c_master_recv(&dev->i2c_client, &buf, 0);
359f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf	if (err < 0) {
360c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab		em28xx_errdev("board has no eeprom\n");
361c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab		memset(eedata, 0, len);
362c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab		return -ENODEV;
363f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf	}
364596d92d5128d308b5a79f21c3e72c87f5fc7e58bMauro Carvalho Chehab
365a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	buf = 0;
3666ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf
3676ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	err = i2c_master_send(&dev->i2c_client, &buf, 1);
3686ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf	if (err != 1) {
369a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
370a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		       dev->name, err);
371f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf		return err;
372a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
373a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	while (size > 0) {
374a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		if (size > 16)
375a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			block = 16;
376a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		else
377a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			block = size;
378a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
379a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		if (block !=
380a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		    (err = i2c_master_recv(&dev->i2c_client, p, block))) {
381a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			printk(KERN_WARNING
382a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			       "%s: i2c eeprom read error (err=%d)\n",
383a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			       dev->name, err);
384f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf			return err;
385a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		}
386a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		size -= block;
387a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		p += block;
388a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
389a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	for (i = 0; i < len; i++) {
390a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		if (0 == (i % 16))
391a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
392a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		printk(" %02x", eedata[i]);
393a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		if (15 == (i % 16))
394a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			printk("\n");
395a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
396a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
39703910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab	if (em_eeprom->id == 0x9567eb1a)
39803910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab		dev->hash = em28xx_hash_mem(eedata, len, 32);
39903910cc39035d27f4c85c8ad2a236cc5c9456127Mauro Carvalho Chehab
4001bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab	printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n",
4011bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab	       dev->name, em_eeprom->id, dev->hash);
4021bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab
4031bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab	printk(KERN_INFO "%s: EEPROM info:\n", dev->name);
404a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
405a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	switch (em_eeprom->chip_conf >> 4 & 0x3) {
406a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	case 0:
4071bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab		printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name);
408a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		break;
409a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	case 1:
4101bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab		printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n",
4111bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab				 dev->name);
412a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		break;
413a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	case 2:
414a1a6ee74f2c68918f2e145dccba3637eea91a52aNicola Soranzo		printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n",
415a1a6ee74f2c68918f2e145dccba3637eea91a52aNicola Soranzo				 dev->name);
416a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		break;
417a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	case 3:
418a1a6ee74f2c68918f2e145dccba3637eea91a52aNicola Soranzo		printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n",
419a1a6ee74f2c68918f2e145dccba3637eea91a52aNicola Soranzo				 dev->name);
420a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		break;
421a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
422a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
423a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	if (em_eeprom->chip_conf & 1 << 3)
4241bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab		printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name);
425a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
426a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	if (em_eeprom->chip_conf & 1 << 2)
4271bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab		printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name);
428a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
429a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	switch (em_eeprom->chip_conf & 0x3) {
430a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	case 0:
4311bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab		printk(KERN_INFO "%s:\t500mA max power\n", dev->name);
432a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		break;
433a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	case 1:
4341bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab		printk(KERN_INFO "%s:\t400mA max power\n", dev->name);
435a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		break;
436a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	case 2:
4371bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab		printk(KERN_INFO "%s:\t300mA max power\n", dev->name);
438a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		break;
439a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	case 3:
4401bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab		printk(KERN_INFO "%s:\t200mA max power\n", dev->name);
441a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		break;
442a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
4431bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab	printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
4441bee0184f6ffba1263a4b1e5732cde2c5292d843Mauro Carvalho Chehab				dev->name,
4456ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf				em_eeprom->string_idx_table,
4466ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf				em_eeprom->string1,
4476ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf				em_eeprom->string2,
4486ea54d938b6f81baa0952a8b15d3e67e6c268b8fDouglas Schilling Landgraf				em_eeprom->string3);
449a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
450a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return 0;
451a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
452a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
453a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* ----------------------------------------------------------- */
454a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
455a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
456a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * functionality()
457a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
458a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Mortonstatic u32 functionality(struct i2c_adapter *adap)
459a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
460a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return I2C_FUNC_SMBUS_EMUL;
461a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
462a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
4633acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic struct i2c_algorithm em28xx_algo = {
4643acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	.master_xfer   = em28xx_i2c_xfer,
465a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	.functionality = functionality,
466a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton};
467a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
4683acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic struct i2c_adapter em28xx_adap_template = {
469a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	.owner = THIS_MODULE,
4703acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	.name = "em28xx",
4713acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	.algo = &em28xx_algo,
472a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton};
473a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
4743acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabstatic struct i2c_client em28xx_client_template = {
4753acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	.name = "em28xx internal",
476a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton};
477a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
478a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/* ----------------------------------------------------------- */
479a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
480a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
481a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * i2c_devs
482a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * incomplete list of known devices
483a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
484a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Mortonstatic char *i2c_devs[128] = {
485a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0x4a >> 1] = "saa7113h",
486a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0x60 >> 1] = "remote IR sensor",
487da45a2a5b96afd7188c058a55eb2917d6524c0cfMarkus Rechberger	[0x8e >> 1] = "remote IR sensor",
488a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0x86 >> 1] = "tda9887",
489a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0x80 >> 1] = "msp34xx",
490a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0x88 >> 1] = "msp34xx",
491a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0xa0 >> 1] = "eeprom",
4922bd1d9eb1c27034a77c8e1887156da72d6160ae1Vitaly Wool	[0xb0 >> 1] = "tda9874",
493a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0xb8 >> 1] = "tvp5150a",
494791a08fc01aaa293a73c9dce260327fdee288fafMauro Carvalho Chehab	[0xba >> 1] = "webcam sensor or tvp5150a",
495a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0xc0 >> 1] = "tuner (analog)",
496a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0xc2 >> 1] = "tuner (analog)",
497a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0xc4 >> 1] = "tuner (analog)",
498a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	[0xc6 >> 1] = "tuner (analog)",
499a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton};
500a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
501a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
502a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * do_i2c_scan()
503a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * check i2c address range for devices
504a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
505fad7b958e753e18ff443786360f7846da50a3085Sascha Sommervoid em28xx_do_i2c_scan(struct em28xx *dev)
506a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
507fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer	u8 i2c_devicelist[128];
508a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	unsigned char buf;
509a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	int i, rc;
510a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
511fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer	memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
512fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer
51353c4e9551c2930767fcdaa54323616c32ed6e9c6Mauro Carvalho Chehab	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
514fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer		dev->i2c_client.addr = i;
515fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer		rc = i2c_master_recv(&dev->i2c_client, &buf, 0);
516a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton		if (rc < 0)
517a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton			continue;
518fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer		i2c_devicelist[i] = i;
519fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer		printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n",
520fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer		       dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
521a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	}
522fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer
523fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer	dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
524fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer					ARRAY_SIZE(i2c_devicelist), 32);
525a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
526a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
527a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
5283acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_register()
529a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * register i2c bus
530a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
5313acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabint em28xx_i2c_register(struct em28xx *dev)
532a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
533f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf	int retval;
534f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf
5353acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
5363acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
5373acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	dev->i2c_adap = em28xx_adap_template;
538a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	dev->i2c_adap.dev.parent = &dev->udev->dev;
539a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	strcpy(dev->i2c_adap.name, dev->name);
540a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	dev->i2c_adap.algo_data = dev;
541f2cf250af156bef127433efd255abfae6aab02f6Douglas Schilling Landgraf	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
542f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf
543f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf	retval = i2c_add_adapter(&dev->i2c_adap);
544f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf	if (retval < 0) {
545f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf		em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
546f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf			__func__, retval);
547f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf		return retval;
548f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf	}
549a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
5503acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab	dev->i2c_client = em28xx_client_template;
551a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	dev->i2c_client.adapter = &dev->i2c_adap;
552a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
553f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf	retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
554c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab	if ((retval < 0) && (retval != -ENODEV)) {
555f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf		em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
556f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf			__func__, retval);
557c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab
558f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf		return retval;
559f2a01a0027b29f682c3833d582e2827a4690f661Douglas Schilling Landgraf	}
560a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
561a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	if (i2c_scan)
562fad7b958e753e18ff443786360f7846da50a3085Sascha Sommer		em28xx_do_i2c_scan(dev);
563c41109fc9a13c6af0e4069dd92fdb4c5c8046649Mauro Carvalho Chehab
564c668f32dca105d876e51862a003a302fa61e4ae4Jean Delvare	/* Instantiate the IR receiver device, if present */
565c668f32dca105d876e51862a003a302fa61e4ae4Jean Delvare	em28xx_register_i2c_ir(dev);
566c668f32dca105d876e51862a003a302fa61e4ae4Jean Delvare
567a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return 0;
568a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
569a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton
570a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton/*
5713acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehab * em28xx_i2c_unregister()
572a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton * unregister i2c_bus
573a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton */
5743acf28095009509c9ca1e283de821b5be9ddede6Mauro Carvalho Chehabint em28xx_i2c_unregister(struct em28xx *dev)
575a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton{
576a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	i2c_del_adapter(&dev->i2c_adap);
577a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton	return 0;
578a6c2ba283565dbc9f055dcb2ecba1971460bb535Andrew Morton}
579