xref: /OK3568_Linux_fs/kernel/drivers/media/usb/au0828/au0828-i2c.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Driver for the Auvitek AU0828 USB bridge
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "au0828.h"
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/moduleparam.h>
12*4882a593Smuzhiyun #include <linux/init.h>
13*4882a593Smuzhiyun #include <linux/delay.h>
14*4882a593Smuzhiyun #include <linux/io.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "media/tuner.h"
17*4882a593Smuzhiyun #include <media/v4l2-common.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun static int i2c_scan;
20*4882a593Smuzhiyun module_param(i2c_scan, int, 0444);
21*4882a593Smuzhiyun MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define I2C_WAIT_DELAY 25
24*4882a593Smuzhiyun #define I2C_WAIT_RETRY 1000
25*4882a593Smuzhiyun 
i2c_slave_did_write_ack(struct i2c_adapter * i2c_adap)26*4882a593Smuzhiyun static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	struct au0828_dev *dev = i2c_adap->algo_data;
29*4882a593Smuzhiyun 	return au0828_read(dev, AU0828_I2C_STATUS_201) &
30*4882a593Smuzhiyun 		AU0828_I2C_STATUS_NO_WRITE_ACK ? 0 : 1;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun 
i2c_slave_did_read_ack(struct i2c_adapter * i2c_adap)33*4882a593Smuzhiyun static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun 	struct au0828_dev *dev = i2c_adap->algo_data;
36*4882a593Smuzhiyun 	return au0828_read(dev, AU0828_I2C_STATUS_201) &
37*4882a593Smuzhiyun 		AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun 
i2c_wait_read_ack(struct i2c_adapter * i2c_adap)40*4882a593Smuzhiyun static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	int count;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	for (count = 0; count < I2C_WAIT_RETRY; count++) {
45*4882a593Smuzhiyun 		if (!i2c_slave_did_read_ack(i2c_adap))
46*4882a593Smuzhiyun 			break;
47*4882a593Smuzhiyun 		udelay(I2C_WAIT_DELAY);
48*4882a593Smuzhiyun 	}
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	if (I2C_WAIT_RETRY == count)
51*4882a593Smuzhiyun 		return 0;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	return 1;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
i2c_is_read_busy(struct i2c_adapter * i2c_adap)56*4882a593Smuzhiyun static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	struct au0828_dev *dev = i2c_adap->algo_data;
59*4882a593Smuzhiyun 	return au0828_read(dev, AU0828_I2C_STATUS_201) &
60*4882a593Smuzhiyun 		AU0828_I2C_STATUS_READ_DONE ? 0 : 1;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
i2c_wait_read_done(struct i2c_adapter * i2c_adap)63*4882a593Smuzhiyun static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	int count;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	for (count = 0; count < I2C_WAIT_RETRY; count++) {
68*4882a593Smuzhiyun 		if (!i2c_is_read_busy(i2c_adap))
69*4882a593Smuzhiyun 			break;
70*4882a593Smuzhiyun 		udelay(I2C_WAIT_DELAY);
71*4882a593Smuzhiyun 	}
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	if (I2C_WAIT_RETRY == count)
74*4882a593Smuzhiyun 		return 0;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	return 1;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
i2c_is_write_done(struct i2c_adapter * i2c_adap)79*4882a593Smuzhiyun static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun 	struct au0828_dev *dev = i2c_adap->algo_data;
82*4882a593Smuzhiyun 	return au0828_read(dev, AU0828_I2C_STATUS_201) &
83*4882a593Smuzhiyun 		AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
i2c_wait_write_done(struct i2c_adapter * i2c_adap)86*4882a593Smuzhiyun static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	int count;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	for (count = 0; count < I2C_WAIT_RETRY; count++) {
91*4882a593Smuzhiyun 		if (i2c_is_write_done(i2c_adap))
92*4882a593Smuzhiyun 			break;
93*4882a593Smuzhiyun 		udelay(I2C_WAIT_DELAY);
94*4882a593Smuzhiyun 	}
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	if (I2C_WAIT_RETRY == count)
97*4882a593Smuzhiyun 		return 0;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	return 1;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
i2c_is_busy(struct i2c_adapter * i2c_adap)102*4882a593Smuzhiyun static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	struct au0828_dev *dev = i2c_adap->algo_data;
105*4882a593Smuzhiyun 	return au0828_read(dev, AU0828_I2C_STATUS_201) &
106*4882a593Smuzhiyun 		AU0828_I2C_STATUS_BUSY ? 1 : 0;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
i2c_wait_done(struct i2c_adapter * i2c_adap)109*4882a593Smuzhiyun static int i2c_wait_done(struct i2c_adapter *i2c_adap)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	int count;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	for (count = 0; count < I2C_WAIT_RETRY; count++) {
114*4882a593Smuzhiyun 		if (!i2c_is_busy(i2c_adap))
115*4882a593Smuzhiyun 			break;
116*4882a593Smuzhiyun 		udelay(I2C_WAIT_DELAY);
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	if (I2C_WAIT_RETRY == count)
120*4882a593Smuzhiyun 		return 0;
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	return 1;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun /* FIXME: Implement join handling correctly */
i2c_sendbytes(struct i2c_adapter * i2c_adap,const struct i2c_msg * msg,int joined_rlen)126*4882a593Smuzhiyun static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
127*4882a593Smuzhiyun 	const struct i2c_msg *msg, int joined_rlen)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun 	int i, strobe = 0;
130*4882a593Smuzhiyun 	struct au0828_dev *dev = i2c_adap->algo_data;
131*4882a593Smuzhiyun 	u8 i2c_speed = dev->board.i2c_clk_divider;
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	dprintk(4, "%s()\n", __func__);
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	if (((dev->board.tuner_type == TUNER_XC5000) ||
138*4882a593Smuzhiyun 	     (dev->board.tuner_type == TUNER_XC5000C)) &&
139*4882a593Smuzhiyun 	    (dev->board.tuner_addr == msg->addr)) {
140*4882a593Smuzhiyun 		/*
141*4882a593Smuzhiyun 		 * Due to I2C clock stretch, we need to use a lower speed
142*4882a593Smuzhiyun 		 * on xc5000 for commands. However, firmware transfer can
143*4882a593Smuzhiyun 		 * speed up to 400 KHz.
144*4882a593Smuzhiyun 		 */
145*4882a593Smuzhiyun 		if (msg->len == 64)
146*4882a593Smuzhiyun 			i2c_speed = AU0828_I2C_CLK_250KHZ;
147*4882a593Smuzhiyun 		else
148*4882a593Smuzhiyun 			i2c_speed = AU0828_I2C_CLK_20KHZ;
149*4882a593Smuzhiyun 	}
150*4882a593Smuzhiyun 	/* Set the I2C clock */
151*4882a593Smuzhiyun 	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	/* Hardware needs 8 bit addresses */
154*4882a593Smuzhiyun 	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	dprintk(4, "SEND: %02x\n", msg->addr);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	/* Deal with i2c_scan */
159*4882a593Smuzhiyun 	if (msg->len == 0) {
160*4882a593Smuzhiyun 		/* The analog tuner detection code makes use of the SMBUS_QUICK
161*4882a593Smuzhiyun 		   message (which involves a zero length i2c write).  To avoid
162*4882a593Smuzhiyun 		   checking the status register when we didn't strobe out any
163*4882a593Smuzhiyun 		   actual bytes to the bus, just do a read check.  This is
164*4882a593Smuzhiyun 		   consistent with how I saw i2c device checking done in the
165*4882a593Smuzhiyun 		   USB trace of the Windows driver */
166*4882a593Smuzhiyun 		au0828_write(dev, AU0828_I2C_TRIGGER_200,
167*4882a593Smuzhiyun 			     AU0828_I2C_TRIGGER_READ);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 		if (!i2c_wait_done(i2c_adap))
170*4882a593Smuzhiyun 			return -EIO;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 		if (i2c_wait_read_ack(i2c_adap))
173*4882a593Smuzhiyun 			return -EIO;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 		return 0;
176*4882a593Smuzhiyun 	}
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	for (i = 0; i < msg->len;) {
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 		dprintk(4, " %02x\n", msg->buf[i]);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 		au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 		strobe++;
185*4882a593Smuzhiyun 		i++;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 		if ((strobe >= 4) || (i >= msg->len)) {
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 			/* Strobe the byte into the bus */
190*4882a593Smuzhiyun 			if (i < msg->len)
191*4882a593Smuzhiyun 				au0828_write(dev, AU0828_I2C_TRIGGER_200,
192*4882a593Smuzhiyun 					     AU0828_I2C_TRIGGER_WRITE |
193*4882a593Smuzhiyun 					     AU0828_I2C_TRIGGER_HOLD);
194*4882a593Smuzhiyun 			else
195*4882a593Smuzhiyun 				au0828_write(dev, AU0828_I2C_TRIGGER_200,
196*4882a593Smuzhiyun 					     AU0828_I2C_TRIGGER_WRITE);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 			/* Reset strobe trigger */
199*4882a593Smuzhiyun 			strobe = 0;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 			if (!i2c_wait_write_done(i2c_adap))
202*4882a593Smuzhiyun 				return -EIO;
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 		}
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun 	if (!i2c_wait_done(i2c_adap))
208*4882a593Smuzhiyun 		return -EIO;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	dprintk(4, "\n");
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	return msg->len;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun /* FIXME: Implement join handling correctly */
i2c_readbytes(struct i2c_adapter * i2c_adap,const struct i2c_msg * msg,int joined)216*4882a593Smuzhiyun static int i2c_readbytes(struct i2c_adapter *i2c_adap,
217*4882a593Smuzhiyun 	const struct i2c_msg *msg, int joined)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	struct au0828_dev *dev = i2c_adap->algo_data;
220*4882a593Smuzhiyun 	u8 i2c_speed = dev->board.i2c_clk_divider;
221*4882a593Smuzhiyun 	int i;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	dprintk(4, "%s()\n", __func__);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	/*
228*4882a593Smuzhiyun 	 * Due to xc5000c clock stretch, we cannot use full speed at
229*4882a593Smuzhiyun 	 * readings from xc5000, as otherwise they'll fail.
230*4882a593Smuzhiyun 	 */
231*4882a593Smuzhiyun 	if (((dev->board.tuner_type == TUNER_XC5000) ||
232*4882a593Smuzhiyun 	     (dev->board.tuner_type == TUNER_XC5000C)) &&
233*4882a593Smuzhiyun 	    (dev->board.tuner_addr == msg->addr))
234*4882a593Smuzhiyun 		i2c_speed = AU0828_I2C_CLK_20KHZ;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	/* Set the I2C clock */
237*4882a593Smuzhiyun 	au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202, i2c_speed);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	/* Hardware needs 8 bit addresses */
240*4882a593Smuzhiyun 	au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	dprintk(4, " RECV:\n");
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	/* Deal with i2c_scan */
245*4882a593Smuzhiyun 	if (msg->len == 0) {
246*4882a593Smuzhiyun 		au0828_write(dev, AU0828_I2C_TRIGGER_200,
247*4882a593Smuzhiyun 			     AU0828_I2C_TRIGGER_READ);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 		if (i2c_wait_read_ack(i2c_adap))
250*4882a593Smuzhiyun 			return -EIO;
251*4882a593Smuzhiyun 		return 0;
252*4882a593Smuzhiyun 	}
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	for (i = 0; i < msg->len;) {
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 		i++;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 		if (i < msg->len)
259*4882a593Smuzhiyun 			au0828_write(dev, AU0828_I2C_TRIGGER_200,
260*4882a593Smuzhiyun 				     AU0828_I2C_TRIGGER_READ |
261*4882a593Smuzhiyun 				     AU0828_I2C_TRIGGER_HOLD);
262*4882a593Smuzhiyun 		else
263*4882a593Smuzhiyun 			au0828_write(dev, AU0828_I2C_TRIGGER_200,
264*4882a593Smuzhiyun 				     AU0828_I2C_TRIGGER_READ);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 		if (!i2c_wait_read_done(i2c_adap))
267*4882a593Smuzhiyun 			return -EIO;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 		msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) &
270*4882a593Smuzhiyun 			0xff;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 		dprintk(4, " %02x\n", msg->buf[i-1]);
273*4882a593Smuzhiyun 	}
274*4882a593Smuzhiyun 	if (!i2c_wait_done(i2c_adap))
275*4882a593Smuzhiyun 		return -EIO;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	dprintk(4, "\n");
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	return msg->len;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
i2c_xfer(struct i2c_adapter * i2c_adap,struct i2c_msg * msgs,int num)282*4882a593Smuzhiyun static int i2c_xfer(struct i2c_adapter *i2c_adap,
283*4882a593Smuzhiyun 		    struct i2c_msg *msgs, int num)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun 	int i, retval = 0;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	dprintk(4, "%s(num = %d)\n", __func__, num);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
290*4882a593Smuzhiyun 		dprintk(4, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
291*4882a593Smuzhiyun 			__func__, num, msgs[i].addr, msgs[i].len);
292*4882a593Smuzhiyun 		if (msgs[i].flags & I2C_M_RD) {
293*4882a593Smuzhiyun 			/* read */
294*4882a593Smuzhiyun 			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
295*4882a593Smuzhiyun 		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
296*4882a593Smuzhiyun 			   msgs[i].addr == msgs[i + 1].addr) {
297*4882a593Smuzhiyun 			/* write then read from same address */
298*4882a593Smuzhiyun 			retval = i2c_sendbytes(i2c_adap, &msgs[i],
299*4882a593Smuzhiyun 					       msgs[i + 1].len);
300*4882a593Smuzhiyun 			if (retval < 0)
301*4882a593Smuzhiyun 				goto err;
302*4882a593Smuzhiyun 			i++;
303*4882a593Smuzhiyun 			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
304*4882a593Smuzhiyun 		} else {
305*4882a593Smuzhiyun 			/* write */
306*4882a593Smuzhiyun 			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
307*4882a593Smuzhiyun 		}
308*4882a593Smuzhiyun 		if (retval < 0)
309*4882a593Smuzhiyun 			goto err;
310*4882a593Smuzhiyun 	}
311*4882a593Smuzhiyun 	return num;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun err:
314*4882a593Smuzhiyun 	return retval;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
au0828_functionality(struct i2c_adapter * adap)317*4882a593Smuzhiyun static u32 au0828_functionality(struct i2c_adapter *adap)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun 	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun static const struct i2c_algorithm au0828_i2c_algo_template = {
323*4882a593Smuzhiyun 	.master_xfer	= i2c_xfer,
324*4882a593Smuzhiyun 	.functionality	= au0828_functionality,
325*4882a593Smuzhiyun };
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun /* ----------------------------------------------------------------------- */
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun static const struct i2c_adapter au0828_i2c_adap_template = {
330*4882a593Smuzhiyun 	.name              = KBUILD_MODNAME,
331*4882a593Smuzhiyun 	.owner             = THIS_MODULE,
332*4882a593Smuzhiyun 	.algo              = &au0828_i2c_algo_template,
333*4882a593Smuzhiyun };
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun static const struct i2c_client au0828_i2c_client_template = {
336*4882a593Smuzhiyun 	.name	= "au0828 internal",
337*4882a593Smuzhiyun };
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun static char *i2c_devs[128] = {
340*4882a593Smuzhiyun 	[0x8e >> 1] = "au8522",
341*4882a593Smuzhiyun 	[0xa0 >> 1] = "eeprom",
342*4882a593Smuzhiyun 	[0xc2 >> 1] = "tuner/xc5000",
343*4882a593Smuzhiyun };
344*4882a593Smuzhiyun 
do_i2c_scan(char * name,struct i2c_client * c)345*4882a593Smuzhiyun static void do_i2c_scan(char *name, struct i2c_client *c)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun 	unsigned char buf;
348*4882a593Smuzhiyun 	int i, rc;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	for (i = 0; i < 128; i++) {
351*4882a593Smuzhiyun 		c->addr = i;
352*4882a593Smuzhiyun 		rc = i2c_master_recv(c, &buf, 0);
353*4882a593Smuzhiyun 		if (rc < 0)
354*4882a593Smuzhiyun 			continue;
355*4882a593Smuzhiyun 		pr_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
356*4882a593Smuzhiyun 		       name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
357*4882a593Smuzhiyun 	}
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun /* init + register i2c adapter */
au0828_i2c_register(struct au0828_dev * dev)361*4882a593Smuzhiyun int au0828_i2c_register(struct au0828_dev *dev)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	dprintk(1, "%s()\n", __func__);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	dev->i2c_adap = au0828_i2c_adap_template;
366*4882a593Smuzhiyun 	dev->i2c_algo = au0828_i2c_algo_template;
367*4882a593Smuzhiyun 	dev->i2c_client = au0828_i2c_client_template;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	dev->i2c_adap.dev.parent = &dev->usbdev->dev;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	strscpy(dev->i2c_adap.name, KBUILD_MODNAME,
372*4882a593Smuzhiyun 		sizeof(dev->i2c_adap.name));
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	dev->i2c_adap.algo = &dev->i2c_algo;
375*4882a593Smuzhiyun 	dev->i2c_adap.algo_data = dev;
376*4882a593Smuzhiyun #ifdef CONFIG_VIDEO_AU0828_V4L2
377*4882a593Smuzhiyun 	i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
378*4882a593Smuzhiyun #else
379*4882a593Smuzhiyun 	i2c_set_adapdata(&dev->i2c_adap, dev);
380*4882a593Smuzhiyun #endif
381*4882a593Smuzhiyun 	i2c_add_adapter(&dev->i2c_adap);
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	dev->i2c_client.adapter = &dev->i2c_adap;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	if (0 == dev->i2c_rc) {
386*4882a593Smuzhiyun 		pr_info("i2c bus registered\n");
387*4882a593Smuzhiyun 		if (i2c_scan)
388*4882a593Smuzhiyun 			do_i2c_scan(KBUILD_MODNAME, &dev->i2c_client);
389*4882a593Smuzhiyun 	} else
390*4882a593Smuzhiyun 		pr_info("i2c bus register FAILED\n");
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	return dev->i2c_rc;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
au0828_i2c_unregister(struct au0828_dev * dev)395*4882a593Smuzhiyun int au0828_i2c_unregister(struct au0828_dev *dev)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun 	i2c_del_adapter(&dev->i2c_adap);
398*4882a593Smuzhiyun 	return 0;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
401