]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/media/video/em28xx/em28xx-cards.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / media / video / em28xx / em28xx-cards.c
index f7e9168157a502d38b543ec89212984fa5620531..87f77a34eeabd092a678208dcac815caf0c230cc 100644 (file)
@@ -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);