]>
Commit | Line | Data |
---|---|---|
a6c2ba28 | 1 | /* |
f7abcd38 | 2 | em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices |
a6c2ba28 | 3 | |
f7abcd38 MCC |
4 | Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it> |
5 | Markus Rechberger <mrechberger@gmail.com> | |
2e7c6dc3 | 6 | Mauro Carvalho Chehab <mchehab@infradead.org> |
f7abcd38 | 7 | Sascha Sommer <saschasommer@freenet.de> |
a6c2ba28 | 8 | |
9 | This program is free software; you can redistribute it and/or modify | |
10 | it under the terms of the GNU General Public License as published by | |
11 | the Free Software Foundation; either version 2 of the License, or | |
12 | (at your option) any later version. | |
13 | ||
14 | This program is distributed in the hope that it will be useful, | |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | GNU General Public License for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
20 | along with this program; if not, write to the Free Software | |
21 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 | */ | |
23 | ||
24 | #include <linux/module.h> | |
25 | #include <linux/kernel.h> | |
26 | #include <linux/usb.h> | |
27 | #include <linux/i2c.h> | |
a6c2ba28 | 28 | #include <linux/video_decoder.h> |
29 | ||
f7abcd38 | 30 | #include "em28xx.h" |
6c362c8e | 31 | #include "tuner-xc2028.h" |
5e453dc7 | 32 | #include <media/v4l2-common.h> |
d5e52653 | 33 | #include <media/tuner.h> |
a6c2ba28 | 34 | |
35 | /* ----------------------------------------------------------- */ | |
36 | ||
37 | static unsigned int i2c_scan = 0; | |
38 | module_param(i2c_scan, int, 0444); | |
39 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); | |
40 | ||
41 | static unsigned int i2c_debug = 0; | |
42 | module_param(i2c_debug, int, 0644); | |
43 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | |
44 | ||
d5e52653 | 45 | #define dprintk1(lvl,fmt, args...) if (i2c_debug>=lvl) do {\ |
674434c6 | 46 | printk(fmt, ##args); } while (0) |
d5e52653 MCC |
47 | #define dprintk2(lvl,fmt, args...) if (i2c_debug>=lvl) do{ \ |
48 | printk(KERN_DEBUG "%s at %s: " fmt, \ | |
f85c657f | 49 | dev->name, __FUNCTION__ , ##args); } while (0) |
a6c2ba28 | 50 | |
51 | /* | |
596d92d5 MCC |
52 | * em2800_i2c_send_max4() |
53 | * send up to 4 bytes to the i2c device | |
54 | */ | |
3acf2809 | 55 | static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, |
596d92d5 MCC |
56 | char *buf, int len) |
57 | { | |
58 | int ret; | |
59 | int write_timeout; | |
60 | unsigned char b2[6]; | |
61 | BUG_ON(len < 1 || len > 4); | |
62 | b2[5] = 0x80 + len - 1; | |
63 | b2[4] = addr; | |
64 | b2[3] = buf[0]; | |
65 | if (len > 1) | |
66 | b2[2] = buf[1]; | |
67 | if (len > 2) | |
68 | b2[1] = buf[2]; | |
69 | if (len > 3) | |
70 | b2[0] = buf[3]; | |
71 | ||
3acf2809 | 72 | ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); |
596d92d5 | 73 | if (ret != 2 + len) { |
beb7dd86 | 74 | em28xx_warn("writing to i2c device failed (error=%i)\n", ret); |
596d92d5 MCC |
75 | return -EIO; |
76 | } | |
77 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; | |
78 | write_timeout -= 5) { | |
3acf2809 | 79 | ret = dev->em28xx_read_reg(dev, 0x05); |
596d92d5 MCC |
80 | if (ret == 0x80 + len - 1) |
81 | return len; | |
e8e41da4 | 82 | msleep(5); |
596d92d5 | 83 | } |
3acf2809 | 84 | em28xx_warn("i2c write timed out\n"); |
596d92d5 MCC |
85 | return -EIO; |
86 | } | |
87 | ||
88 | /* | |
89 | * em2800_i2c_send_bytes() | |
90 | */ | |
91 | static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, | |
92 | short len) | |
93 | { | |
94 | char *bufPtr = buf; | |
95 | int ret; | |
96 | int wrcount = 0; | |
97 | int count; | |
98 | int maxLen = 4; | |
3acf2809 | 99 | struct em28xx *dev = (struct em28xx *)data; |
596d92d5 MCC |
100 | while (len > 0) { |
101 | count = (len > maxLen) ? maxLen : len; | |
102 | ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); | |
103 | if (ret > 0) { | |
104 | len -= count; | |
105 | bufPtr += count; | |
106 | wrcount += count; | |
107 | } else | |
108 | return (ret < 0) ? ret : -EFAULT; | |
109 | } | |
110 | return wrcount; | |
111 | } | |
112 | ||
113 | /* | |
114 | * em2800_i2c_check_for_device() | |
115 | * check if there is a i2c_device at the supplied address | |
116 | */ | |
3acf2809 | 117 | static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) |
596d92d5 MCC |
118 | { |
119 | char msg; | |
120 | int ret; | |
121 | int write_timeout; | |
122 | msg = addr; | |
3acf2809 | 123 | ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1); |
596d92d5 | 124 | if (ret < 0) { |
3acf2809 | 125 | em28xx_warn("setting i2c device address failed (error=%i)\n", |
596d92d5 MCC |
126 | ret); |
127 | return ret; | |
128 | } | |
129 | msg = 0x84; | |
3acf2809 | 130 | ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1); |
596d92d5 | 131 | if (ret < 0) { |
3acf2809 | 132 | em28xx_warn("preparing i2c read failed (error=%i)\n", ret); |
596d92d5 MCC |
133 | return ret; |
134 | } | |
135 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; | |
136 | write_timeout -= 5) { | |
3acf2809 | 137 | unsigned msg = dev->em28xx_read_reg(dev, 0x5); |
596d92d5 MCC |
138 | if (msg == 0x94) |
139 | return -ENODEV; | |
140 | else if (msg == 0x84) | |
141 | return 0; | |
e8e41da4 | 142 | msleep(5); |
596d92d5 MCC |
143 | } |
144 | return -ENODEV; | |
145 | } | |
146 | ||
147 | /* | |
148 | * em2800_i2c_recv_bytes() | |
149 | * read from the i2c device | |
150 | */ | |
3acf2809 | 151 | static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, |
596d92d5 MCC |
152 | char *buf, int len) |
153 | { | |
154 | int ret; | |
155 | /* check for the device and set i2c read address */ | |
156 | ret = em2800_i2c_check_for_device(dev, addr); | |
157 | if (ret) { | |
3acf2809 | 158 | em28xx_warn |
596d92d5 MCC |
159 | ("preparing read at i2c address 0x%x failed (error=%i)\n", |
160 | addr, ret); | |
161 | return ret; | |
162 | } | |
3acf2809 | 163 | ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len); |
596d92d5 | 164 | if (ret < 0) { |
3acf2809 | 165 | em28xx_warn("reading from i2c device at 0x%x failed (error=%i)", |
596d92d5 MCC |
166 | addr, ret); |
167 | return ret; | |
168 | } | |
169 | return ret; | |
170 | } | |
171 | ||
172 | /* | |
3acf2809 | 173 | * em28xx_i2c_send_bytes() |
a6c2ba28 | 174 | * untested for more than 4 bytes |
175 | */ | |
3acf2809 | 176 | static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf, |
596d92d5 | 177 | short len, int stop) |
a6c2ba28 | 178 | { |
179 | int wrcount = 0; | |
3acf2809 | 180 | struct em28xx *dev = (struct em28xx *)data; |
a6c2ba28 | 181 | |
3acf2809 | 182 | wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); |
a6c2ba28 | 183 | |
184 | return wrcount; | |
185 | } | |
186 | ||
187 | /* | |
3acf2809 | 188 | * em28xx_i2c_recv_bytes() |
a6c2ba28 | 189 | * read a byte from the i2c device |
190 | */ | |
3acf2809 | 191 | static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, |
596d92d5 | 192 | char *buf, int len) |
a6c2ba28 | 193 | { |
194 | int ret; | |
3acf2809 | 195 | ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); |
a6c2ba28 | 196 | if (ret < 0) { |
3acf2809 | 197 | em28xx_warn("reading i2c device failed (error=%i)\n", ret); |
a6c2ba28 | 198 | return ret; |
199 | } | |
3acf2809 | 200 | if (dev->em28xx_read_reg(dev, 0x5) != 0) |
a6c2ba28 | 201 | return -ENODEV; |
202 | return ret; | |
203 | } | |
204 | ||
205 | /* | |
3acf2809 | 206 | * em28xx_i2c_check_for_device() |
a6c2ba28 | 207 | * check if there is a i2c_device at the supplied address |
208 | */ | |
3acf2809 | 209 | static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr) |
a6c2ba28 | 210 | { |
211 | char msg; | |
212 | int ret; | |
213 | msg = addr; | |
214 | ||
3acf2809 | 215 | ret = dev->em28xx_read_reg_req(dev, 2, addr); |
a6c2ba28 | 216 | if (ret < 0) { |
3acf2809 | 217 | em28xx_warn("reading from i2c device failed (error=%i)\n", ret); |
a6c2ba28 | 218 | return ret; |
219 | } | |
3acf2809 | 220 | if (dev->em28xx_read_reg(dev, 0x5) != 0) |
a6c2ba28 | 221 | return -ENODEV; |
222 | return 0; | |
223 | } | |
224 | ||
225 | /* | |
3acf2809 | 226 | * em28xx_i2c_xfer() |
a6c2ba28 | 227 | * the main i2c transfer function |
228 | */ | |
3acf2809 | 229 | static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, |
a6c2ba28 | 230 | struct i2c_msg msgs[], int num) |
231 | { | |
3acf2809 | 232 | struct em28xx *dev = i2c_adap->algo_data; |
a6c2ba28 | 233 | int addr, rc, i, byte; |
234 | ||
235 | if (num <= 0) | |
236 | return 0; | |
237 | for (i = 0; i < num; i++) { | |
238 | addr = msgs[i].addr << 1; | |
d5e52653 | 239 | dprintk2(2,"%s %s addr=%x len=%d:", |
a6c2ba28 | 240 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", |
241 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); | |
242 | if (!msgs[i].len) { /* no len: check only for device presence */ | |
596d92d5 MCC |
243 | if (dev->is_em2800) |
244 | rc = em2800_i2c_check_for_device(dev, addr); | |
245 | else | |
3acf2809 | 246 | rc = em28xx_i2c_check_for_device(dev, addr); |
a6c2ba28 | 247 | if (rc < 0) { |
d5e52653 | 248 | dprintk2(2," no device\n"); |
a6c2ba28 | 249 | return rc; |
250 | } | |
251 | ||
596d92d5 | 252 | } else if (msgs[i].flags & I2C_M_RD) { |
a6c2ba28 | 253 | /* read bytes */ |
596d92d5 MCC |
254 | if (dev->is_em2800) |
255 | rc = em2800_i2c_recv_bytes(dev, addr, | |
256 | msgs[i].buf, | |
257 | msgs[i].len); | |
258 | else | |
3acf2809 | 259 | rc = em28xx_i2c_recv_bytes(dev, addr, |
596d92d5 MCC |
260 | msgs[i].buf, |
261 | msgs[i].len); | |
d5e52653 | 262 | if (i2c_debug>=2) { |
a6c2ba28 | 263 | for (byte = 0; byte < msgs[i].len; byte++) { |
264 | printk(" %02x", msgs[i].buf[byte]); | |
265 | } | |
266 | } | |
267 | } else { | |
268 | /* write bytes */ | |
d5e52653 | 269 | if (i2c_debug>=2) { |
a6c2ba28 | 270 | for (byte = 0; byte < msgs[i].len; byte++) |
271 | printk(" %02x", msgs[i].buf[byte]); | |
272 | } | |
596d92d5 MCC |
273 | if (dev->is_em2800) |
274 | rc = em2800_i2c_send_bytes(dev, addr, | |
275 | msgs[i].buf, | |
276 | msgs[i].len); | |
277 | else | |
3acf2809 | 278 | rc = em28xx_i2c_send_bytes(dev, addr, |
596d92d5 MCC |
279 | msgs[i].buf, |
280 | msgs[i].len, | |
281 | i == num - 1); | |
a6c2ba28 | 282 | } |
e8e41da4 MR |
283 | if (rc < 0) |
284 | goto err; | |
d5e52653 | 285 | if (i2c_debug>=2) |
a6c2ba28 | 286 | printk("\n"); |
287 | } | |
288 | ||
289 | return num; | |
290 | err: | |
d5e52653 | 291 | dprintk2(2," ERROR: %i\n", rc); |
a6c2ba28 | 292 | return rc; |
293 | } | |
294 | ||
03910cc3 MCC |
295 | /* based on linux/sunrpc/svcauth.h and linux/hash.h |
296 | * The original hash function returns a different value, if arch is x86_64 | |
297 | * or i386. | |
298 | */ | |
299 | static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits) | |
300 | { | |
301 | unsigned long hash = 0; | |
302 | unsigned long l = 0; | |
303 | int len = 0; | |
304 | unsigned char c; | |
305 | do { | |
306 | if (len == length) { | |
307 | c = (char)len; | |
308 | len = -1; | |
309 | } else | |
310 | c = *buf++; | |
311 | l = (l << 8) | c; | |
312 | len++; | |
313 | if ((len & (32 / 8 - 1)) == 0) | |
314 | hash = ((hash^l) * 0x9e370001UL); | |
315 | } while (len); | |
316 | ||
317 | return (hash >> (32 - bits)) & 0xffffffffUL; | |
318 | } | |
319 | ||
3acf2809 | 320 | static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) |
a6c2ba28 | 321 | { |
322 | unsigned char buf, *p = eedata; | |
3acf2809 | 323 | struct em28xx_eeprom *em_eeprom = (void *)eedata; |
a6c2ba28 | 324 | int i, err, size = len, block; |
325 | ||
326 | dev->i2c_client.addr = 0xa0 >> 1; | |
596d92d5 MCC |
327 | |
328 | /* Check if board has eeprom */ | |
329 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); | |
330 | if (err < 0) | |
331 | return -1; | |
332 | ||
a6c2ba28 | 333 | buf = 0; |
334 | if (1 != (err = i2c_master_send(&dev->i2c_client, &buf, 1))) { | |
335 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", | |
336 | dev->name, err); | |
337 | return -1; | |
338 | } | |
339 | while (size > 0) { | |
340 | if (size > 16) | |
341 | block = 16; | |
342 | else | |
343 | block = size; | |
344 | ||
345 | if (block != | |
346 | (err = i2c_master_recv(&dev->i2c_client, p, block))) { | |
347 | printk(KERN_WARNING | |
348 | "%s: i2c eeprom read error (err=%d)\n", | |
349 | dev->name, err); | |
350 | return -1; | |
351 | } | |
352 | size -= block; | |
353 | p += block; | |
354 | } | |
355 | for (i = 0; i < len; i++) { | |
356 | if (0 == (i % 16)) | |
357 | printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); | |
358 | printk(" %02x", eedata[i]); | |
359 | if (15 == (i % 16)) | |
360 | printk("\n"); | |
361 | } | |
362 | ||
03910cc3 MCC |
363 | if (em_eeprom->id == 0x9567eb1a) |
364 | dev->hash = em28xx_hash_mem(eedata, len, 32); | |
365 | ||
366 | printk(KERN_INFO "EEPROM ID= 0x%08x, hash = 0x%08lx\n", | |
367 | em_eeprom->id, dev->hash); | |
a6c2ba28 | 368 | printk(KERN_INFO "Vendor/Product ID= %04x:%04x\n", em_eeprom->vendor_ID, |
369 | em_eeprom->product_ID); | |
370 | ||
371 | switch (em_eeprom->chip_conf >> 4 & 0x3) { | |
372 | case 0: | |
373 | printk(KERN_INFO "No audio on board.\n"); | |
374 | break; | |
375 | case 1: | |
376 | printk(KERN_INFO "AC97 audio (5 sample rates)\n"); | |
377 | break; | |
378 | case 2: | |
379 | printk(KERN_INFO "I2S audio, sample rate=32k\n"); | |
380 | break; | |
381 | case 3: | |
382 | printk(KERN_INFO "I2S audio, 3 sample rates\n"); | |
383 | break; | |
384 | } | |
385 | ||
386 | if (em_eeprom->chip_conf & 1 << 3) | |
387 | printk(KERN_INFO "USB Remote wakeup capable\n"); | |
388 | ||
389 | if (em_eeprom->chip_conf & 1 << 2) | |
390 | printk(KERN_INFO "USB Self power capable\n"); | |
391 | ||
392 | switch (em_eeprom->chip_conf & 0x3) { | |
393 | case 0: | |
394 | printk(KERN_INFO "500mA max power\n"); | |
395 | break; | |
396 | case 1: | |
397 | printk(KERN_INFO "400mA max power\n"); | |
398 | break; | |
399 | case 2: | |
400 | printk(KERN_INFO "300mA max power\n"); | |
401 | break; | |
402 | case 3: | |
403 | printk(KERN_INFO "200mA max power\n"); | |
404 | break; | |
405 | } | |
91cad0f2 MCC |
406 | printk(KERN_INFO "Table at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", |
407 | em_eeprom->string_idx_table,em_eeprom->string1, | |
408 | em_eeprom->string2,em_eeprom->string3); | |
a6c2ba28 | 409 | |
410 | return 0; | |
411 | } | |
412 | ||
413 | /* ----------------------------------------------------------- */ | |
414 | ||
a6c2ba28 | 415 | /* |
416 | * functionality() | |
417 | */ | |
418 | static u32 functionality(struct i2c_adapter *adap) | |
419 | { | |
420 | return I2C_FUNC_SMBUS_EMUL; | |
421 | } | |
422 | ||
a6c2ba28 | 423 | |
a6c2ba28 | 424 | /* |
425 | * attach_inform() | |
426 | * gets called when a device attaches to the i2c bus | |
427 | * does some basic configuration | |
428 | */ | |
429 | static int attach_inform(struct i2c_client *client) | |
430 | { | |
3acf2809 | 431 | struct em28xx *dev = client->adapter->algo_data; |
a6c2ba28 | 432 | |
a6c2ba28 | 433 | switch (client->addr << 1) { |
8c6da5c4 | 434 | case 0x86: |
fe51f819 MCC |
435 | case 0x84: |
436 | case 0x96: | |
437 | case 0x94: | |
15396236 | 438 | { |
7f171123 MCC |
439 | struct v4l2_priv_tun_config tda9887_cfg; |
440 | ||
15396236 MCC |
441 | struct tuner_setup tun_setup; |
442 | ||
443 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | |
444 | tun_setup.type = TUNER_TDA9887; | |
445 | tun_setup.addr = client->addr; | |
446 | ||
447 | em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup); | |
7f171123 MCC |
448 | |
449 | tda9887_cfg.tuner = TUNER_TDA9887; | |
450 | tda9887_cfg.priv = &dev->tda9887_conf; | |
451 | em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, | |
452 | &tda9887_cfg); | |
a9ae9fb1 | 453 | break; |
15396236 | 454 | } |
30556b23 MR |
455 | case 0x42: |
456 | dprintk1(1,"attach_inform: saa7114 detected.\n"); | |
457 | break; | |
a9ae9fb1 | 458 | case 0x4a: |
d5e52653 | 459 | dprintk1(1,"attach_inform: saa7113 detected.\n"); |
a9ae9fb1 MR |
460 | break; |
461 | case 0xa0: | |
d5e52653 MCC |
462 | dprintk1(1,"attach_inform: eeprom detected.\n"); |
463 | break; | |
464 | case 0x60: | |
465 | case 0x8e: | |
466 | { | |
467 | struct IR_i2c *ir = i2c_get_clientdata(client); | |
468 | dprintk1(1,"attach_inform: IR detected (%s).\n",ir->phys); | |
3acf2809 | 469 | em28xx_set_ir(dev,ir); |
a9ae9fb1 | 470 | break; |
d5e52653 | 471 | } |
a9ae9fb1 MR |
472 | case 0x80: |
473 | case 0x88: | |
d5e52653 | 474 | dprintk1(1,"attach_inform: msp34xx detected.\n"); |
a9ae9fb1 MR |
475 | break; |
476 | case 0xb8: | |
477 | case 0xba: | |
d5e52653 | 478 | dprintk1(1,"attach_inform: tvp5150 detected.\n"); |
a9ae9fb1 | 479 | break; |
15396236 | 480 | |
a9ae9fb1 | 481 | default: |
03910cc3 MCC |
482 | if (!dev->tuner_addr) |
483 | dev->tuner_addr = client->addr; | |
484 | ||
d5e52653 | 485 | dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1); |
03910cc3 | 486 | |
a6c2ba28 | 487 | } |
488 | ||
489 | return 0; | |
490 | } | |
491 | ||
3acf2809 MCC |
492 | static struct i2c_algorithm em28xx_algo = { |
493 | .master_xfer = em28xx_i2c_xfer, | |
a6c2ba28 | 494 | .functionality = functionality, |
495 | }; | |
496 | ||
3acf2809 | 497 | static struct i2c_adapter em28xx_adap_template = { |
a6c2ba28 | 498 | .owner = THIS_MODULE, |
a6c2ba28 | 499 | .class = I2C_CLASS_TV_ANALOG, |
3acf2809 MCC |
500 | .name = "em28xx", |
501 | .id = I2C_HW_B_EM28XX, | |
502 | .algo = &em28xx_algo, | |
a6c2ba28 | 503 | .client_register = attach_inform, |
504 | }; | |
505 | ||
3acf2809 MCC |
506 | static struct i2c_client em28xx_client_template = { |
507 | .name = "em28xx internal", | |
a6c2ba28 | 508 | }; |
509 | ||
510 | /* ----------------------------------------------------------- */ | |
511 | ||
512 | /* | |
513 | * i2c_devs | |
514 | * incomplete list of known devices | |
515 | */ | |
516 | static char *i2c_devs[128] = { | |
517 | [0x4a >> 1] = "saa7113h", | |
518 | [0x60 >> 1] = "remote IR sensor", | |
da45a2a5 | 519 | [0x8e >> 1] = "remote IR sensor", |
a6c2ba28 | 520 | [0x86 >> 1] = "tda9887", |
521 | [0x80 >> 1] = "msp34xx", | |
522 | [0x88 >> 1] = "msp34xx", | |
523 | [0xa0 >> 1] = "eeprom", | |
524 | [0xb8 >> 1] = "tvp5150a", | |
525 | [0xba >> 1] = "tvp5150a", | |
526 | [0xc0 >> 1] = "tuner (analog)", | |
527 | [0xc2 >> 1] = "tuner (analog)", | |
528 | [0xc4 >> 1] = "tuner (analog)", | |
529 | [0xc6 >> 1] = "tuner (analog)", | |
530 | }; | |
531 | ||
532 | /* | |
533 | * do_i2c_scan() | |
534 | * check i2c address range for devices | |
535 | */ | |
fad7b958 | 536 | void em28xx_do_i2c_scan(struct em28xx *dev) |
a6c2ba28 | 537 | { |
fad7b958 | 538 | u8 i2c_devicelist[128]; |
a6c2ba28 | 539 | unsigned char buf; |
540 | int i, rc; | |
541 | ||
fad7b958 SS |
542 | memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); |
543 | ||
53c4e955 | 544 | for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { |
fad7b958 SS |
545 | dev->i2c_client.addr = i; |
546 | rc = i2c_master_recv(&dev->i2c_client, &buf, 0); | |
a6c2ba28 | 547 | if (rc < 0) |
548 | continue; | |
fad7b958 SS |
549 | i2c_devicelist[i] = i; |
550 | printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", | |
551 | dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); | |
a6c2ba28 | 552 | } |
fad7b958 SS |
553 | |
554 | dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, | |
555 | ARRAY_SIZE(i2c_devicelist), 32); | |
a6c2ba28 | 556 | } |
557 | ||
558 | /* | |
3acf2809 | 559 | * em28xx_i2c_call_clients() |
a6c2ba28 | 560 | * send commands to all attached i2c devices |
561 | */ | |
3acf2809 | 562 | void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg) |
a6c2ba28 | 563 | { |
564 | BUG_ON(NULL == dev->i2c_adap.algo_data); | |
565 | i2c_clients_command(&dev->i2c_adap, cmd, arg); | |
566 | } | |
567 | ||
568 | /* | |
3acf2809 | 569 | * em28xx_i2c_register() |
a6c2ba28 | 570 | * register i2c bus |
571 | */ | |
3acf2809 | 572 | int em28xx_i2c_register(struct em28xx *dev) |
a6c2ba28 | 573 | { |
3acf2809 MCC |
574 | BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); |
575 | BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); | |
576 | dev->i2c_adap = em28xx_adap_template; | |
a6c2ba28 | 577 | dev->i2c_adap.dev.parent = &dev->udev->dev; |
578 | strcpy(dev->i2c_adap.name, dev->name); | |
579 | dev->i2c_adap.algo_data = dev; | |
580 | i2c_add_adapter(&dev->i2c_adap); | |
581 | ||
3acf2809 | 582 | dev->i2c_client = em28xx_client_template; |
a6c2ba28 | 583 | dev->i2c_client.adapter = &dev->i2c_adap; |
584 | ||
3acf2809 | 585 | em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); |
a6c2ba28 | 586 | |
587 | if (i2c_scan) | |
fad7b958 | 588 | em28xx_do_i2c_scan(dev); |
a6c2ba28 | 589 | return 0; |
590 | } | |
591 | ||
592 | /* | |
3acf2809 | 593 | * em28xx_i2c_unregister() |
a6c2ba28 | 594 | * unregister i2c_bus |
595 | */ | |
3acf2809 | 596 | int em28xx_i2c_unregister(struct em28xx *dev) |
a6c2ba28 | 597 | { |
598 | i2c_del_adapter(&dev->i2c_adap); | |
599 | return 0; | |
600 | } |