aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/em28xx
diff options
context:
space:
mode:
authorFrank Schaefer <fschaefer.oss@googlemail.com>2013-03-03 13:37:40 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2013-03-04 14:20:51 -0500
commit87b52439cff4a8b745f419b9e99fa68a5533c342 (patch)
tree4712554f8b3266b98f3db71375d6139b30d9fc93 /drivers/media/usb/em28xx
parent0c28dcc054ecbcd16e197bd9bf9b394cc1f691c5 (diff)
[media] em28xx: add basic support for eeproms with 16 bit address width
Newer devices (em2874, em2884, em28174, em25xx, em27[6,7,8]x) use eeproms with 16 bit instead of 8 bit address width. The used eeprom type depends on the chip type, which makes sure eeproms can't be damaged. This patch adds basic support for 16 bit eeproms only, which includes - reading the content - calculating the eeprom hash - displaying the content The eeprom content uses a different format, for which support will be added with subsequent patches. Tested with the "Hauppauge HVR-930C" and the "Speedlink VAD Laplace webcam" (with additional experimental patches). Signed-off-by: Frank Schäfer <fschaefer.oss@googlemail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb/em28xx')
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c4
-rw-r--r--drivers/media/usb/em28xx/em28xx-i2c.c69
-rw-r--r--drivers/media/usb/em28xx/em28xx.h1
3 files changed, 49 insertions, 25 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 9332d051bde9..f371dbede27e 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -2183,6 +2183,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
2183 {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, 2183 {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
2184 {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT}, 2184 {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT},
2185}; 2185};
2186/* NOTE: introduce a separate hash table for devices with 16 bit eeproms */
2186 2187
2187/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ 2188/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
2188static unsigned short saa711x_addrs[] = { 2189static unsigned short saa711x_addrs[] = {
@@ -3019,11 +3020,13 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
3019 chip_name = "em2874"; 3020 chip_name = "em2874";
3020 dev->reg_gpio_num = EM2874_R80_GPIO; 3021 dev->reg_gpio_num = EM2874_R80_GPIO;
3021 dev->wait_after_write = 0; 3022 dev->wait_after_write = 0;
3023 dev->eeprom_addrwidth_16bit = 1;
3022 break; 3024 break;
3023 case CHIP_ID_EM28174: 3025 case CHIP_ID_EM28174:
3024 chip_name = "em28174"; 3026 chip_name = "em28174";
3025 dev->reg_gpio_num = EM2874_R80_GPIO; 3027 dev->reg_gpio_num = EM2874_R80_GPIO;
3026 dev->wait_after_write = 0; 3028 dev->wait_after_write = 0;
3029 dev->eeprom_addrwidth_16bit = 1;
3027 break; 3030 break;
3028 case CHIP_ID_EM2883: 3031 case CHIP_ID_EM2883:
3029 chip_name = "em2882/3"; 3032 chip_name = "em2882/3";
@@ -3033,6 +3036,7 @@ static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
3033 chip_name = "em2884"; 3036 chip_name = "em2884";
3034 dev->reg_gpio_num = EM2874_R80_GPIO; 3037 dev->reg_gpio_num = EM2874_R80_GPIO;
3035 dev->wait_after_write = 0; 3038 dev->wait_after_write = 0;
3039 dev->eeprom_addrwidth_16bit = 1;
3036 break; 3040 break;
3037 default: 3041 default:
3038 printk(KERN_INFO DRIVER_NAME 3042 printk(KERN_INFO DRIVER_NAME
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index 1b90e7536aa5..3f0012c9cf25 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -372,46 +372,34 @@ static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
372 372
373static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len) 373static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
374{ 374{
375 unsigned char buf, *p = eedata; 375 unsigned char buf[2], *p = eedata;
376 struct em28xx_eeprom *em_eeprom = (void *)eedata; 376 struct em28xx_eeprom *em_eeprom = (void *)eedata;
377 int i, err, size = len, block, block_max; 377 int i, err, size = len, block, block_max;
378 378
379 if (dev->chip_id == CHIP_ID_EM2874 ||
380 dev->chip_id == CHIP_ID_EM28174 ||
381 dev->chip_id == CHIP_ID_EM2884) {
382 /* Empia switched to a 16-bit addressable eeprom in newer
383 devices. While we could certainly write a routine to read
384 the eeprom, there is nothing of use in there that cannot be
385 accessed through registers, and there is the risk that we
386 could corrupt the eeprom (since a 16-bit read call is
387 interpreted as a write call by 8-bit eeproms).
388 */
389 return 0;
390 }
391
392 dev->i2c_client.addr = 0xa0 >> 1; 379 dev->i2c_client.addr = 0xa0 >> 1;
393 380
394 /* Check if board has eeprom */ 381 /* Check if board has eeprom */
395 err = i2c_master_recv(&dev->i2c_client, &buf, 0); 382 err = i2c_master_recv(&dev->i2c_client, buf, 0);
396 if (err < 0) { 383 if (err < 0) {
397 em28xx_info("board has no eeprom\n"); 384 em28xx_info("board has no eeprom\n");
398 memset(eedata, 0, len); 385 memset(eedata, 0, len);
399 return -ENODEV; 386 return -ENODEV;
400 } 387 }
401 388
402 buf = 0; 389 /* Select address memory address 0x00(00) */
403 390 buf[0] = 0;
404 err = i2c_master_send(&dev->i2c_client, &buf, 1); 391 buf[1] = 0;
405 if (err != 1) { 392 err = i2c_master_send(&dev->i2c_client, buf, 1 + dev->eeprom_addrwidth_16bit);
393 if (err != 1 + dev->eeprom_addrwidth_16bit) {
406 em28xx_errdev("failed to read eeprom (err=%d)\n", err); 394 em28xx_errdev("failed to read eeprom (err=%d)\n", err);
407 return err; 395 return err;
408 } 396 }
409 397
398 /* Read eeprom content */
410 if (dev->board.is_em2800) 399 if (dev->board.is_em2800)
411 block_max = 4; 400 block_max = 4;
412 else 401 else
413 block_max = 64; 402 block_max = 64;
414
415 while (size > 0) { 403 while (size > 0) {
416 if (size > block_max) 404 if (size > block_max)
417 block = block_max; 405 block = block_max;
@@ -426,17 +414,48 @@ static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
426 size -= block; 414 size -= block;
427 p += block; 415 p += block;
428 } 416 }
417
418 /* Display eeprom content */
429 for (i = 0; i < len; i++) { 419 for (i = 0; i < len; i++) {
430 if (0 == (i % 16)) 420 if (0 == (i % 16)) {
431 em28xx_info("i2c eeprom %02x:", i); 421 if (dev->eeprom_addrwidth_16bit)
422 em28xx_info("i2c eeprom %04x:", i);
423 else
424 em28xx_info("i2c eeprom %02x:", i);
425 }
432 printk(" %02x", eedata[i]); 426 printk(" %02x", eedata[i]);
433 if (15 == (i % 16)) 427 if (15 == (i % 16))
434 printk("\n"); 428 printk("\n");
435 } 429 }
436 430
437 if (em_eeprom->id[0] != 0x1a || em_eeprom->id[1] != 0xeb || 431 if (dev->eeprom_addrwidth_16bit &&
438 em_eeprom->id[2] != 0x67 || em_eeprom->id[3] != 0x95) { 432 eedata[0] == 0x26 && eedata[3] == 0x00) {
439 em28xx_errdev("Unknown eeprom type or eeprom corrupted !"); 433 /* new eeprom format; size 4-64kb */
434 dev->hash = em28xx_hash_mem(eedata, len, 32);
435 em28xx_info("EEPROM hash = 0x%08lx\n", dev->hash);
436 em28xx_info("EEPROM info: boot page address = 0x%02x04, "
437 "boot configuration = 0x%02x\n",
438 eedata[1], eedata[2]);
439 /* boot configuration (address 0x0002):
440 * [0] microcode download speed: 1 = 400 kHz; 0 = 100 kHz
441 * [1] always selects 12 kb RAM
442 * [2] USB device speed: 1 = force Full Speed; 0 = auto detect
443 * [4] 1 = force fast mode and no suspend for device testing
444 * [5:7] USB PHY tuning registers; determined by device
445 * characterization
446 */
447
448 /* FIXME:
449 * - read more than 256 bytes / addresses above 0x00ff
450 * - find offset for device config dataset and extract it
451 * - decrypt eeprom data for camera bridges (em25xx, em276x+)
452 * - use separate/different eeprom hashes (not yet used)
453 */
454
455 return 0;
456 } else if (em_eeprom->id[0] != 0x1a || em_eeprom->id[1] != 0xeb ||
457 em_eeprom->id[2] != 0x67 || em_eeprom->id[3] != 0x95) {
458 em28xx_info("unknown eeprom format or eeprom corrupted !\n");
440 return -ENODEV; 459 return -ENODEV;
441 } 460 }
442 461
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 90266a1e7957..139dfe54a057 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -510,6 +510,7 @@ struct em28xx {
510 /* i2c i/o */ 510 /* i2c i/o */
511 struct i2c_adapter i2c_adap; 511 struct i2c_adapter i2c_adap;
512 struct i2c_client i2c_client; 512 struct i2c_client i2c_client;
513 unsigned char eeprom_addrwidth_16bit:1;
513 /* video for linux */ 514 /* video for linux */
514 int users; /* user count for exclusive use */ 515 int users; /* user count for exclusive use */
515 int streaming_users; /* Number of actively streaming users */ 516 int streaming_users; /* Number of actively streaming users */