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 | |
f7abcd38 | 29 | #include "em28xx.h" |
6c362c8e | 30 | #include "tuner-xc2028.h" |
5e453dc7 | 31 | #include <media/v4l2-common.h> |
d5e52653 | 32 | #include <media/tuner.h> |
a6c2ba28 | 33 | |
34 | /* ----------------------------------------------------------- */ | |
35 | ||
ff699e6b | 36 | static unsigned int i2c_scan; |
a6c2ba28 | 37 | module_param(i2c_scan, int, 0444); |
38 | MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time"); | |
39 | ||
ff699e6b | 40 | static unsigned int i2c_debug; |
a6c2ba28 | 41 | module_param(i2c_debug, int, 0644); |
42 | MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]"); | |
43 | ||
6ea54d93 DSL |
44 | |
45 | #define dprintk1(lvl, fmt, args...) \ | |
46 | do { \ | |
47 | if (i2c_debug >= lvl) { \ | |
48 | printk(fmt, ##args); \ | |
49 | } \ | |
50 | } while (0) | |
51 | ||
52 | #define dprintk2(lvl, fmt, args...) \ | |
53 | do { \ | |
54 | if (i2c_debug >= lvl) { \ | |
55 | printk(KERN_DEBUG "%s at %s: " fmt, \ | |
56 | dev->name, __func__ , ##args); \ | |
57 | } \ | |
58 | } while (0) | |
a6c2ba28 | 59 | |
60 | /* | |
596d92d5 MCC |
61 | * em2800_i2c_send_max4() |
62 | * send up to 4 bytes to the i2c device | |
63 | */ | |
3acf2809 | 64 | static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr, |
596d92d5 MCC |
65 | char *buf, int len) |
66 | { | |
67 | int ret; | |
68 | int write_timeout; | |
69 | unsigned char b2[6]; | |
70 | BUG_ON(len < 1 || len > 4); | |
71 | b2[5] = 0x80 + len - 1; | |
72 | b2[4] = addr; | |
73 | b2[3] = buf[0]; | |
74 | if (len > 1) | |
75 | b2[2] = buf[1]; | |
76 | if (len > 2) | |
77 | b2[1] = buf[2]; | |
78 | if (len > 3) | |
79 | b2[0] = buf[3]; | |
80 | ||
3acf2809 | 81 | ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); |
596d92d5 | 82 | if (ret != 2 + len) { |
beb7dd86 | 83 | em28xx_warn("writing to i2c device failed (error=%i)\n", ret); |
596d92d5 MCC |
84 | return -EIO; |
85 | } | |
86 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; | |
87 | write_timeout -= 5) { | |
3acf2809 | 88 | ret = dev->em28xx_read_reg(dev, 0x05); |
596d92d5 MCC |
89 | if (ret == 0x80 + len - 1) |
90 | return len; | |
e8e41da4 | 91 | msleep(5); |
596d92d5 | 92 | } |
3acf2809 | 93 | em28xx_warn("i2c write timed out\n"); |
596d92d5 MCC |
94 | return -EIO; |
95 | } | |
96 | ||
97 | /* | |
98 | * em2800_i2c_send_bytes() | |
99 | */ | |
100 | static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf, | |
101 | short len) | |
102 | { | |
103 | char *bufPtr = buf; | |
104 | int ret; | |
105 | int wrcount = 0; | |
106 | int count; | |
107 | int maxLen = 4; | |
3acf2809 | 108 | struct em28xx *dev = (struct em28xx *)data; |
596d92d5 MCC |
109 | while (len > 0) { |
110 | count = (len > maxLen) ? maxLen : len; | |
111 | ret = em2800_i2c_send_max4(dev, addr, bufPtr, count); | |
112 | if (ret > 0) { | |
113 | len -= count; | |
114 | bufPtr += count; | |
115 | wrcount += count; | |
116 | } else | |
117 | return (ret < 0) ? ret : -EFAULT; | |
118 | } | |
119 | return wrcount; | |
120 | } | |
121 | ||
122 | /* | |
123 | * em2800_i2c_check_for_device() | |
124 | * check if there is a i2c_device at the supplied address | |
125 | */ | |
3acf2809 | 126 | static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr) |
596d92d5 MCC |
127 | { |
128 | char msg; | |
129 | int ret; | |
130 | int write_timeout; | |
131 | msg = addr; | |
3acf2809 | 132 | ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1); |
596d92d5 | 133 | if (ret < 0) { |
3acf2809 | 134 | em28xx_warn("setting i2c device address failed (error=%i)\n", |
596d92d5 MCC |
135 | ret); |
136 | return ret; | |
137 | } | |
138 | msg = 0x84; | |
3acf2809 | 139 | ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1); |
596d92d5 | 140 | if (ret < 0) { |
3acf2809 | 141 | em28xx_warn("preparing i2c read failed (error=%i)\n", ret); |
596d92d5 MCC |
142 | return ret; |
143 | } | |
144 | for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0; | |
145 | write_timeout -= 5) { | |
d45b9b8a HV |
146 | unsigned reg = dev->em28xx_read_reg(dev, 0x5); |
147 | ||
148 | if (reg == 0x94) | |
596d92d5 | 149 | return -ENODEV; |
d45b9b8a | 150 | else if (reg == 0x84) |
596d92d5 | 151 | return 0; |
e8e41da4 | 152 | msleep(5); |
596d92d5 MCC |
153 | } |
154 | return -ENODEV; | |
155 | } | |
156 | ||
157 | /* | |
158 | * em2800_i2c_recv_bytes() | |
159 | * read from the i2c device | |
160 | */ | |
3acf2809 | 161 | static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, |
596d92d5 MCC |
162 | char *buf, int len) |
163 | { | |
164 | int ret; | |
165 | /* check for the device and set i2c read address */ | |
166 | ret = em2800_i2c_check_for_device(dev, addr); | |
167 | if (ret) { | |
3acf2809 | 168 | em28xx_warn |
596d92d5 MCC |
169 | ("preparing read at i2c address 0x%x failed (error=%i)\n", |
170 | addr, ret); | |
171 | return ret; | |
172 | } | |
3acf2809 | 173 | ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len); |
596d92d5 | 174 | if (ret < 0) { |
3acf2809 | 175 | em28xx_warn("reading from i2c device at 0x%x failed (error=%i)", |
596d92d5 MCC |
176 | addr, ret); |
177 | return ret; | |
178 | } | |
179 | return ret; | |
180 | } | |
181 | ||
182 | /* | |
3acf2809 | 183 | * em28xx_i2c_send_bytes() |
a6c2ba28 | 184 | * untested for more than 4 bytes |
185 | */ | |
3acf2809 | 186 | static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf, |
596d92d5 | 187 | short len, int stop) |
a6c2ba28 | 188 | { |
189 | int wrcount = 0; | |
3acf2809 | 190 | struct em28xx *dev = (struct em28xx *)data; |
a6c2ba28 | 191 | |
3acf2809 | 192 | wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); |
a6c2ba28 | 193 | |
194 | return wrcount; | |
195 | } | |
196 | ||
197 | /* | |
3acf2809 | 198 | * em28xx_i2c_recv_bytes() |
a6c2ba28 | 199 | * read a byte from the i2c device |
200 | */ | |
3acf2809 | 201 | static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr, |
596d92d5 | 202 | char *buf, int len) |
a6c2ba28 | 203 | { |
204 | int ret; | |
3acf2809 | 205 | ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); |
a6c2ba28 | 206 | if (ret < 0) { |
3acf2809 | 207 | em28xx_warn("reading i2c device failed (error=%i)\n", ret); |
a6c2ba28 | 208 | return ret; |
209 | } | |
3acf2809 | 210 | if (dev->em28xx_read_reg(dev, 0x5) != 0) |
a6c2ba28 | 211 | return -ENODEV; |
212 | return ret; | |
213 | } | |
214 | ||
215 | /* | |
3acf2809 | 216 | * em28xx_i2c_check_for_device() |
a6c2ba28 | 217 | * check if there is a i2c_device at the supplied address |
218 | */ | |
3acf2809 | 219 | static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr) |
a6c2ba28 | 220 | { |
221 | char msg; | |
222 | int ret; | |
223 | msg = addr; | |
224 | ||
3acf2809 | 225 | ret = dev->em28xx_read_reg_req(dev, 2, addr); |
a6c2ba28 | 226 | if (ret < 0) { |
3acf2809 | 227 | em28xx_warn("reading from i2c device failed (error=%i)\n", ret); |
a6c2ba28 | 228 | return ret; |
229 | } | |
3acf2809 | 230 | if (dev->em28xx_read_reg(dev, 0x5) != 0) |
a6c2ba28 | 231 | return -ENODEV; |
232 | return 0; | |
233 | } | |
234 | ||
235 | /* | |
3acf2809 | 236 | * em28xx_i2c_xfer() |
a6c2ba28 | 237 | * the main i2c transfer function |
238 | */ | |
3acf2809 | 239 | static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, |
a6c2ba28 | 240 | struct i2c_msg msgs[], int num) |
241 | { | |
3acf2809 | 242 | struct em28xx *dev = i2c_adap->algo_data; |
a6c2ba28 | 243 | int addr, rc, i, byte; |
244 | ||
245 | if (num <= 0) | |
246 | return 0; | |
247 | for (i = 0; i < num; i++) { | |
248 | addr = msgs[i].addr << 1; | |
6ea54d93 | 249 | dprintk2(2, "%s %s addr=%x len=%d:", |
a6c2ba28 | 250 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", |
251 | i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len); | |
6ea54d93 | 252 | if (!msgs[i].len) { /* no len: check only for device presence */ |
505b6d0b | 253 | if (dev->board.is_em2800) |
596d92d5 MCC |
254 | rc = em2800_i2c_check_for_device(dev, addr); |
255 | else | |
3acf2809 | 256 | rc = em28xx_i2c_check_for_device(dev, addr); |
a6c2ba28 | 257 | if (rc < 0) { |
6ea54d93 | 258 | dprintk2(2, " no device\n"); |
a6c2ba28 | 259 | return rc; |
260 | } | |
261 | ||
596d92d5 | 262 | } else if (msgs[i].flags & I2C_M_RD) { |
a6c2ba28 | 263 | /* read bytes */ |
505b6d0b | 264 | if (dev->board.is_em2800) |
596d92d5 MCC |
265 | rc = em2800_i2c_recv_bytes(dev, addr, |
266 | msgs[i].buf, | |
267 | msgs[i].len); | |
268 | else | |
3acf2809 | 269 | rc = em28xx_i2c_recv_bytes(dev, addr, |
596d92d5 MCC |
270 | msgs[i].buf, |
271 | msgs[i].len); | |
6ea54d93 DSL |
272 | if (i2c_debug >= 2) { |
273 | for (byte = 0; byte < msgs[i].len; byte++) | |
a6c2ba28 | 274 | printk(" %02x", msgs[i].buf[byte]); |
a6c2ba28 | 275 | } |
276 | } else { | |
277 | /* write bytes */ | |
6ea54d93 | 278 | if (i2c_debug >= 2) { |
a6c2ba28 | 279 | for (byte = 0; byte < msgs[i].len; byte++) |
280 | printk(" %02x", msgs[i].buf[byte]); | |
281 | } | |
505b6d0b | 282 | if (dev->board.is_em2800) |
596d92d5 MCC |
283 | rc = em2800_i2c_send_bytes(dev, addr, |
284 | msgs[i].buf, | |
285 | msgs[i].len); | |
286 | else | |
3acf2809 | 287 | rc = em28xx_i2c_send_bytes(dev, addr, |
596d92d5 MCC |
288 | msgs[i].buf, |
289 | msgs[i].len, | |
290 | i == num - 1); | |
a6c2ba28 | 291 | } |
e8e41da4 MR |
292 | if (rc < 0) |
293 | goto err; | |
6ea54d93 | 294 | if (i2c_debug >= 2) |
a6c2ba28 | 295 | printk("\n"); |
296 | } | |
297 | ||
298 | return num; | |
6ea54d93 DSL |
299 | err: |
300 | dprintk2(2, " ERROR: %i\n", rc); | |
a6c2ba28 | 301 | return rc; |
302 | } | |
303 | ||
03910cc3 MCC |
304 | /* based on linux/sunrpc/svcauth.h and linux/hash.h |
305 | * The original hash function returns a different value, if arch is x86_64 | |
306 | * or i386. | |
307 | */ | |
308 | static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits) | |
309 | { | |
310 | unsigned long hash = 0; | |
311 | unsigned long l = 0; | |
312 | int len = 0; | |
313 | unsigned char c; | |
314 | do { | |
315 | if (len == length) { | |
316 | c = (char)len; | |
317 | len = -1; | |
318 | } else | |
319 | c = *buf++; | |
320 | l = (l << 8) | c; | |
321 | len++; | |
322 | if ((len & (32 / 8 - 1)) == 0) | |
323 | hash = ((hash^l) * 0x9e370001UL); | |
324 | } while (len); | |
325 | ||
326 | return (hash >> (32 - bits)) & 0xffffffffUL; | |
327 | } | |
328 | ||
3acf2809 | 329 | static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) |
a6c2ba28 | 330 | { |
331 | unsigned char buf, *p = eedata; | |
3acf2809 | 332 | struct em28xx_eeprom *em_eeprom = (void *)eedata; |
a6c2ba28 | 333 | int i, err, size = len, block; |
334 | ||
a527c9f8 DH |
335 | if (dev->chip_id == CHIP_ID_EM2874) { |
336 | /* Empia switched to a 16-bit addressable eeprom in newer | |
337 | devices. While we could certainly write a routine to read | |
338 | the eeprom, there is nothing of use in there that cannot be | |
339 | accessed through registers, and there is the risk that we | |
340 | could corrupt the eeprom (since a 16-bit read call is | |
341 | interpreted as a write call by 8-bit eeproms). | |
342 | */ | |
343 | return 0; | |
344 | } | |
345 | ||
a6c2ba28 | 346 | dev->i2c_client.addr = 0xa0 >> 1; |
596d92d5 MCC |
347 | |
348 | /* Check if board has eeprom */ | |
349 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); | |
f2a01a00 | 350 | if (err < 0) { |
c41109fc MCC |
351 | em28xx_errdev("board has no eeprom\n"); |
352 | memset(eedata, 0, len); | |
353 | return -ENODEV; | |
f2a01a00 | 354 | } |
596d92d5 | 355 | |
a6c2ba28 | 356 | buf = 0; |
6ea54d93 DSL |
357 | |
358 | err = i2c_master_send(&dev->i2c_client, &buf, 1); | |
359 | if (err != 1) { | |
a6c2ba28 | 360 | printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n", |
361 | dev->name, err); | |
f2a01a00 | 362 | return err; |
a6c2ba28 | 363 | } |
364 | while (size > 0) { | |
365 | if (size > 16) | |
366 | block = 16; | |
367 | else | |
368 | block = size; | |
369 | ||
370 | if (block != | |
371 | (err = i2c_master_recv(&dev->i2c_client, p, block))) { | |
372 | printk(KERN_WARNING | |
373 | "%s: i2c eeprom read error (err=%d)\n", | |
374 | dev->name, err); | |
f2a01a00 | 375 | return err; |
a6c2ba28 | 376 | } |
377 | size -= block; | |
378 | p += block; | |
379 | } | |
380 | for (i = 0; i < len; i++) { | |
381 | if (0 == (i % 16)) | |
382 | printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i); | |
383 | printk(" %02x", eedata[i]); | |
384 | if (15 == (i % 16)) | |
385 | printk("\n"); | |
386 | } | |
387 | ||
03910cc3 MCC |
388 | if (em_eeprom->id == 0x9567eb1a) |
389 | dev->hash = em28xx_hash_mem(eedata, len, 32); | |
390 | ||
1bee0184 MCC |
391 | printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n", |
392 | dev->name, em_eeprom->id, dev->hash); | |
393 | ||
394 | printk(KERN_INFO "%s: EEPROM info:\n", dev->name); | |
a6c2ba28 | 395 | |
396 | switch (em_eeprom->chip_conf >> 4 & 0x3) { | |
397 | case 0: | |
1bee0184 | 398 | printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name); |
a6c2ba28 | 399 | break; |
400 | case 1: | |
1bee0184 MCC |
401 | printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n", |
402 | dev->name); | |
a6c2ba28 | 403 | break; |
404 | case 2: | |
a1a6ee74 NS |
405 | printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", |
406 | dev->name); | |
a6c2ba28 | 407 | break; |
408 | case 3: | |
a1a6ee74 NS |
409 | printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", |
410 | dev->name); | |
a6c2ba28 | 411 | break; |
412 | } | |
413 | ||
414 | if (em_eeprom->chip_conf & 1 << 3) | |
1bee0184 | 415 | printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name); |
a6c2ba28 | 416 | |
417 | if (em_eeprom->chip_conf & 1 << 2) | |
1bee0184 | 418 | printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name); |
a6c2ba28 | 419 | |
420 | switch (em_eeprom->chip_conf & 0x3) { | |
421 | case 0: | |
1bee0184 | 422 | printk(KERN_INFO "%s:\t500mA max power\n", dev->name); |
a6c2ba28 | 423 | break; |
424 | case 1: | |
1bee0184 | 425 | printk(KERN_INFO "%s:\t400mA max power\n", dev->name); |
a6c2ba28 | 426 | break; |
427 | case 2: | |
1bee0184 | 428 | printk(KERN_INFO "%s:\t300mA max power\n", dev->name); |
a6c2ba28 | 429 | break; |
430 | case 3: | |
1bee0184 | 431 | printk(KERN_INFO "%s:\t200mA max power\n", dev->name); |
a6c2ba28 | 432 | break; |
433 | } | |
1bee0184 MCC |
434 | printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", |
435 | dev->name, | |
6ea54d93 DSL |
436 | em_eeprom->string_idx_table, |
437 | em_eeprom->string1, | |
438 | em_eeprom->string2, | |
439 | em_eeprom->string3); | |
a6c2ba28 | 440 | |
441 | return 0; | |
442 | } | |
443 | ||
444 | /* ----------------------------------------------------------- */ | |
445 | ||
a6c2ba28 | 446 | /* |
447 | * functionality() | |
448 | */ | |
449 | static u32 functionality(struct i2c_adapter *adap) | |
450 | { | |
451 | return I2C_FUNC_SMBUS_EMUL; | |
452 | } | |
453 | ||
3acf2809 MCC |
454 | static struct i2c_algorithm em28xx_algo = { |
455 | .master_xfer = em28xx_i2c_xfer, | |
a6c2ba28 | 456 | .functionality = functionality, |
457 | }; | |
458 | ||
3acf2809 | 459 | static struct i2c_adapter em28xx_adap_template = { |
a6c2ba28 | 460 | .owner = THIS_MODULE, |
3acf2809 | 461 | .name = "em28xx", |
3acf2809 | 462 | .algo = &em28xx_algo, |
a6c2ba28 | 463 | }; |
464 | ||
3acf2809 MCC |
465 | static struct i2c_client em28xx_client_template = { |
466 | .name = "em28xx internal", | |
a6c2ba28 | 467 | }; |
468 | ||
469 | /* ----------------------------------------------------------- */ | |
470 | ||
471 | /* | |
472 | * i2c_devs | |
473 | * incomplete list of known devices | |
474 | */ | |
475 | static char *i2c_devs[128] = { | |
476 | [0x4a >> 1] = "saa7113h", | |
477 | [0x60 >> 1] = "remote IR sensor", | |
da45a2a5 | 478 | [0x8e >> 1] = "remote IR sensor", |
a6c2ba28 | 479 | [0x86 >> 1] = "tda9887", |
480 | [0x80 >> 1] = "msp34xx", | |
481 | [0x88 >> 1] = "msp34xx", | |
482 | [0xa0 >> 1] = "eeprom", | |
2bd1d9eb | 483 | [0xb0 >> 1] = "tda9874", |
a6c2ba28 | 484 | [0xb8 >> 1] = "tvp5150a", |
791a08fc | 485 | [0xba >> 1] = "webcam sensor or tvp5150a", |
a6c2ba28 | 486 | [0xc0 >> 1] = "tuner (analog)", |
487 | [0xc2 >> 1] = "tuner (analog)", | |
488 | [0xc4 >> 1] = "tuner (analog)", | |
489 | [0xc6 >> 1] = "tuner (analog)", | |
490 | }; | |
491 | ||
492 | /* | |
493 | * do_i2c_scan() | |
494 | * check i2c address range for devices | |
495 | */ | |
fad7b958 | 496 | void em28xx_do_i2c_scan(struct em28xx *dev) |
a6c2ba28 | 497 | { |
fad7b958 | 498 | u8 i2c_devicelist[128]; |
a6c2ba28 | 499 | unsigned char buf; |
500 | int i, rc; | |
501 | ||
fad7b958 SS |
502 | memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); |
503 | ||
53c4e955 | 504 | for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { |
fad7b958 SS |
505 | dev->i2c_client.addr = i; |
506 | rc = i2c_master_recv(&dev->i2c_client, &buf, 0); | |
a6c2ba28 | 507 | if (rc < 0) |
508 | continue; | |
fad7b958 SS |
509 | i2c_devicelist[i] = i; |
510 | printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", | |
511 | dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); | |
a6c2ba28 | 512 | } |
fad7b958 SS |
513 | |
514 | dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, | |
515 | ARRAY_SIZE(i2c_devicelist), 32); | |
a6c2ba28 | 516 | } |
517 | ||
a6c2ba28 | 518 | /* |
3acf2809 | 519 | * em28xx_i2c_register() |
a6c2ba28 | 520 | * register i2c bus |
521 | */ | |
3acf2809 | 522 | int em28xx_i2c_register(struct em28xx *dev) |
a6c2ba28 | 523 | { |
f2a01a00 DSL |
524 | int retval; |
525 | ||
3acf2809 MCC |
526 | BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); |
527 | BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); | |
528 | dev->i2c_adap = em28xx_adap_template; | |
a6c2ba28 | 529 | dev->i2c_adap.dev.parent = &dev->udev->dev; |
530 | strcpy(dev->i2c_adap.name, dev->name); | |
531 | dev->i2c_adap.algo_data = dev; | |
f2cf250a | 532 | i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); |
f2a01a00 DSL |
533 | |
534 | retval = i2c_add_adapter(&dev->i2c_adap); | |
535 | if (retval < 0) { | |
536 | em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", | |
537 | __func__, retval); | |
538 | return retval; | |
539 | } | |
a6c2ba28 | 540 | |
3acf2809 | 541 | dev->i2c_client = em28xx_client_template; |
a6c2ba28 | 542 | dev->i2c_client.adapter = &dev->i2c_adap; |
543 | ||
f2a01a00 | 544 | retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); |
c41109fc | 545 | if ((retval < 0) && (retval != -ENODEV)) { |
f2a01a00 DSL |
546 | em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", |
547 | __func__, retval); | |
c41109fc | 548 | |
f2a01a00 DSL |
549 | return retval; |
550 | } | |
a6c2ba28 | 551 | |
552 | if (i2c_scan) | |
fad7b958 | 553 | em28xx_do_i2c_scan(dev); |
c41109fc | 554 | |
c668f32d JD |
555 | /* Instantiate the IR receiver device, if present */ |
556 | em28xx_register_i2c_ir(dev); | |
557 | ||
a6c2ba28 | 558 | return 0; |
559 | } | |
560 | ||
561 | /* | |
3acf2809 | 562 | * em28xx_i2c_unregister() |
a6c2ba28 | 563 | * unregister i2c_bus |
564 | */ | |
3acf2809 | 565 | int em28xx_i2c_unregister(struct em28xx *dev) |
a6c2ba28 | 566 | { |
567 | i2c_del_adapter(&dev->i2c_adap); | |
568 | return 0; | |
569 | } |