V4L/DVB (9629): Add support for the ATI TV Wonder HD 600 USB Remote Control
[safe/jmp/linux-2.6] / drivers / media / video / em28xx / em28xx-cards.c
index 6b241cc..75b2af2 100644 (file)
@@ -93,28 +93,6 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = 0,
                } },
        },
-       [EM2800_BOARD_KWORLD_USB2800] = {
-               .name         = "Kworld USB2800",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .is_em2800    = 1,
-               .vchannels    = 3,
-               .tuner_type   = TUNER_PHILIPS_FCV1236D,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA7113,
-               .input          = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = 0,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = 1,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = 1,
-               } },
-       },
        [EM2820_BOARD_KWORLD_PVRTV2800RF] = {
                .name         = "Kworld PVR TV 2800 RF",
                .is_em2800    = 0,
@@ -599,7 +577,7 @@ struct em28xx_board em28xx_boards[] = {
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = 1,
+                       .amux     = 3,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
                        .vmux     = TVP5150_SVIDEO,
@@ -614,6 +592,7 @@ struct em28xx_board em28xx_boards[] = {
                .mts_firmware   = 1,
                .has_12mhz_i2s  = 1,
                .has_dvb        = 1,
+               .ir_codes       = ir_codes_hauppauge_new,
                .decoder        = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -637,6 +616,7 @@ struct em28xx_board em28xx_boards[] = {
                .mts_firmware   = 1,
                .has_12mhz_i2s  = 1,
                .has_dvb        = 1,
+               .ir_codes       = ir_codes_pinnacle_pctv_hd,
                .decoder        = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -660,6 +640,7 @@ struct em28xx_board em28xx_boards[] = {
                .mts_firmware   = 1,
                .has_12mhz_i2s  = 1,
                .has_dvb        = 1,
+               .ir_codes       = ir_codes_ati_tv_wonder_hd_600,
                .decoder        = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -952,22 +933,23 @@ struct em28xx_board em28xx_boards[] = {
        },
        [EM2880_BOARD_KWORLD_DVB_310U] = {
                .name         = "KWorld DVB-T 310U",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
                .tuner_type   = TUNER_XC2028,
+               .has_dvb      = 1,
+               .mts_firmware = 1,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = 0,
+                       .amux     = EM28XX_AMUX_VIDEO,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = 1,
-               }, {
+                       .amux     = EM28XX_AMUX_AC97_LINE_IN,
+               }, {    /* S-video has not been tested yet */
                        .type     = EM28XX_VMUX_SVIDEO,
                        .vmux     = TVP5150_SVIDEO,
-                       .amux     = 1,
+                       .amux     = EM28XX_AMUX_AC97_LINE_IN,
                } },
        },
        [EM2881_BOARD_DNT_DA2_HYBRID] = {
@@ -1015,6 +997,7 @@ struct em28xx_board em28xx_boards[] = {
                .valid        = EM28XX_BOARD_NOT_VALIDATED,
                .vchannels    = 3,
                .tuner_type   = TUNER_XC2028,
+               .mts_firmware = 1,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -1091,7 +1074,7 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = 1,
                } },
        },
-       [EM2820_BOARD_COMPRO_VIDEO_MATE] = {
+       [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
                .name         = "Compro VideoMate ForYou/Stereo",
                .vchannels    = 2,
                .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
@@ -1107,6 +1090,21 @@ struct em28xx_board em28xx_boards[] = {
                        .amux     = EM28XX_AMUX_LINE_IN,
                } },
        },
+       [EM2874_BOARD_PINNACLE_PCTV_80E] = {
+               .name         = "Pinnacle PCTV HD Mini",
+               .vchannels    = 0,
+               .tuner_type   = TUNER_ABSENT,
+               .has_dvb        = 1,
+               .ir_codes       = ir_codes_pinnacle_pctv_hd,
+               .decoder      = EM28XX_NODECODER,
+#ifdef DJH_DEBUG
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+#endif
+       },
 };
 const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
 
@@ -1121,7 +1119,7 @@ struct usb_device_id em28xx_id_table [] = {
        { USB_DEVICE(0xeb1a, 0x2820),
                        .driver_info = EM2820_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2821),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
+                       .driver_info = EM2820_BOARD_PROLINK_PLAYTV_USB2 },
        { USB_DEVICE(0xeb1a, 0x2860),
                        .driver_info = EM2820_BOARD_UNKNOWN },
        { USB_DEVICE(0xeb1a, 0x2861),
@@ -1169,7 +1167,7 @@ struct usb_device_id em28xx_id_table [] = {
        { USB_DEVICE(0x185b, 0x2870),
                        .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE },
        { USB_DEVICE(0x185b, 0x2041),
-                       .driver_info = EM2820_BOARD_COMPRO_VIDEO_MATE },
+                       .driver_info = EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU },
        { USB_DEVICE(0x2040, 0x4200),
                        .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
        { USB_DEVICE(0x2040, 0x4201),
@@ -1200,6 +1198,8 @@ struct usb_device_id em28xx_id_table [] = {
                        .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO },
        { USB_DEVICE(0x2304, 0x0227),
                        .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
+       { USB_DEVICE(0x2304, 0x023f),
+                       .driver_info = EM2874_BOARD_PINNACLE_PCTV_80E },
        { USB_DEVICE(0x0413, 0x6023),
                        .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII },
        { USB_DEVICE(0x093b, 0xa005),
@@ -1275,12 +1275,24 @@ static struct em28xx_reg_seq em2882_terratec_hybrid_xs_digital[] = {
        {  -1,                  -1,     -1,               -1},
 };
 
+/* Pinnacle PCTV HD Mini (80e) GPIOs
+   0-5: not used
+   6:   demod reset, active low
+   7:   LED on, active high */
+static struct em28xx_reg_seq em2874_pinnacle_80e_digital[] = {
+       {EM28XX_R06_I2C_CLK,    0x45,   0xff,             10}, /*400 KHz*/
+       {EM2874_R80_GPIO,       0x80,   0xff,             100},/*Demod reset*/
+       {EM2874_R80_GPIO,       0xc0,   0xff,             10},
+       {  -1,                  -1,     -1,               -1},
+};
+
 /*
  * EEPROM hash table for devices with generic USB IDs
  */
 static struct em28xx_hash_table em28xx_eeprom_hash [] = {
        /* P/N: SA 60002070465 Tuner: TVF7533-MF */
        {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
+       {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
 };
 
 /* I2C devicelist hash table for devices with generic USB IDs */
@@ -1290,7 +1302,7 @@ static struct em28xx_hash_table em28xx_i2c_hash[] = {
        {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT},
 };
 
-int em28xx_tuner_callback(void *ptr, int command, int arg)
+int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
 {
        int rc = 0;
        struct em28xx *dev = ptr;
@@ -1321,6 +1333,7 @@ static void em28xx_set_model(struct em28xx *dev)
        dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
        dev->has_dvb = em28xx_boards[dev->model].has_dvb;
        dev->has_snapshot_button = em28xx_boards[dev->model].has_snapshot_button;
+       dev->ir_codes = em28xx_boards[dev->model].ir_codes;
        dev->valid = em28xx_boards[dev->model].valid;
 }
 
@@ -1331,17 +1344,25 @@ void em28xx_pre_card_setup(struct em28xx *dev)
 {
        int rc;
 
-       rc = em28xx_read_reg(dev, EM2880_R04_GPO);
-       if (rc >= 0)
-               dev->reg_gpo = rc;
+       /* Set the default GPO/GPIO for legacy devices */
+       dev->reg_gpo_num = EM2880_R04_GPO;
+       dev->reg_gpio_num = EM28XX_R08_GPIO;
 
        dev->wait_after_write = 5;
+
+       /* Based on the Chip ID, set the device configuration */
        rc = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
        if (rc > 0) {
+               dev->chip_id = rc;
                switch (rc) {
                case CHIP_ID_EM2860:
                        em28xx_info("chip ID is em2860\n");
                        break;
+               case CHIP_ID_EM2874:
+                       em28xx_info("chip ID is em2874\n");
+                       dev->reg_gpio_num = EM2874_R80_GPIO;
+                       dev->wait_after_write = 0;
+                       break;
                case CHIP_ID_EM2883:
                        em28xx_info("chip ID is em2882/em2883\n");
                        dev->wait_after_write = 0;
@@ -1350,6 +1371,12 @@ void em28xx_pre_card_setup(struct em28xx *dev)
                        em28xx_info("em28xx chip ID = %d\n", rc);
                }
        }
+
+       /* Prepopulate cached GPO register content */
+       rc = em28xx_read_reg(dev, dev->reg_gpo_num);
+       if (rc >= 0)
+               dev->reg_gpo = rc;
+
        em28xx_set_model(dev);
 
        /* request some modules */
@@ -1523,6 +1550,13 @@ void em28xx_pre_card_setup(struct em28xx *dev)
                /* enables audio for that device */
                em28xx_write_regs_req(dev, 0x00, 0x08, "\xfd", 1);
                break;
+
+       case EM2874_BOARD_PINNACLE_PCTV_80E:
+               /* Set 400 KHz clock */
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x45", 1);
+
+               dev->digital_gpio = em2874_pinnacle_80e_digital;
+               break;
        }
 
        em28xx_gpio_set(dev, dev->tun_analog_gpio);
@@ -1551,9 +1585,12 @@ static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
                /* djh - Not sure which demod we need here */
                ctl->demod = XC3028_FE_DEFAULT;
                break;
+       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
+               ctl->demod = XC3028_FE_DEFAULT;
+               ctl->fname = XC3028L_DEFAULT_FIRMWARE;
+               break;
        case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
        case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
-       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
                /* FIXME: Better to specify the needed IF */
                ctl->demod = XC3028_FE_DEFAULT;
                break;
@@ -1763,6 +1800,20 @@ void em28xx_card_setup(struct em28xx *dev)
                break;
        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.
+                */
+       case EM2880_BOARD_MSI_DIGIVOX_AD:
                if (!em28xx_hint_board(dev))
                        em28xx_set_model(dev);
                break;
@@ -1797,4 +1848,6 @@ void em28xx_card_setup(struct em28xx *dev)
 #endif
 
        em28xx_config_tuner(dev);
+
+       em28xx_ir_init(dev);
 }