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: | |
1bee0184 | 405 | printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n", dev->name); |
a6c2ba28 | 406 | break; |
407 | case 3: | |
1bee0184 | 408 | printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n", dev->name); |
a6c2ba28 | 409 | break; |
410 | } | |
411 | ||
412 | if (em_eeprom->chip_conf & 1 << 3) | |
1bee0184 | 413 | printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name); |
a6c2ba28 | 414 | |
415 | if (em_eeprom->chip_conf & 1 << 2) | |
1bee0184 | 416 | printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name); |
a6c2ba28 | 417 | |
418 | switch (em_eeprom->chip_conf & 0x3) { | |
419 | case 0: | |
1bee0184 | 420 | printk(KERN_INFO "%s:\t500mA max power\n", dev->name); |
a6c2ba28 | 421 | break; |
422 | case 1: | |
1bee0184 | 423 | printk(KERN_INFO "%s:\t400mA max power\n", dev->name); |
a6c2ba28 | 424 | break; |
425 | case 2: | |
1bee0184 | 426 | printk(KERN_INFO "%s:\t300mA max power\n", dev->name); |
a6c2ba28 | 427 | break; |
428 | case 3: | |
1bee0184 | 429 | printk(KERN_INFO "%s:\t200mA max power\n", dev->name); |
a6c2ba28 | 430 | break; |
431 | } | |
1bee0184 MCC |
432 | printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", |
433 | dev->name, | |
6ea54d93 DSL |
434 | em_eeprom->string_idx_table, |
435 | em_eeprom->string1, | |
436 | em_eeprom->string2, | |
437 | em_eeprom->string3); | |
a6c2ba28 | 438 | |
439 | return 0; | |
440 | } | |
441 | ||
442 | /* ----------------------------------------------------------- */ | |
443 | ||
a6c2ba28 | 444 | /* |
445 | * functionality() | |
446 | */ | |
447 | static u32 functionality(struct i2c_adapter *adap) | |
448 | { | |
449 | return I2C_FUNC_SMBUS_EMUL; | |
450 | } | |
451 | ||
a6c2ba28 | 452 | /* |
453 | * attach_inform() | |
454 | * gets called when a device attaches to the i2c bus | |
455 | * does some basic configuration | |
456 | */ | |
457 | static int attach_inform(struct i2c_client *client) | |
458 | { | |
3acf2809 | 459 | struct em28xx *dev = client->adapter->algo_data; |
a6c2ba28 | 460 | |
a6c2ba28 | 461 | switch (client->addr << 1) { |
6ea54d93 DSL |
462 | case 0x86: |
463 | case 0x84: | |
464 | case 0x96: | |
465 | case 0x94: | |
466 | { | |
467 | struct v4l2_priv_tun_config tda9887_cfg; | |
468 | ||
469 | struct tuner_setup tun_setup; | |
470 | ||
471 | tun_setup.mode_mask = T_ANALOG_TV | T_RADIO; | |
472 | tun_setup.type = TUNER_TDA9887; | |
473 | tun_setup.addr = client->addr; | |
474 | ||
475 | em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, | |
476 | &tun_setup); | |
477 | ||
478 | tda9887_cfg.tuner = TUNER_TDA9887; | |
479 | tda9887_cfg.priv = &dev->tda9887_conf; | |
480 | em28xx_i2c_call_clients(dev, TUNER_SET_CONFIG, | |
481 | &tda9887_cfg); | |
482 | break; | |
483 | } | |
484 | case 0x42: | |
485 | dprintk1(1, "attach_inform: saa7114 detected.\n"); | |
486 | break; | |
487 | case 0x4a: | |
488 | dprintk1(1, "attach_inform: saa7113 detected.\n"); | |
489 | break; | |
490 | case 0xa0: | |
491 | dprintk1(1, "attach_inform: eeprom detected.\n"); | |
492 | break; | |
493 | case 0x60: | |
494 | case 0x8e: | |
495 | { | |
496 | struct IR_i2c *ir = i2c_get_clientdata(client); | |
497 | dprintk1(1, "attach_inform: IR detected (%s).\n", | |
498 | ir->phys); | |
499 | em28xx_set_ir(dev, ir); | |
500 | break; | |
501 | } | |
502 | case 0x80: | |
503 | case 0x88: | |
504 | dprintk1(1, "attach_inform: msp34xx detected.\n"); | |
505 | break; | |
506 | case 0xb8: | |
507 | case 0xba: | |
508 | dprintk1(1, "attach_inform: tvp5150 detected.\n"); | |
509 | break; | |
510 | ||
511 | default: | |
512 | if (!dev->tuner_addr) | |
513 | dev->tuner_addr = client->addr; | |
514 | ||
515 | dprintk1(1, "attach inform: detected I2C address %x\n", | |
516 | client->addr << 1); | |
03910cc3 | 517 | |
a6c2ba28 | 518 | } |
519 | ||
520 | return 0; | |
521 | } | |
522 | ||
3acf2809 MCC |
523 | static struct i2c_algorithm em28xx_algo = { |
524 | .master_xfer = em28xx_i2c_xfer, | |
a6c2ba28 | 525 | .functionality = functionality, |
526 | }; | |
527 | ||
3acf2809 | 528 | static struct i2c_adapter em28xx_adap_template = { |
a6c2ba28 | 529 | .owner = THIS_MODULE, |
a6c2ba28 | 530 | .class = I2C_CLASS_TV_ANALOG, |
3acf2809 MCC |
531 | .name = "em28xx", |
532 | .id = I2C_HW_B_EM28XX, | |
533 | .algo = &em28xx_algo, | |
a6c2ba28 | 534 | .client_register = attach_inform, |
535 | }; | |
536 | ||
3acf2809 MCC |
537 | static struct i2c_client em28xx_client_template = { |
538 | .name = "em28xx internal", | |
a6c2ba28 | 539 | }; |
540 | ||
541 | /* ----------------------------------------------------------- */ | |
542 | ||
543 | /* | |
544 | * i2c_devs | |
545 | * incomplete list of known devices | |
546 | */ | |
547 | static char *i2c_devs[128] = { | |
548 | [0x4a >> 1] = "saa7113h", | |
549 | [0x60 >> 1] = "remote IR sensor", | |
da45a2a5 | 550 | [0x8e >> 1] = "remote IR sensor", |
a6c2ba28 | 551 | [0x86 >> 1] = "tda9887", |
552 | [0x80 >> 1] = "msp34xx", | |
553 | [0x88 >> 1] = "msp34xx", | |
554 | [0xa0 >> 1] = "eeprom", | |
555 | [0xb8 >> 1] = "tvp5150a", | |
556 | [0xba >> 1] = "tvp5150a", | |
557 | [0xc0 >> 1] = "tuner (analog)", | |
558 | [0xc2 >> 1] = "tuner (analog)", | |
559 | [0xc4 >> 1] = "tuner (analog)", | |
560 | [0xc6 >> 1] = "tuner (analog)", | |
561 | }; | |
562 | ||
563 | /* | |
564 | * do_i2c_scan() | |
565 | * check i2c address range for devices | |
566 | */ | |
fad7b958 | 567 | void em28xx_do_i2c_scan(struct em28xx *dev) |
a6c2ba28 | 568 | { |
fad7b958 | 569 | u8 i2c_devicelist[128]; |
a6c2ba28 | 570 | unsigned char buf; |
571 | int i, rc; | |
572 | ||
fad7b958 SS |
573 | memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); |
574 | ||
53c4e955 | 575 | for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { |
fad7b958 SS |
576 | dev->i2c_client.addr = i; |
577 | rc = i2c_master_recv(&dev->i2c_client, &buf, 0); | |
a6c2ba28 | 578 | if (rc < 0) |
579 | continue; | |
fad7b958 SS |
580 | i2c_devicelist[i] = i; |
581 | printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n", | |
582 | dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); | |
a6c2ba28 | 583 | } |
fad7b958 SS |
584 | |
585 | dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, | |
586 | ARRAY_SIZE(i2c_devicelist), 32); | |
a6c2ba28 | 587 | } |
588 | ||
589 | /* | |
3acf2809 | 590 | * em28xx_i2c_call_clients() |
a6c2ba28 | 591 | * send commands to all attached i2c devices |
592 | */ | |
3acf2809 | 593 | void em28xx_i2c_call_clients(struct em28xx *dev, unsigned int cmd, void *arg) |
a6c2ba28 | 594 | { |
595 | BUG_ON(NULL == dev->i2c_adap.algo_data); | |
596 | i2c_clients_command(&dev->i2c_adap, cmd, arg); | |
597 | } | |
598 | ||
599 | /* | |
3acf2809 | 600 | * em28xx_i2c_register() |
a6c2ba28 | 601 | * register i2c bus |
602 | */ | |
3acf2809 | 603 | int em28xx_i2c_register(struct em28xx *dev) |
a6c2ba28 | 604 | { |
f2a01a00 DSL |
605 | int retval; |
606 | ||
3acf2809 MCC |
607 | BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); |
608 | BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); | |
609 | dev->i2c_adap = em28xx_adap_template; | |
a6c2ba28 | 610 | dev->i2c_adap.dev.parent = &dev->udev->dev; |
611 | strcpy(dev->i2c_adap.name, dev->name); | |
612 | dev->i2c_adap.algo_data = dev; | |
f2a01a00 DSL |
613 | |
614 | retval = i2c_add_adapter(&dev->i2c_adap); | |
615 | if (retval < 0) { | |
616 | em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", | |
617 | __func__, retval); | |
618 | return retval; | |
619 | } | |
a6c2ba28 | 620 | |
3acf2809 | 621 | dev->i2c_client = em28xx_client_template; |
a6c2ba28 | 622 | dev->i2c_client.adapter = &dev->i2c_adap; |
623 | ||
f2a01a00 | 624 | retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata)); |
c41109fc | 625 | if ((retval < 0) && (retval != -ENODEV)) { |
f2a01a00 DSL |
626 | em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", |
627 | __func__, retval); | |
c41109fc | 628 | |
f2a01a00 DSL |
629 | return retval; |
630 | } | |
a6c2ba28 | 631 | |
632 | if (i2c_scan) | |
fad7b958 | 633 | em28xx_do_i2c_scan(dev); |
c41109fc | 634 | |
a6c2ba28 | 635 | return 0; |
636 | } | |
637 | ||
638 | /* | |
3acf2809 | 639 | * em28xx_i2c_unregister() |
a6c2ba28 | 640 | * unregister i2c_bus |
641 | */ | |
3acf2809 | 642 | int em28xx_i2c_unregister(struct em28xx *dev) |
a6c2ba28 | 643 | { |
644 | i2c_del_adapter(&dev->i2c_adap); | |
645 | return 0; | |
646 | } |