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