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