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 | ||
a6c2ba28 | 44 | /* |
f5ae371a FS |
45 | * em2800_i2c_send_bytes() |
46 | * send up to 4 bytes to the em2800 i2c device | |
596d92d5 | 47 | */ |
f5ae371a | 48 | static int em2800_i2c_send_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) |
596d92d5 MCC |
49 | { |
50 | int ret; | |
51 | int write_timeout; | |
a6bad040 | 52 | u8 b2[6]; |
f5ae371a FS |
53 | |
54 | if (len < 1 || len > 4) | |
55 | return -EOPNOTSUPP; | |
56 | ||
596d92d5 MCC |
57 | BUG_ON(len < 1 || len > 4); |
58 | b2[5] = 0x80 + len - 1; | |
59 | b2[4] = addr; | |
60 | b2[3] = buf[0]; | |
61 | if (len > 1) | |
62 | b2[2] = buf[1]; | |
63 | if (len > 2) | |
64 | b2[1] = buf[2]; | |
65 | if (len > 3) | |
66 | b2[0] = buf[3]; | |
67 | ||
2fcc82d8 | 68 | /* trigger write */ |
3acf2809 | 69 | ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len); |
596d92d5 | 70 | if (ret != 2 + len) { |
45f04e82 FS |
71 | em28xx_warn("failed to trigger write to i2c address 0x%x " |
72 | "(error=%i)\n", addr, ret); | |
73 | return (ret < 0) ? ret : -EIO; | |
596d92d5 | 74 | } |
2fcc82d8 FS |
75 | /* wait for completion */ |
76 | for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0; | |
596d92d5 | 77 | write_timeout -= 5) { |
3acf2809 | 78 | ret = dev->em28xx_read_reg(dev, 0x05); |
45f04e82 | 79 | if (ret == 0x80 + len - 1) { |
596d92d5 | 80 | return len; |
45f04e82 FS |
81 | } else if (ret == 0x94 + len - 1) { |
82 | return -ENODEV; | |
83 | } else if (ret < 0) { | |
84 | em28xx_warn("failed to get i2c transfer status from " | |
85 | "bridge register (error=%i)\n", ret); | |
86 | return ret; | |
87 | } | |
e8e41da4 | 88 | msleep(5); |
596d92d5 | 89 | } |
45f04e82 | 90 | em28xx_warn("write to i2c device at 0x%x timed out\n", addr); |
596d92d5 MCC |
91 | return -EIO; |
92 | } | |
93 | ||
596d92d5 | 94 | /* |
2fcc82d8 FS |
95 | * em2800_i2c_recv_bytes() |
96 | * read up to 4 bytes from the em2800 i2c device | |
596d92d5 | 97 | */ |
2fcc82d8 | 98 | static int em2800_i2c_recv_bytes(struct em28xx *dev, u8 addr, u8 *buf, u16 len) |
596d92d5 | 99 | { |
2fcc82d8 | 100 | u8 buf2[4]; |
596d92d5 | 101 | int ret; |
2fcc82d8 FS |
102 | int read_timeout; |
103 | int i; | |
104 | ||
105 | if (len < 1 || len > 4) | |
106 | return -EOPNOTSUPP; | |
107 | ||
108 | /* trigger read */ | |
109 | buf2[1] = 0x84 + len - 1; | |
110 | buf2[0] = addr; | |
111 | ret = dev->em28xx_write_regs(dev, 0x04, buf2, 2); | |
112 | if (ret != 2) { | |
113 | em28xx_warn("failed to trigger read from i2c address 0x%x " | |
114 | "(error=%i)\n", addr, ret); | |
115 | return (ret < 0) ? ret : -EIO; | |
596d92d5 | 116 | } |
d45b9b8a | 117 | |
2fcc82d8 FS |
118 | /* wait for completion */ |
119 | for (read_timeout = EM2800_I2C_XFER_TIMEOUT; read_timeout > 0; | |
120 | read_timeout -= 5) { | |
121 | ret = dev->em28xx_read_reg(dev, 0x05); | |
122 | if (ret == 0x84 + len - 1) { | |
123 | break; | |
124 | } else if (ret == 0x94 + len - 1) { | |
596d92d5 | 125 | return -ENODEV; |
2fcc82d8 FS |
126 | } else if (ret < 0) { |
127 | em28xx_warn("failed to get i2c transfer status from " | |
128 | "bridge register (error=%i)\n", ret); | |
129 | return ret; | |
130 | } | |
e8e41da4 | 131 | msleep(5); |
596d92d5 | 132 | } |
2fcc82d8 FS |
133 | if (ret != 0x84 + len - 1) |
134 | em28xx_warn("read from i2c device at 0x%x timed out\n", addr); | |
135 | ||
136 | /* get the received message */ | |
137 | ret = dev->em28xx_read_reg_req_len(dev, 0x00, 4-len, buf2, len); | |
138 | if (ret != len) { | |
139 | em28xx_warn("reading from i2c device at 0x%x failed: " | |
140 | "couldn't get the received message from the bridge " | |
141 | "(error=%i)\n", addr, ret); | |
142 | return (ret < 0) ? ret : -EIO; | |
143 | } | |
144 | for (i = 0; i < len; i++) | |
145 | buf[i] = buf2[len - 1 - i]; | |
146 | ||
147 | return ret; | |
596d92d5 MCC |
148 | } |
149 | ||
150 | /* | |
2fcc82d8 FS |
151 | * em2800_i2c_check_for_device() |
152 | * check if there is an i2c device at the supplied address | |
596d92d5 | 153 | */ |
2fcc82d8 | 154 | static int em2800_i2c_check_for_device(struct em28xx *dev, u8 addr) |
596d92d5 | 155 | { |
2fcc82d8 | 156 | u8 buf; |
596d92d5 | 157 | int ret; |
f5ae371a | 158 | |
2fcc82d8 FS |
159 | ret = em2800_i2c_recv_bytes(dev, addr, &buf, 1); |
160 | if (ret == 1) | |
161 | return 0; | |
162 | return (ret < 0) ? ret : -EIO; | |
596d92d5 MCC |
163 | } |
164 | ||
165 | /* | |
3acf2809 | 166 | * em28xx_i2c_send_bytes() |
a6c2ba28 | 167 | */ |
a6bad040 FS |
168 | static int em28xx_i2c_send_bytes(struct em28xx *dev, u16 addr, u8 *buf, |
169 | u16 len, int stop) | |
a6c2ba28 | 170 | { |
bbc70e64 | 171 | int write_timeout, ret; |
a6c2ba28 | 172 | |
f5ae371a FS |
173 | if (len < 1 || len > 64) |
174 | return -EOPNOTSUPP; | |
45f04e82 FS |
175 | /* NOTE: limited by the USB ctrl message constraints |
176 | * Zero length reads always succeed, even if no device is connected */ | |
f5ae371a | 177 | |
45f04e82 FS |
178 | /* Write to i2c device */ |
179 | ret = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len); | |
180 | if (ret != len) { | |
181 | if (ret < 0) { | |
182 | em28xx_warn("writing to i2c device at 0x%x failed " | |
183 | "(error=%i)\n", addr, ret); | |
184 | return ret; | |
185 | } else { | |
186 | em28xx_warn("%i bytes write to i2c device at 0x%x " | |
187 | "requested, but %i bytes written\n", | |
188 | len, addr, ret); | |
189 | return -EIO; | |
190 | } | |
191 | } | |
a6c2ba28 | 192 | |
45f04e82 | 193 | /* Check success of the i2c operation */ |
2fcc82d8 | 194 | for (write_timeout = EM2800_I2C_XFER_TIMEOUT; write_timeout > 0; |
bbc70e64 MCC |
195 | write_timeout -= 5) { |
196 | ret = dev->em28xx_read_reg(dev, 0x05); | |
45f04e82 FS |
197 | if (ret == 0) { /* success */ |
198 | return len; | |
199 | } else if (ret == 0x10) { | |
200 | return -ENODEV; | |
201 | } else if (ret < 0) { | |
202 | em28xx_warn("failed to read i2c transfer status from " | |
203 | "bridge (error=%i)\n", ret); | |
204 | return ret; | |
205 | } | |
bbc70e64 | 206 | msleep(5); |
45f04e82 FS |
207 | /* NOTE: do we really have to wait for success ? |
208 | Never seen anything else than 0x00 or 0x10 | |
209 | (even with high payload) ... */ | |
bbc70e64 | 210 | } |
45f04e82 FS |
211 | em28xx_warn("write to i2c device at 0x%x timed out\n", addr); |
212 | return -EIO; | |
a6c2ba28 | 213 | } |
214 | ||
215 | /* | |
3acf2809 | 216 | * em28xx_i2c_recv_bytes() |
a6c2ba28 | 217 | * read a byte from the i2c device |
218 | */ | |
a6bad040 | 219 | static int em28xx_i2c_recv_bytes(struct em28xx *dev, u16 addr, u8 *buf, u16 len) |
a6c2ba28 | 220 | { |
221 | int ret; | |
f5ae371a FS |
222 | |
223 | if (len < 1 || len > 64) | |
224 | return -EOPNOTSUPP; | |
45f04e82 FS |
225 | /* NOTE: limited by the USB ctrl message constraints |
226 | * Zero length reads always succeed, even if no device is connected */ | |
f5ae371a | 227 | |
45f04e82 | 228 | /* Read data from i2c device */ |
3acf2809 | 229 | ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len); |
45f04e82 FS |
230 | if (ret != len) { |
231 | if (ret < 0) { | |
232 | em28xx_warn("reading from i2c device at 0x%x failed " | |
233 | "(error=%i)\n", addr, ret); | |
234 | return ret; | |
235 | } else { | |
236 | em28xx_warn("%i bytes requested from i2c device at " | |
237 | "0x%x, but %i bytes received\n", | |
238 | len, addr, ret); | |
239 | return -EIO; | |
240 | } | |
241 | } | |
242 | ||
243 | /* Check success of the i2c operation */ | |
244 | ret = dev->em28xx_read_reg(dev, 0x05); | |
a6c2ba28 | 245 | if (ret < 0) { |
45f04e82 FS |
246 | em28xx_warn("failed to read i2c transfer status from " |
247 | "bridge (error=%i)\n", ret); | |
a6c2ba28 | 248 | return ret; |
249 | } | |
45f04e82 FS |
250 | if (ret > 0) { |
251 | if (ret == 0x10) { | |
252 | return -ENODEV; | |
253 | } else { | |
254 | em28xx_warn("unknown i2c error (status=%i)\n", ret); | |
255 | return -EIO; | |
256 | } | |
257 | } | |
258 | return len; | |
a6c2ba28 | 259 | } |
260 | ||
261 | /* | |
3acf2809 | 262 | * em28xx_i2c_check_for_device() |
a6c2ba28 | 263 | * check if there is a i2c_device at the supplied address |
264 | */ | |
a6bad040 | 265 | static int em28xx_i2c_check_for_device(struct em28xx *dev, u16 addr) |
a6c2ba28 | 266 | { |
a6c2ba28 | 267 | int ret; |
45f04e82 | 268 | u8 buf; |
a6c2ba28 | 269 | |
45f04e82 FS |
270 | ret = em28xx_i2c_recv_bytes(dev, addr, &buf, 1); |
271 | if (ret == 1) | |
272 | return 0; | |
273 | return (ret < 0) ? ret : -EIO; | |
a6c2ba28 | 274 | } |
275 | ||
276 | /* | |
3acf2809 | 277 | * em28xx_i2c_xfer() |
a6c2ba28 | 278 | * the main i2c transfer function |
279 | */ | |
3acf2809 | 280 | static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap, |
a6c2ba28 | 281 | struct i2c_msg msgs[], int num) |
282 | { | |
3acf2809 | 283 | struct em28xx *dev = i2c_adap->algo_data; |
a6c2ba28 | 284 | int addr, rc, i, byte; |
285 | ||
286 | if (num <= 0) | |
287 | return 0; | |
288 | for (i = 0; i < num; i++) { | |
289 | addr = msgs[i].addr << 1; | |
d90f0677 | 290 | if (i2c_debug) |
d7a80eaa FS |
291 | printk(KERN_DEBUG "%s at %s: %s %s addr=%02x len=%d:", |
292 | dev->name, __func__ , | |
293 | (msgs[i].flags & I2C_M_RD) ? "read" : "write", | |
294 | i == num - 1 ? "stop" : "nonstop", | |
295 | addr, msgs[i].len); | |
6ea54d93 | 296 | if (!msgs[i].len) { /* no len: check only for device presence */ |
505b6d0b | 297 | if (dev->board.is_em2800) |
596d92d5 MCC |
298 | rc = em2800_i2c_check_for_device(dev, addr); |
299 | else | |
3acf2809 | 300 | rc = em28xx_i2c_check_for_device(dev, addr); |
45f04e82 | 301 | if (rc == -ENODEV) { |
d90f0677 | 302 | if (i2c_debug) |
45f04e82 | 303 | printk(" no device\n"); |
a6c2ba28 | 304 | return rc; |
305 | } | |
596d92d5 | 306 | } else if (msgs[i].flags & I2C_M_RD) { |
a6c2ba28 | 307 | /* read bytes */ |
505b6d0b | 308 | if (dev->board.is_em2800) |
596d92d5 MCC |
309 | rc = em2800_i2c_recv_bytes(dev, addr, |
310 | msgs[i].buf, | |
311 | msgs[i].len); | |
312 | else | |
3acf2809 | 313 | rc = em28xx_i2c_recv_bytes(dev, addr, |
596d92d5 MCC |
314 | msgs[i].buf, |
315 | msgs[i].len); | |
d90f0677 | 316 | if (i2c_debug) { |
6ea54d93 | 317 | for (byte = 0; byte < msgs[i].len; byte++) |
a6c2ba28 | 318 | printk(" %02x", msgs[i].buf[byte]); |
a6c2ba28 | 319 | } |
320 | } else { | |
321 | /* write bytes */ | |
d90f0677 | 322 | if (i2c_debug) { |
a6c2ba28 | 323 | for (byte = 0; byte < msgs[i].len; byte++) |
324 | printk(" %02x", msgs[i].buf[byte]); | |
325 | } | |
505b6d0b | 326 | if (dev->board.is_em2800) |
596d92d5 MCC |
327 | rc = em2800_i2c_send_bytes(dev, addr, |
328 | msgs[i].buf, | |
329 | msgs[i].len); | |
330 | else | |
3acf2809 | 331 | rc = em28xx_i2c_send_bytes(dev, addr, |
596d92d5 MCC |
332 | msgs[i].buf, |
333 | msgs[i].len, | |
334 | i == num - 1); | |
a6c2ba28 | 335 | } |
45f04e82 | 336 | if (rc < 0) { |
d90f0677 | 337 | if (i2c_debug) |
45f04e82 FS |
338 | printk(" ERROR: %i\n", rc); |
339 | return rc; | |
340 | } | |
d90f0677 | 341 | if (i2c_debug) |
a6c2ba28 | 342 | printk("\n"); |
343 | } | |
344 | ||
345 | return num; | |
a6c2ba28 | 346 | } |
347 | ||
03910cc3 MCC |
348 | /* based on linux/sunrpc/svcauth.h and linux/hash.h |
349 | * The original hash function returns a different value, if arch is x86_64 | |
350 | * or i386. | |
351 | */ | |
352 | static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits) | |
353 | { | |
354 | unsigned long hash = 0; | |
355 | unsigned long l = 0; | |
356 | int len = 0; | |
357 | unsigned char c; | |
358 | do { | |
359 | if (len == length) { | |
360 | c = (char)len; | |
361 | len = -1; | |
362 | } else | |
363 | c = *buf++; | |
364 | l = (l << 8) | c; | |
365 | len++; | |
366 | if ((len & (32 / 8 - 1)) == 0) | |
367 | hash = ((hash^l) * 0x9e370001UL); | |
368 | } while (len); | |
369 | ||
370 | return (hash >> (32 - bits)) & 0xffffffffUL; | |
371 | } | |
372 | ||
d832c5b2 FS |
373 | /* Helper function to read data blocks from i2c clients with 8 or 16 bit |
374 | * address width, 8 bit register width and auto incrementation been activated */ | |
375 | static int em28xx_i2c_read_block(struct em28xx *dev, u16 addr, bool addr_w16, | |
376 | u16 len, u8 *data) | |
377 | { | |
378 | int remain = len, rsize, rsize_max, ret; | |
379 | u8 buf[2]; | |
380 | ||
381 | /* Sanity check */ | |
382 | if (addr + remain > (addr_w16 * 0xff00 + 0xff + 1)) | |
383 | return -EINVAL; | |
384 | /* Select address */ | |
385 | buf[0] = addr >> 8; | |
386 | buf[1] = addr & 0xff; | |
387 | ret = i2c_master_send(&dev->i2c_client, buf + !addr_w16, 1 + addr_w16); | |
388 | if (ret < 0) | |
389 | return ret; | |
390 | /* Read data */ | |
391 | if (dev->board.is_em2800) | |
392 | rsize_max = 4; | |
393 | else | |
394 | rsize_max = 64; | |
395 | while (remain > 0) { | |
396 | if (remain > rsize_max) | |
397 | rsize = rsize_max; | |
398 | else | |
399 | rsize = remain; | |
400 | ||
401 | ret = i2c_master_recv(&dev->i2c_client, data, rsize); | |
402 | if (ret < 0) | |
403 | return ret; | |
404 | ||
405 | remain -= rsize; | |
406 | data += rsize; | |
407 | } | |
408 | ||
409 | return len; | |
410 | } | |
411 | ||
a217968f | 412 | static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char **eedata, int len) |
a6c2ba28 | 413 | { |
a217968f FS |
414 | u8 buf, *data; |
415 | struct em28xx_eeprom *em_eeprom; | |
d832c5b2 | 416 | int i, err; |
a6c2ba28 | 417 | |
a217968f FS |
418 | *eedata = NULL; |
419 | ||
a6c2ba28 | 420 | dev->i2c_client.addr = 0xa0 >> 1; |
596d92d5 MCC |
421 | |
422 | /* Check if board has eeprom */ | |
d832c5b2 | 423 | err = i2c_master_recv(&dev->i2c_client, &buf, 0); |
f2a01a00 | 424 | if (err < 0) { |
12d7ce18 | 425 | em28xx_info("board has no eeprom\n"); |
c41109fc | 426 | return -ENODEV; |
f2a01a00 | 427 | } |
596d92d5 | 428 | |
a217968f FS |
429 | data = kzalloc(len, GFP_KERNEL); |
430 | if (data == NULL) | |
431 | return -ENOMEM; | |
432 | ||
d832c5b2 FS |
433 | /* Read EEPROM content */ |
434 | err = em28xx_i2c_read_block(dev, 0x0000, dev->eeprom_addrwidth_16bit, | |
a217968f | 435 | len, data); |
d832c5b2 | 436 | if (err != len) { |
12d7ce18 | 437 | em28xx_errdev("failed to read eeprom (err=%d)\n", err); |
a217968f | 438 | kfree(data); |
f2a01a00 | 439 | return err; |
a6c2ba28 | 440 | } |
90271964 | 441 | |
87b52439 | 442 | /* Display eeprom content */ |
a6c2ba28 | 443 | for (i = 0; i < len; i++) { |
87b52439 FS |
444 | if (0 == (i % 16)) { |
445 | if (dev->eeprom_addrwidth_16bit) | |
446 | em28xx_info("i2c eeprom %04x:", i); | |
447 | else | |
448 | em28xx_info("i2c eeprom %02x:", i); | |
449 | } | |
a217968f | 450 | printk(" %02x", data[i]); |
a6c2ba28 | 451 | if (15 == (i % 16)) |
452 | printk("\n"); | |
453 | } | |
454 | ||
87b52439 | 455 | if (dev->eeprom_addrwidth_16bit && |
a217968f | 456 | data[0] == 0x26 && data[3] == 0x00) { |
87b52439 | 457 | /* new eeprom format; size 4-64kb */ |
a217968f | 458 | dev->hash = em28xx_hash_mem(data, len, 32); |
87b52439 FS |
459 | em28xx_info("EEPROM hash = 0x%08lx\n", dev->hash); |
460 | em28xx_info("EEPROM info: boot page address = 0x%02x04, " | |
461 | "boot configuration = 0x%02x\n", | |
a217968f | 462 | data[1], data[2]); |
87b52439 FS |
463 | /* boot configuration (address 0x0002): |
464 | * [0] microcode download speed: 1 = 400 kHz; 0 = 100 kHz | |
465 | * [1] always selects 12 kb RAM | |
466 | * [2] USB device speed: 1 = force Full Speed; 0 = auto detect | |
467 | * [4] 1 = force fast mode and no suspend for device testing | |
468 | * [5:7] USB PHY tuning registers; determined by device | |
469 | * characterization | |
470 | */ | |
471 | ||
472 | /* FIXME: | |
473 | * - read more than 256 bytes / addresses above 0x00ff | |
474 | * - find offset for device config dataset and extract it | |
475 | * - decrypt eeprom data for camera bridges (em25xx, em276x+) | |
476 | * - use separate/different eeprom hashes (not yet used) | |
477 | */ | |
478 | ||
479 | return 0; | |
a217968f FS |
480 | } else if (data[0] != 0x1a || data[1] != 0xeb || |
481 | data[2] != 0x67 || data[3] != 0x95) { | |
87b52439 | 482 | em28xx_info("unknown eeprom format or eeprom corrupted !\n"); |
f55eacbe FS |
483 | return -ENODEV; |
484 | } | |
485 | ||
a217968f FS |
486 | *eedata = data; |
487 | em_eeprom = (void *)eedata; | |
488 | ||
489 | dev->hash = em28xx_hash_mem(data, len, 32); | |
03910cc3 | 490 | |
0c28dcc0 FS |
491 | em28xx_info("EEPROM ID = %02x %02x %02x %02x, EEPROM hash = 0x%08lx\n", |
492 | em_eeprom->id[0], em_eeprom->id[1], | |
493 | em_eeprom->id[2], em_eeprom->id[3], dev->hash); | |
1bee0184 | 494 | |
12d7ce18 | 495 | em28xx_info("EEPROM info:\n"); |
a6c2ba28 | 496 | |
0c28dcc0 | 497 | switch (le16_to_cpu(em_eeprom->chip_conf) >> 4 & 0x3) { |
a6c2ba28 | 498 | case 0: |
12d7ce18 | 499 | em28xx_info("\tNo audio on board.\n"); |
a6c2ba28 | 500 | break; |
501 | case 1: | |
12d7ce18 | 502 | em28xx_info("\tAC97 audio (5 sample rates)\n"); |
a6c2ba28 | 503 | break; |
504 | case 2: | |
12d7ce18 | 505 | em28xx_info("\tI2S audio, sample rate=32k\n"); |
a6c2ba28 | 506 | break; |
507 | case 3: | |
12d7ce18 | 508 | em28xx_info("\tI2S audio, 3 sample rates\n"); |
a6c2ba28 | 509 | break; |
510 | } | |
511 | ||
0c28dcc0 | 512 | if (le16_to_cpu(em_eeprom->chip_conf) & 1 << 3) |
12d7ce18 | 513 | em28xx_info("\tUSB Remote wakeup capable\n"); |
a6c2ba28 | 514 | |
0c28dcc0 | 515 | if (le16_to_cpu(em_eeprom->chip_conf) & 1 << 2) |
12d7ce18 | 516 | em28xx_info("\tUSB Self power capable\n"); |
a6c2ba28 | 517 | |
0c28dcc0 | 518 | switch (le16_to_cpu(em_eeprom->chip_conf) & 0x3) { |
a6c2ba28 | 519 | case 0: |
12d7ce18 | 520 | em28xx_info("\t500mA max power\n"); |
a6c2ba28 | 521 | break; |
522 | case 1: | |
12d7ce18 | 523 | em28xx_info("\t400mA max power\n"); |
a6c2ba28 | 524 | break; |
525 | case 2: | |
12d7ce18 | 526 | em28xx_info("\t300mA max power\n"); |
a6c2ba28 | 527 | break; |
528 | case 3: | |
12d7ce18 | 529 | em28xx_info("\t200mA max power\n"); |
a6c2ba28 | 530 | break; |
531 | } | |
12d7ce18 FS |
532 | em28xx_info("\tTable at offset 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n", |
533 | em_eeprom->string_idx_table, | |
0c28dcc0 FS |
534 | le16_to_cpu(em_eeprom->string1), |
535 | le16_to_cpu(em_eeprom->string2), | |
536 | le16_to_cpu(em_eeprom->string3)); | |
a6c2ba28 | 537 | |
538 | return 0; | |
539 | } | |
540 | ||
541 | /* ----------------------------------------------------------- */ | |
542 | ||
a6c2ba28 | 543 | /* |
544 | * functionality() | |
545 | */ | |
546 | static u32 functionality(struct i2c_adapter *adap) | |
547 | { | |
eaf33c40 FS |
548 | struct em28xx *dev = adap->algo_data; |
549 | u32 func_flags = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | |
550 | if (dev->board.is_em2800) | |
551 | func_flags &= ~I2C_FUNC_SMBUS_WRITE_BLOCK_DATA; | |
552 | return func_flags; | |
a6c2ba28 | 553 | } |
554 | ||
3acf2809 MCC |
555 | static struct i2c_algorithm em28xx_algo = { |
556 | .master_xfer = em28xx_i2c_xfer, | |
a6c2ba28 | 557 | .functionality = functionality, |
558 | }; | |
559 | ||
3acf2809 | 560 | static struct i2c_adapter em28xx_adap_template = { |
a6c2ba28 | 561 | .owner = THIS_MODULE, |
3acf2809 | 562 | .name = "em28xx", |
3acf2809 | 563 | .algo = &em28xx_algo, |
a6c2ba28 | 564 | }; |
565 | ||
3acf2809 MCC |
566 | static struct i2c_client em28xx_client_template = { |
567 | .name = "em28xx internal", | |
a6c2ba28 | 568 | }; |
569 | ||
570 | /* ----------------------------------------------------------- */ | |
571 | ||
572 | /* | |
573 | * i2c_devs | |
574 | * incomplete list of known devices | |
575 | */ | |
576 | static char *i2c_devs[128] = { | |
0b3966e4 | 577 | [0x3e >> 1] = "remote IR sensor", |
a6c2ba28 | 578 | [0x4a >> 1] = "saa7113h", |
729841ed | 579 | [0x52 >> 1] = "drxk", |
a6c2ba28 | 580 | [0x60 >> 1] = "remote IR sensor", |
da45a2a5 | 581 | [0x8e >> 1] = "remote IR sensor", |
a6c2ba28 | 582 | [0x86 >> 1] = "tda9887", |
583 | [0x80 >> 1] = "msp34xx", | |
584 | [0x88 >> 1] = "msp34xx", | |
585 | [0xa0 >> 1] = "eeprom", | |
2bd1d9eb | 586 | [0xb0 >> 1] = "tda9874", |
a6c2ba28 | 587 | [0xb8 >> 1] = "tvp5150a", |
791a08fc | 588 | [0xba >> 1] = "webcam sensor or tvp5150a", |
a6c2ba28 | 589 | [0xc0 >> 1] = "tuner (analog)", |
590 | [0xc2 >> 1] = "tuner (analog)", | |
591 | [0xc4 >> 1] = "tuner (analog)", | |
592 | [0xc6 >> 1] = "tuner (analog)", | |
593 | }; | |
594 | ||
595 | /* | |
596 | * do_i2c_scan() | |
597 | * check i2c address range for devices | |
598 | */ | |
fad7b958 | 599 | void em28xx_do_i2c_scan(struct em28xx *dev) |
a6c2ba28 | 600 | { |
fad7b958 | 601 | u8 i2c_devicelist[128]; |
a6c2ba28 | 602 | unsigned char buf; |
603 | int i, rc; | |
604 | ||
fad7b958 SS |
605 | memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist)); |
606 | ||
53c4e955 | 607 | for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) { |
fad7b958 SS |
608 | dev->i2c_client.addr = i; |
609 | rc = i2c_master_recv(&dev->i2c_client, &buf, 0); | |
a6c2ba28 | 610 | if (rc < 0) |
611 | continue; | |
fad7b958 | 612 | i2c_devicelist[i] = i; |
12d7ce18 FS |
613 | em28xx_info("found i2c device @ 0x%x [%s]\n", |
614 | i << 1, i2c_devs[i] ? i2c_devs[i] : "???"); | |
a6c2ba28 | 615 | } |
fad7b958 SS |
616 | |
617 | dev->i2c_hash = em28xx_hash_mem(i2c_devicelist, | |
618 | ARRAY_SIZE(i2c_devicelist), 32); | |
a6c2ba28 | 619 | } |
620 | ||
a6c2ba28 | 621 | /* |
3acf2809 | 622 | * em28xx_i2c_register() |
a6c2ba28 | 623 | * register i2c bus |
624 | */ | |
3acf2809 | 625 | int em28xx_i2c_register(struct em28xx *dev) |
a6c2ba28 | 626 | { |
f2a01a00 DSL |
627 | int retval; |
628 | ||
3acf2809 MCC |
629 | BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg); |
630 | BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req); | |
631 | dev->i2c_adap = em28xx_adap_template; | |
a6c2ba28 | 632 | dev->i2c_adap.dev.parent = &dev->udev->dev; |
633 | strcpy(dev->i2c_adap.name, dev->name); | |
634 | dev->i2c_adap.algo_data = dev; | |
f2cf250a | 635 | i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev); |
f2a01a00 DSL |
636 | |
637 | retval = i2c_add_adapter(&dev->i2c_adap); | |
638 | if (retval < 0) { | |
639 | em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n", | |
640 | __func__, retval); | |
641 | return retval; | |
642 | } | |
a6c2ba28 | 643 | |
3acf2809 | 644 | dev->i2c_client = em28xx_client_template; |
a6c2ba28 | 645 | dev->i2c_client.adapter = &dev->i2c_adap; |
646 | ||
a217968f | 647 | retval = em28xx_i2c_eeprom(dev, &dev->eedata, 256); |
c41109fc | 648 | if ((retval < 0) && (retval != -ENODEV)) { |
f2a01a00 DSL |
649 | em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n", |
650 | __func__, retval); | |
c41109fc | 651 | |
f2a01a00 DSL |
652 | return retval; |
653 | } | |
a6c2ba28 | 654 | |
655 | if (i2c_scan) | |
fad7b958 | 656 | em28xx_do_i2c_scan(dev); |
c41109fc | 657 | |
a6c2ba28 | 658 | return 0; |
659 | } | |
660 | ||
661 | /* | |
3acf2809 | 662 | * em28xx_i2c_unregister() |
a6c2ba28 | 663 | * unregister i2c_bus |
664 | */ | |
3acf2809 | 665 | int em28xx_i2c_unregister(struct em28xx *dev) |
a6c2ba28 | 666 | { |
667 | i2c_del_adapter(&dev->i2c_adap); | |
668 | return 0; | |
669 | } |