xref: /linux/drivers/media/pci/saa7134/saa7134-i2c.c (revision 30693f346e4f5c0720de66c424b38053f9e34a08)
1b285192aSMauro Carvalho Chehab /*
2b285192aSMauro Carvalho Chehab  *
3b285192aSMauro Carvalho Chehab  * device driver for philips saa7134 based TV cards
4b285192aSMauro Carvalho Chehab  * i2c interface support
5b285192aSMauro Carvalho Chehab  *
6b285192aSMauro Carvalho Chehab  * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7b285192aSMauro Carvalho Chehab  *
8b285192aSMauro Carvalho Chehab  *  This program is free software; you can redistribute it and/or modify
9b285192aSMauro Carvalho Chehab  *  it under the terms of the GNU General Public License as published by
10b285192aSMauro Carvalho Chehab  *  the Free Software Foundation; either version 2 of the License, or
11b285192aSMauro Carvalho Chehab  *  (at your option) any later version.
12b285192aSMauro Carvalho Chehab  *
13b285192aSMauro Carvalho Chehab  *  This program is distributed in the hope that it will be useful,
14b285192aSMauro Carvalho Chehab  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15b285192aSMauro Carvalho Chehab  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16b285192aSMauro Carvalho Chehab  *  GNU General Public License for more details.
17b285192aSMauro Carvalho Chehab  *
18b285192aSMauro Carvalho Chehab  *  You should have received a copy of the GNU General Public License
19b285192aSMauro Carvalho Chehab  *  along with this program; if not, write to the Free Software
20b285192aSMauro Carvalho Chehab  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21b285192aSMauro Carvalho Chehab  */
22b285192aSMauro Carvalho Chehab 
239a12ccfcSMauro Carvalho Chehab #include "saa7134.h"
249a12ccfcSMauro Carvalho Chehab #include "saa7134-reg.h"
259a12ccfcSMauro Carvalho Chehab 
26b285192aSMauro Carvalho Chehab #include <linux/init.h>
27b285192aSMauro Carvalho Chehab #include <linux/list.h>
28b285192aSMauro Carvalho Chehab #include <linux/module.h>
29b285192aSMauro Carvalho Chehab #include <linux/kernel.h>
30b285192aSMauro Carvalho Chehab #include <linux/delay.h>
31b285192aSMauro Carvalho Chehab 
32b285192aSMauro Carvalho Chehab #include <media/v4l2-common.h>
33b285192aSMauro Carvalho Chehab 
34b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */
35b285192aSMauro Carvalho Chehab 
36b285192aSMauro Carvalho Chehab static unsigned int i2c_debug;
37b285192aSMauro Carvalho Chehab module_param(i2c_debug, int, 0644);
38b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_debug,"enable debug messages [i2c]");
39b285192aSMauro Carvalho Chehab 
40b285192aSMauro Carvalho Chehab static unsigned int i2c_scan;
41b285192aSMauro Carvalho Chehab module_param(i2c_scan, int, 0444);
42b285192aSMauro Carvalho Chehab MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
43b285192aSMauro Carvalho Chehab 
44*30693f34SMauro Carvalho Chehab #define i2c_dbg(level, fmt, arg...)    if (i2c_debug == level) \
45*30693f34SMauro Carvalho Chehab 	printk(KERN_DEBUG pr_fmt("i2c: " fmt), ## arg)
46*30693f34SMauro Carvalho Chehab 
47*30693f34SMauro Carvalho Chehab #define i2c_cont(level, fmt, arg...)    if (i2c_debug == level) \
48*30693f34SMauro Carvalho Chehab 	pr_cont(fmt, ## arg)
49b285192aSMauro Carvalho Chehab 
50b285192aSMauro Carvalho Chehab #define I2C_WAIT_DELAY  32
51b285192aSMauro Carvalho Chehab #define I2C_WAIT_RETRY  16
52b285192aSMauro Carvalho Chehab 
53b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */
54b285192aSMauro Carvalho Chehab 
55b285192aSMauro Carvalho Chehab static char *str_i2c_status[] = {
56b285192aSMauro Carvalho Chehab 	"IDLE", "DONE_STOP", "BUSY", "TO_SCL", "TO_ARB", "DONE_WRITE",
57b285192aSMauro Carvalho Chehab 	"DONE_READ", "DONE_WRITE_TO", "DONE_READ_TO", "NO_DEVICE",
58b285192aSMauro Carvalho Chehab 	"NO_ACKN", "BUS_ERR", "ARB_LOST", "SEQ_ERR", "ST_ERR", "SW_ERR"
59b285192aSMauro Carvalho Chehab };
60b285192aSMauro Carvalho Chehab 
61b285192aSMauro Carvalho Chehab enum i2c_status {
62b285192aSMauro Carvalho Chehab 	IDLE          = 0,  // no I2C command pending
63b285192aSMauro Carvalho Chehab 	DONE_STOP     = 1,  // I2C command done and STOP executed
64b285192aSMauro Carvalho Chehab 	BUSY          = 2,  // executing I2C command
65b285192aSMauro Carvalho Chehab 	TO_SCL        = 3,  // executing I2C command, time out on clock stretching
66b285192aSMauro Carvalho Chehab 	TO_ARB        = 4,  // time out on arbitration trial, still trying
67b285192aSMauro Carvalho Chehab 	DONE_WRITE    = 5,  // I2C command done and awaiting next write command
68b285192aSMauro Carvalho Chehab 	DONE_READ     = 6,  // I2C command done and awaiting next read command
69b285192aSMauro Carvalho Chehab 	DONE_WRITE_TO = 7,  // see 5, and time out on status echo
70b285192aSMauro Carvalho Chehab 	DONE_READ_TO  = 8,  // see 6, and time out on status echo
71b285192aSMauro Carvalho Chehab 	NO_DEVICE     = 9,  // no acknowledge on device slave address
72b285192aSMauro Carvalho Chehab 	NO_ACKN       = 10, // no acknowledge after data byte transfer
73b285192aSMauro Carvalho Chehab 	BUS_ERR       = 11, // bus error
74b285192aSMauro Carvalho Chehab 	ARB_LOST      = 12, // arbitration lost during transfer
75b285192aSMauro Carvalho Chehab 	SEQ_ERR       = 13, // erroneous programming sequence
76b285192aSMauro Carvalho Chehab 	ST_ERR        = 14, // wrong status echoing
77b285192aSMauro Carvalho Chehab 	SW_ERR        = 15  // software error
78b285192aSMauro Carvalho Chehab };
79b285192aSMauro Carvalho Chehab 
80b285192aSMauro Carvalho Chehab static char *str_i2c_attr[] = {
81b285192aSMauro Carvalho Chehab 	"NOP", "STOP", "CONTINUE", "START"
82b285192aSMauro Carvalho Chehab };
83b285192aSMauro Carvalho Chehab 
84b285192aSMauro Carvalho Chehab enum i2c_attr {
85b285192aSMauro Carvalho Chehab 	NOP           = 0,  // no operation on I2C bus
86b285192aSMauro Carvalho Chehab 	STOP          = 1,  // stop condition, no associated byte transfer
87b285192aSMauro Carvalho Chehab 	CONTINUE      = 2,  // continue with byte transfer
88b285192aSMauro Carvalho Chehab 	START         = 3   // start condition with byte transfer
89b285192aSMauro Carvalho Chehab };
90b285192aSMauro Carvalho Chehab 
91b285192aSMauro Carvalho Chehab static inline enum i2c_status i2c_get_status(struct saa7134_dev *dev)
92b285192aSMauro Carvalho Chehab {
93b285192aSMauro Carvalho Chehab 	enum i2c_status status;
94b285192aSMauro Carvalho Chehab 
95b285192aSMauro Carvalho Chehab 	status = saa_readb(SAA7134_I2C_ATTR_STATUS) & 0x0f;
96*30693f34SMauro Carvalho Chehab 	i2c_dbg(2, "i2c stat <= %s\n", str_i2c_status[status]);
97b285192aSMauro Carvalho Chehab 	return status;
98b285192aSMauro Carvalho Chehab }
99b285192aSMauro Carvalho Chehab 
100b285192aSMauro Carvalho Chehab static inline void i2c_set_status(struct saa7134_dev *dev,
101b285192aSMauro Carvalho Chehab 				  enum i2c_status status)
102b285192aSMauro Carvalho Chehab {
103*30693f34SMauro Carvalho Chehab 	i2c_dbg(2, "i2c stat => %s\n", str_i2c_status[status]);
104b285192aSMauro Carvalho Chehab 	saa_andorb(SAA7134_I2C_ATTR_STATUS,0x0f,status);
105b285192aSMauro Carvalho Chehab }
106b285192aSMauro Carvalho Chehab 
107b285192aSMauro Carvalho Chehab static inline void i2c_set_attr(struct saa7134_dev *dev, enum i2c_attr attr)
108b285192aSMauro Carvalho Chehab {
109*30693f34SMauro Carvalho Chehab 	i2c_dbg(2, "i2c attr => %s\n", str_i2c_attr[attr]);
110b285192aSMauro Carvalho Chehab 	saa_andorb(SAA7134_I2C_ATTR_STATUS,0xc0,attr << 6);
111b285192aSMauro Carvalho Chehab }
112b285192aSMauro Carvalho Chehab 
113b285192aSMauro Carvalho Chehab static inline int i2c_is_error(enum i2c_status status)
114b285192aSMauro Carvalho Chehab {
115b285192aSMauro Carvalho Chehab 	switch (status) {
116b285192aSMauro Carvalho Chehab 	case NO_DEVICE:
117b285192aSMauro Carvalho Chehab 	case NO_ACKN:
118b285192aSMauro Carvalho Chehab 	case BUS_ERR:
119b285192aSMauro Carvalho Chehab 	case ARB_LOST:
120b285192aSMauro Carvalho Chehab 	case SEQ_ERR:
121b285192aSMauro Carvalho Chehab 	case ST_ERR:
122b285192aSMauro Carvalho Chehab 		return true;
123b285192aSMauro Carvalho Chehab 	default:
124b285192aSMauro Carvalho Chehab 		return false;
125b285192aSMauro Carvalho Chehab 	}
126b285192aSMauro Carvalho Chehab }
127b285192aSMauro Carvalho Chehab 
128b285192aSMauro Carvalho Chehab static inline int i2c_is_idle(enum i2c_status status)
129b285192aSMauro Carvalho Chehab {
130b285192aSMauro Carvalho Chehab 	switch (status) {
131b285192aSMauro Carvalho Chehab 	case IDLE:
132b285192aSMauro Carvalho Chehab 	case DONE_STOP:
133b285192aSMauro Carvalho Chehab 		return true;
134b285192aSMauro Carvalho Chehab 	default:
135b285192aSMauro Carvalho Chehab 		return false;
136b285192aSMauro Carvalho Chehab 	}
137b285192aSMauro Carvalho Chehab }
138b285192aSMauro Carvalho Chehab 
139b285192aSMauro Carvalho Chehab static inline int i2c_is_busy(enum i2c_status status)
140b285192aSMauro Carvalho Chehab {
141b285192aSMauro Carvalho Chehab 	switch (status) {
142b285192aSMauro Carvalho Chehab 	case BUSY:
143b285192aSMauro Carvalho Chehab 	case TO_SCL:
144b285192aSMauro Carvalho Chehab 	case TO_ARB:
145b285192aSMauro Carvalho Chehab 		return true;
146b285192aSMauro Carvalho Chehab 	default:
147b285192aSMauro Carvalho Chehab 		return false;
148b285192aSMauro Carvalho Chehab 	}
149b285192aSMauro Carvalho Chehab }
150b285192aSMauro Carvalho Chehab 
151b285192aSMauro Carvalho Chehab static int i2c_is_busy_wait(struct saa7134_dev *dev)
152b285192aSMauro Carvalho Chehab {
153b285192aSMauro Carvalho Chehab 	enum i2c_status status;
154b285192aSMauro Carvalho Chehab 	int count;
155b285192aSMauro Carvalho Chehab 
156b285192aSMauro Carvalho Chehab 	for (count = 0; count < I2C_WAIT_RETRY; count++) {
157b285192aSMauro Carvalho Chehab 		status = i2c_get_status(dev);
158b285192aSMauro Carvalho Chehab 		if (!i2c_is_busy(status))
159b285192aSMauro Carvalho Chehab 			break;
160b285192aSMauro Carvalho Chehab 		saa_wait(I2C_WAIT_DELAY);
161b285192aSMauro Carvalho Chehab 	}
162b285192aSMauro Carvalho Chehab 	if (I2C_WAIT_RETRY == count)
163b285192aSMauro Carvalho Chehab 		return false;
164b285192aSMauro Carvalho Chehab 	return true;
165b285192aSMauro Carvalho Chehab }
166b285192aSMauro Carvalho Chehab 
167b285192aSMauro Carvalho Chehab static int i2c_reset(struct saa7134_dev *dev)
168b285192aSMauro Carvalho Chehab {
169b285192aSMauro Carvalho Chehab 	enum i2c_status status;
170b285192aSMauro Carvalho Chehab 	int count;
171b285192aSMauro Carvalho Chehab 
172*30693f34SMauro Carvalho Chehab 	i2c_dbg(2, "i2c reset\n");
173b285192aSMauro Carvalho Chehab 	status = i2c_get_status(dev);
174b285192aSMauro Carvalho Chehab 	if (!i2c_is_error(status))
175b285192aSMauro Carvalho Chehab 		return true;
176b285192aSMauro Carvalho Chehab 	i2c_set_status(dev,status);
177b285192aSMauro Carvalho Chehab 
178b285192aSMauro Carvalho Chehab 	for (count = 0; count < I2C_WAIT_RETRY; count++) {
179b285192aSMauro Carvalho Chehab 		status = i2c_get_status(dev);
180b285192aSMauro Carvalho Chehab 		if (!i2c_is_error(status))
181b285192aSMauro Carvalho Chehab 			break;
182b285192aSMauro Carvalho Chehab 		udelay(I2C_WAIT_DELAY);
183b285192aSMauro Carvalho Chehab 	}
184b285192aSMauro Carvalho Chehab 	if (I2C_WAIT_RETRY == count)
185b285192aSMauro Carvalho Chehab 		return false;
186b285192aSMauro Carvalho Chehab 
187b285192aSMauro Carvalho Chehab 	if (!i2c_is_idle(status))
188b285192aSMauro Carvalho Chehab 		return false;
189b285192aSMauro Carvalho Chehab 
190b285192aSMauro Carvalho Chehab 	i2c_set_attr(dev,NOP);
191b285192aSMauro Carvalho Chehab 	return true;
192b285192aSMauro Carvalho Chehab }
193b285192aSMauro Carvalho Chehab 
194b285192aSMauro Carvalho Chehab static inline int i2c_send_byte(struct saa7134_dev *dev,
195b285192aSMauro Carvalho Chehab 				enum i2c_attr attr,
196b285192aSMauro Carvalho Chehab 				unsigned char data)
197b285192aSMauro Carvalho Chehab {
198b285192aSMauro Carvalho Chehab 	enum i2c_status status;
199b285192aSMauro Carvalho Chehab 	__u32 dword;
200b285192aSMauro Carvalho Chehab 
201b285192aSMauro Carvalho Chehab 	/* have to write both attr + data in one 32bit word */
202b285192aSMauro Carvalho Chehab 	dword  = saa_readl(SAA7134_I2C_ATTR_STATUS >> 2);
203b285192aSMauro Carvalho Chehab 	dword &= 0x0f;
204b285192aSMauro Carvalho Chehab 	dword |= (attr << 6);
205b285192aSMauro Carvalho Chehab 	dword |= ((__u32)data << 8);
206b285192aSMauro Carvalho Chehab 	dword |= 0x00 << 16;  /* 100 kHz */
207b285192aSMauro Carvalho Chehab //	dword |= 0x40 << 16;  /* 400 kHz */
208b285192aSMauro Carvalho Chehab 	dword |= 0xf0 << 24;
209b285192aSMauro Carvalho Chehab 	saa_writel(SAA7134_I2C_ATTR_STATUS >> 2, dword);
210*30693f34SMauro Carvalho Chehab 	i2c_dbg(2, "i2c data => 0x%x\n", data);
211b285192aSMauro Carvalho Chehab 
212b285192aSMauro Carvalho Chehab 	if (!i2c_is_busy_wait(dev))
213b285192aSMauro Carvalho Chehab 		return -EIO;
214b285192aSMauro Carvalho Chehab 	status = i2c_get_status(dev);
215b285192aSMauro Carvalho Chehab 	if (i2c_is_error(status))
216b285192aSMauro Carvalho Chehab 		return -EIO;
217b285192aSMauro Carvalho Chehab 	return 0;
218b285192aSMauro Carvalho Chehab }
219b285192aSMauro Carvalho Chehab 
220b285192aSMauro Carvalho Chehab static inline int i2c_recv_byte(struct saa7134_dev *dev)
221b285192aSMauro Carvalho Chehab {
222b285192aSMauro Carvalho Chehab 	enum i2c_status status;
223b285192aSMauro Carvalho Chehab 	unsigned char data;
224b285192aSMauro Carvalho Chehab 
225b285192aSMauro Carvalho Chehab 	i2c_set_attr(dev,CONTINUE);
226b285192aSMauro Carvalho Chehab 	if (!i2c_is_busy_wait(dev))
227b285192aSMauro Carvalho Chehab 		return -EIO;
228b285192aSMauro Carvalho Chehab 	status = i2c_get_status(dev);
229b285192aSMauro Carvalho Chehab 	if (i2c_is_error(status))
230b285192aSMauro Carvalho Chehab 		return -EIO;
231b285192aSMauro Carvalho Chehab 	data = saa_readb(SAA7134_I2C_DATA);
232*30693f34SMauro Carvalho Chehab 	i2c_dbg(2, "i2c data <= 0x%x\n", data);
233b285192aSMauro Carvalho Chehab 	return data;
234b285192aSMauro Carvalho Chehab }
235b285192aSMauro Carvalho Chehab 
236b285192aSMauro Carvalho Chehab static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
237b285192aSMauro Carvalho Chehab 			    struct i2c_msg *msgs, int num)
238b285192aSMauro Carvalho Chehab {
239b285192aSMauro Carvalho Chehab 	struct saa7134_dev *dev = i2c_adap->algo_data;
240b285192aSMauro Carvalho Chehab 	enum i2c_status status;
241b285192aSMauro Carvalho Chehab 	unsigned char data;
242b285192aSMauro Carvalho Chehab 	int addr,rc,i,byte;
243b285192aSMauro Carvalho Chehab 
244b285192aSMauro Carvalho Chehab 	status = i2c_get_status(dev);
245b285192aSMauro Carvalho Chehab 	if (!i2c_is_idle(status))
246b285192aSMauro Carvalho Chehab 		if (!i2c_reset(dev))
247b285192aSMauro Carvalho Chehab 			return -EIO;
248b285192aSMauro Carvalho Chehab 
249*30693f34SMauro Carvalho Chehab 	i2c_dbg(2, "start xfer\n");
250*30693f34SMauro Carvalho Chehab 	i2c_dbg(1, "i2c xfer:");
251b285192aSMauro Carvalho Chehab 	for (i = 0; i < num; i++) {
252b285192aSMauro Carvalho Chehab 		if (!(msgs[i].flags & I2C_M_NOSTART) || 0 == i) {
253b285192aSMauro Carvalho Chehab 			/* send address */
254*30693f34SMauro Carvalho Chehab 			i2c_dbg(2, "send address\n");
255b285192aSMauro Carvalho Chehab 			addr  = msgs[i].addr << 1;
256b285192aSMauro Carvalho Chehab 			if (msgs[i].flags & I2C_M_RD)
257b285192aSMauro Carvalho Chehab 				addr |= 1;
258b285192aSMauro Carvalho Chehab 			if (i > 0 && msgs[i].flags &
259b285192aSMauro Carvalho Chehab 			    I2C_M_RD && msgs[i].addr != 0x40 &&
26034fe2784SOndrej Zary 			    msgs[i].addr != 0x41 &&
261b285192aSMauro Carvalho Chehab 			    msgs[i].addr != 0x19) {
262b285192aSMauro Carvalho Chehab 				/* workaround for a saa7134 i2c bug
263b285192aSMauro Carvalho Chehab 				 * needed to talk to the mt352 demux
264b285192aSMauro Carvalho Chehab 				 * thanks to pinnacle for the hint */
265b285192aSMauro Carvalho Chehab 				int quirk = 0xfe;
266*30693f34SMauro Carvalho Chehab 				i2c_cont(1, " [%02x quirk]",quirk);
267b285192aSMauro Carvalho Chehab 				i2c_send_byte(dev,START,quirk);
268b285192aSMauro Carvalho Chehab 				i2c_recv_byte(dev);
269b285192aSMauro Carvalho Chehab 			}
270*30693f34SMauro Carvalho Chehab 			i2c_cont(1, " < %02x", addr);
271b285192aSMauro Carvalho Chehab 			rc = i2c_send_byte(dev,START,addr);
272b285192aSMauro Carvalho Chehab 			if (rc < 0)
273b285192aSMauro Carvalho Chehab 				 goto err;
274b285192aSMauro Carvalho Chehab 		}
275b285192aSMauro Carvalho Chehab 		if (msgs[i].flags & I2C_M_RD) {
276b285192aSMauro Carvalho Chehab 			/* read bytes */
277*30693f34SMauro Carvalho Chehab 			i2c_dbg(2, "read bytes\n");
278b285192aSMauro Carvalho Chehab 			for (byte = 0; byte < msgs[i].len; byte++) {
279*30693f34SMauro Carvalho Chehab 				i2c_cont(1, " =");
280b285192aSMauro Carvalho Chehab 				rc = i2c_recv_byte(dev);
281b285192aSMauro Carvalho Chehab 				if (rc < 0)
282b285192aSMauro Carvalho Chehab 					goto err;
283*30693f34SMauro Carvalho Chehab 				i2c_cont(1, "%02x", rc);
284b285192aSMauro Carvalho Chehab 				msgs[i].buf[byte] = rc;
285b285192aSMauro Carvalho Chehab 			}
286b285192aSMauro Carvalho Chehab 			/* discard mysterious extra byte when reading
287b285192aSMauro Carvalho Chehab 			   from Samsung S5H1411.  i2c bus gets error
288b285192aSMauro Carvalho Chehab 			   if we do not. */
289b285192aSMauro Carvalho Chehab 			if (0x19 == msgs[i].addr) {
290*30693f34SMauro Carvalho Chehab 				i2c_cont(1, " ?");
291b285192aSMauro Carvalho Chehab 				rc = i2c_recv_byte(dev);
292b285192aSMauro Carvalho Chehab 				if (rc < 0)
293b285192aSMauro Carvalho Chehab 					goto err;
294*30693f34SMauro Carvalho Chehab 				i2c_cont(1, "%02x", rc);
295b285192aSMauro Carvalho Chehab 			}
296b285192aSMauro Carvalho Chehab 		} else {
297b285192aSMauro Carvalho Chehab 			/* write bytes */
298*30693f34SMauro Carvalho Chehab 			i2c_dbg(2, "write bytes\n");
299b285192aSMauro Carvalho Chehab 			for (byte = 0; byte < msgs[i].len; byte++) {
300b285192aSMauro Carvalho Chehab 				data = msgs[i].buf[byte];
301*30693f34SMauro Carvalho Chehab 				i2c_cont(1, " %02x", data);
302b285192aSMauro Carvalho Chehab 				rc = i2c_send_byte(dev,CONTINUE,data);
303b285192aSMauro Carvalho Chehab 				if (rc < 0)
304b285192aSMauro Carvalho Chehab 					goto err;
305b285192aSMauro Carvalho Chehab 			}
306b285192aSMauro Carvalho Chehab 		}
307b285192aSMauro Carvalho Chehab 	}
308*30693f34SMauro Carvalho Chehab 	i2c_dbg(2, "xfer done\n");
309*30693f34SMauro Carvalho Chehab 	i2c_cont(1, " >");
310b285192aSMauro Carvalho Chehab 	i2c_set_attr(dev,STOP);
311b285192aSMauro Carvalho Chehab 	rc = -EIO;
312b285192aSMauro Carvalho Chehab 	if (!i2c_is_busy_wait(dev))
313b285192aSMauro Carvalho Chehab 		goto err;
314b285192aSMauro Carvalho Chehab 	status = i2c_get_status(dev);
315b285192aSMauro Carvalho Chehab 	if (i2c_is_error(status))
316b285192aSMauro Carvalho Chehab 		goto err;
317b285192aSMauro Carvalho Chehab 	/* ensure that the bus is idle for at least one bit slot */
318b285192aSMauro Carvalho Chehab 	msleep(1);
319b285192aSMauro Carvalho Chehab 
320*30693f34SMauro Carvalho Chehab 	i2c_cont(1, "\n");
321b285192aSMauro Carvalho Chehab 	return num;
322b285192aSMauro Carvalho Chehab  err:
323b285192aSMauro Carvalho Chehab 	if (1 == i2c_debug) {
324b285192aSMauro Carvalho Chehab 		status = i2c_get_status(dev);
325*30693f34SMauro Carvalho Chehab 		i2c_cont(1, " ERROR: %s\n", str_i2c_status[status]);
326b285192aSMauro Carvalho Chehab 	}
327b285192aSMauro Carvalho Chehab 	return rc;
328b285192aSMauro Carvalho Chehab }
329b285192aSMauro Carvalho Chehab 
330b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */
331b285192aSMauro Carvalho Chehab 
332b285192aSMauro Carvalho Chehab static u32 functionality(struct i2c_adapter *adap)
333b285192aSMauro Carvalho Chehab {
334b285192aSMauro Carvalho Chehab 	return I2C_FUNC_SMBUS_EMUL;
335b285192aSMauro Carvalho Chehab }
336b285192aSMauro Carvalho Chehab 
337b285192aSMauro Carvalho Chehab static struct i2c_algorithm saa7134_algo = {
338b285192aSMauro Carvalho Chehab 	.master_xfer   = saa7134_i2c_xfer,
339b285192aSMauro Carvalho Chehab 	.functionality = functionality,
340b285192aSMauro Carvalho Chehab };
341b285192aSMauro Carvalho Chehab 
342b285192aSMauro Carvalho Chehab static struct i2c_adapter saa7134_adap_template = {
343b285192aSMauro Carvalho Chehab 	.owner         = THIS_MODULE,
344b285192aSMauro Carvalho Chehab 	.name          = "saa7134",
345b285192aSMauro Carvalho Chehab 	.algo          = &saa7134_algo,
346b285192aSMauro Carvalho Chehab };
347b285192aSMauro Carvalho Chehab 
348b285192aSMauro Carvalho Chehab static struct i2c_client saa7134_client_template = {
349b285192aSMauro Carvalho Chehab 	.name	= "saa7134 internal",
350b285192aSMauro Carvalho Chehab };
351b285192aSMauro Carvalho Chehab 
352b285192aSMauro Carvalho Chehab /* ----------------------------------------------------------- */
353b285192aSMauro Carvalho Chehab 
354b285192aSMauro Carvalho Chehab static int
355b285192aSMauro Carvalho Chehab saa7134_i2c_eeprom(struct saa7134_dev *dev, unsigned char *eedata, int len)
356b285192aSMauro Carvalho Chehab {
357b285192aSMauro Carvalho Chehab 	unsigned char buf;
358b285192aSMauro Carvalho Chehab 	int i,err;
359b285192aSMauro Carvalho Chehab 
360b285192aSMauro Carvalho Chehab 	dev->i2c_client.addr = 0xa0 >> 1;
361b285192aSMauro Carvalho Chehab 	buf = 0;
362b285192aSMauro Carvalho Chehab 	if (1 != (err = i2c_master_send(&dev->i2c_client,&buf,1))) {
36383582009SMauro Carvalho Chehab 		pr_info("%s: Huh, no eeprom present (err=%d)?\n",
364b285192aSMauro Carvalho Chehab 		       dev->name,err);
365b285192aSMauro Carvalho Chehab 		return -1;
366b285192aSMauro Carvalho Chehab 	}
367b285192aSMauro Carvalho Chehab 	if (len != (err = i2c_master_recv(&dev->i2c_client,eedata,len))) {
36883582009SMauro Carvalho Chehab 		pr_warn("%s: i2c eeprom read error (err=%d)\n",
369b285192aSMauro Carvalho Chehab 		       dev->name,err);
370b285192aSMauro Carvalho Chehab 		return -1;
371b285192aSMauro Carvalho Chehab 	}
372b285192aSMauro Carvalho Chehab 	for (i = 0; i < len; i++) {
373b285192aSMauro Carvalho Chehab 		if (0 == (i % 16))
37483582009SMauro Carvalho Chehab 			pr_info("%s: i2c eeprom %02x:",dev->name,i);
375b285192aSMauro Carvalho Chehab 		printk(" %02x",eedata[i]);
376b285192aSMauro Carvalho Chehab 		if (15 == (i % 16))
377b285192aSMauro Carvalho Chehab 			printk("\n");
378b285192aSMauro Carvalho Chehab 	}
379b285192aSMauro Carvalho Chehab 	return 0;
380b285192aSMauro Carvalho Chehab }
381b285192aSMauro Carvalho Chehab 
382b285192aSMauro Carvalho Chehab static char *i2c_devs[128] = {
383b285192aSMauro Carvalho Chehab 	[ 0x20      ] = "mpeg encoder (saa6752hs)",
384b285192aSMauro Carvalho Chehab 	[ 0xa0 >> 1 ] = "eeprom",
385b285192aSMauro Carvalho Chehab 	[ 0xc0 >> 1 ] = "tuner (analog)",
386b285192aSMauro Carvalho Chehab 	[ 0x86 >> 1 ] = "tda9887",
387b285192aSMauro Carvalho Chehab 	[ 0x5a >> 1 ] = "remote control",
388b285192aSMauro Carvalho Chehab };
389b285192aSMauro Carvalho Chehab 
390b285192aSMauro Carvalho Chehab static void do_i2c_scan(char *name, struct i2c_client *c)
391b285192aSMauro Carvalho Chehab {
392b285192aSMauro Carvalho Chehab 	unsigned char buf;
393b285192aSMauro Carvalho Chehab 	int i,rc;
394b285192aSMauro Carvalho Chehab 
395b285192aSMauro Carvalho Chehab 	for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
396b285192aSMauro Carvalho Chehab 		c->addr = i;
397b285192aSMauro Carvalho Chehab 		rc = i2c_master_recv(c,&buf,0);
398b285192aSMauro Carvalho Chehab 		if (rc < 0)
399b285192aSMauro Carvalho Chehab 			continue;
400b285192aSMauro Carvalho Chehab 		printk("%s: i2c scan: found device @ 0x%x  [%s]\n",
401b285192aSMauro Carvalho Chehab 		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
402b285192aSMauro Carvalho Chehab 	}
403b285192aSMauro Carvalho Chehab }
404b285192aSMauro Carvalho Chehab 
405b285192aSMauro Carvalho Chehab int saa7134_i2c_register(struct saa7134_dev *dev)
406b285192aSMauro Carvalho Chehab {
407b285192aSMauro Carvalho Chehab 	dev->i2c_adap = saa7134_adap_template;
408b285192aSMauro Carvalho Chehab 	dev->i2c_adap.dev.parent = &dev->pci->dev;
409b285192aSMauro Carvalho Chehab 	strcpy(dev->i2c_adap.name,dev->name);
410b285192aSMauro Carvalho Chehab 	dev->i2c_adap.algo_data = dev;
411b285192aSMauro Carvalho Chehab 	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
412b285192aSMauro Carvalho Chehab 	i2c_add_adapter(&dev->i2c_adap);
413b285192aSMauro Carvalho Chehab 
414b285192aSMauro Carvalho Chehab 	dev->i2c_client = saa7134_client_template;
415b285192aSMauro Carvalho Chehab 	dev->i2c_client.adapter = &dev->i2c_adap;
416b285192aSMauro Carvalho Chehab 
417b285192aSMauro Carvalho Chehab 	saa7134_i2c_eeprom(dev,dev->eedata,sizeof(dev->eedata));
418b285192aSMauro Carvalho Chehab 	if (i2c_scan)
419b285192aSMauro Carvalho Chehab 		do_i2c_scan(dev->name,&dev->i2c_client);
420b285192aSMauro Carvalho Chehab 
421b285192aSMauro Carvalho Chehab 	/* Instantiate the IR receiver device, if present */
422b285192aSMauro Carvalho Chehab 	saa7134_probe_i2c_ir(dev);
423b285192aSMauro Carvalho Chehab 	return 0;
424b285192aSMauro Carvalho Chehab }
425b285192aSMauro Carvalho Chehab 
426b285192aSMauro Carvalho Chehab int saa7134_i2c_unregister(struct saa7134_dev *dev)
427b285192aSMauro Carvalho Chehab {
428b285192aSMauro Carvalho Chehab 	i2c_del_adapter(&dev->i2c_adap);
429b285192aSMauro Carvalho Chehab 	return 0;
430b285192aSMauro Carvalho Chehab }
431