diff options
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-cards.c')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-cards.c | 103 |
1 files changed, 86 insertions, 17 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index f7e9168157a..87f77a34eea 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -33,6 +33,7 @@ #include <media/saa7115.h> #include <media/tvp5150.h> #include <media/tvaudio.h> +#include <media/mt9v011.h> #include <media/i2c-addr.h> #include <media/tveeprom.h> #include <media/v4l2-common.h> @@ -268,6 +269,20 @@ static struct em28xx_reg_seq dikom_dk300_digital[] = { }; +/* Reset for the most [digital] boards */ +static struct em28xx_reg_seq leadership_digital[] = { + {EM2874_R80_GPIO, 0x70, 0xff, 10}, + { -1, -1, -1, -1}, +}; + +static struct em28xx_reg_seq leadership_reset[] = { + {EM2874_R80_GPIO, 0xf0, 0xff, 10}, + {EM2874_R80_GPIO, 0xb0, 0xff, 10}, + {EM2874_R80_GPIO, 0xf0, 0xff, 10}, + { -1, -1, -1, -1}, +}; + + /* * Board definitions */ @@ -1224,6 +1239,19 @@ struct em28xx_board em28xx_boards[] = { .vmux = SAA7115_COMPOSITE0, } }, }, + + [EM2874_LEADERSHIP_ISDBT] = { + .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | + EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_100_KHZ, + .xclk = EM28XX_XCLK_FREQUENCY_10MHZ, + .name = "EM2874 Leadership ISDBT", + .tuner_type = TUNER_ABSENT, + .tuner_gpio = leadership_reset, + .dvb_gpio = leadership_digital, + .has_dvb = 1, + }, + [EM2880_BOARD_MSI_DIGIVOX_AD] = { .name = "MSI DigiVox A/D", .valid = EM28XX_BOARD_NOT_VALIDATED, @@ -1469,7 +1497,7 @@ struct em28xx_board em28xx_boards[] = { } }, }, [EM2882_BOARD_TERRATEC_HYBRID_XS] = { - .name = "Terratec Hybrid XS (em2882)", + .name = "Terratec Cinnergy Hybrid T USB XS (em2882)", .tuner_type = TUNER_XC2028, .tuner_gpio = default_tuner_gpio, .mts_firmware = 1, @@ -1633,11 +1661,11 @@ struct em28xx_board em28xx_boards[] = { .input = { { .type = EM28XX_VMUX_COMPOSITE1, .vmux = SAA7115_COMPOSITE0, - .amux = EM28XX_AMUX_VIDEO2, + .amux = EM28XX_AMUX_LINE_IN, }, { .type = EM28XX_VMUX_SVIDEO, .vmux = SAA7115_SVIDEO3, - .amux = EM28XX_AMUX_VIDEO2, + .amux = EM28XX_AMUX_LINE_IN, } }, }, [EM2860_BOARD_TERRATEC_AV350] = { @@ -1754,6 +1782,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0x2868), .driver_info = EM2820_BOARD_UNKNOWN }, + { USB_DEVICE(0xeb1a, 0x2875), + .driver_info = EM2820_BOARD_UNKNOWN }, { USB_DEVICE(0xeb1a, 0xe300), .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U }, { USB_DEVICE(0xeb1a, 0xe303), @@ -1791,7 +1821,7 @@ struct usb_device_id em28xx_id_table[] = { { USB_DEVICE(0x0ccd, 0x005e), .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0042), - .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, + .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, { USB_DEVICE(0x0ccd, 0x0043), .driver_info = EM2870_BOARD_TERRATEC_XS }, { USB_DEVICE(0x0ccd, 0x0047), @@ -1873,6 +1903,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = { {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT}, {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC}, {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF}, + {0x6b800080, EM2874_LEADERSHIP_ISDBT, TUNER_ABSENT}, }; /* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */ @@ -1887,11 +1918,6 @@ static unsigned short tvp5150_addrs[] = { I2C_CLIENT_END }; -static unsigned short mt9v011_addrs[] = { - 0xba >> 1, - I2C_CLIENT_END -}; - static unsigned short msp3400_addrs[] = { 0x80 >> 1, 0x88 >> 1, @@ -2407,8 +2433,9 @@ void em28xx_register_i2c_ir(struct em28xx *dev) dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW; dev->init_data.get_key = em28xx_get_key_em_haup; dev->init_data.name = "i2c IR (EM2840 Hauppauge)"; + break; case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE: - dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;; + dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE; dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe; dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)"; break; @@ -2430,8 +2457,36 @@ void em28xx_card_setup(struct em28xx *dev) dev->board.is_webcam = 0; else dev->progressive = 1; - } else - em28xx_set_model(dev); + } + + if (!dev->board.is_webcam) { + switch (dev->model) { + case EM2820_BOARD_UNKNOWN: + case EM2800_BOARD_UNKNOWN: + /* + * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD. + * + * This occurs because they share identical USB vendor and + * product IDs. + * + * What we do here is look up the EEPROM hash of the K-WORLD + * and if it is found then we decide that we do not have + * a DIGIVOX and reset the device to the K-WORLD instead. + * + * This solution is only valid if they do not share eeprom + * hash identities which has not been determined as yet. + */ + if (em28xx_hint_board(dev) < 0) + em28xx_errdev("Board not discovered\n"); + else { + em28xx_set_model(dev); + em28xx_pre_card_setup(dev); + } + break; + default: + em28xx_set_model(dev); + } + } em28xx_info("Identified as %s (card=%d)\n", dev->board.name, dev->model); @@ -2565,11 +2620,17 @@ void em28xx_card_setup(struct em28xx *dev) "tvp5150", 0, tvp5150_addrs); if (dev->em28xx_sensor == EM28XX_MT9V011) { + struct mt9v011_platform_data pdata; + struct i2c_board_info mt9v011_info = { + .type = "mt9v011", + .addr = 0xba >> 1, + .platform_data = &pdata, + }; struct v4l2_subdev *sd; - sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, - &dev->i2c_adap, "mt9v011", 0, mt9v011_addrs); - v4l2_subdev_call(sd, core, s_config, 0, &dev->sensor_xtal); + pdata.xtal = dev->sensor_xtal; + sd = v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap, + &mt9v011_info, NULL); } @@ -2632,8 +2693,14 @@ static void request_modules(struct em28xx *dev) INIT_WORK(&dev->request_module_wk, request_module_async); schedule_work(&dev->request_module_wk); } + +static void flush_request_modules(struct em28xx *dev) +{ + flush_work_sync(&dev->request_module_wk); +} #else #define request_modules(dev) +#define flush_request_modules(dev) #endif /* CONFIG_MODULES */ /* @@ -2749,8 +2816,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, em28xx_pre_card_setup(dev); if (!dev->board.is_em2800) { - /* Sets I2C speed to 100 KHz */ - retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); + /* Resets I2C speed */ + em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); if (retval < 0) { em28xx_errdev("%s: em28xx_write_regs_req failed!" " retval [%d]\n", @@ -3060,6 +3127,8 @@ static void em28xx_usb_disconnect(struct usb_interface *interface) em28xx_info("disconnecting %s\n", dev->vdev->name); + flush_request_modules(dev); + /* wait until all current v4l2 io is finished then deallocate resources */ mutex_lock(&dev->lock); |