]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/media/video/em28xx/em28xx-cards.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / media / video / em28xx / em28xx-cards.c
index c4204c90fb01d9586c9319599b7ba29ae4408811..aae7753fef117d1c7b12f0bcc30a83a1f018c19e 100644 (file)
@@ -42,19 +42,42 @@ static int tuner = -1;
 module_param(tuner, int, 0444);
 MODULE_PARM_DESC(tuner, "tuner type");
 
+static unsigned int disable_ir;
+module_param(disable_ir, int, 0444);
+MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
+
 struct em28xx_hash_table {
        unsigned long hash;
        unsigned int  model;
        unsigned int  tuner;
 };
 
+/* Boards supported by driver */
+
+#define EM2800_BOARD_UNKNOWN                   0
+#define EM2820_BOARD_UNKNOWN                   1
+#define EM2820_BOARD_TERRATEC_CINERGY_250      2
+#define EM2820_BOARD_PINNACLE_USB_2            3
+#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
+#define EM2820_BOARD_MSI_VOX_USB_2              5
+#define EM2800_BOARD_TERRATEC_CINERGY_200       6
+#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
+#define EM2800_BOARD_KWORLD_USB2800             8
+#define EM2820_BOARD_PINNACLE_DVC_90           9
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900   10
+#define EM2880_BOARD_TERRATEC_HYBRID_XS                11
+#define EM2820_BOARD_KWORLD_PVRTV2800RF                12
+#define EM2880_BOARD_TERRATEC_PRODIGY_XS       13
+#define EM2820_BOARD_PROLINK_PLAYTV_USB2       14
+#define EM2800_BOARD_VGEAR_POCKETTV             15
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950   16
+
 struct em28xx_board em28xx_boards[] = {
        [EM2800_BOARD_UNKNOWN] = {
                .name         = "Unknown EM2800 video grabber",
                .is_em2800    = 1,
                .vchannels    = 2,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .decoder      = EM28XX_SAA7113,
                .input           = { {
                        .type     = EM28XX_VMUX_COMPOSITE1,
@@ -69,13 +92,14 @@ struct em28xx_board em28xx_boards[] = {
        [EM2820_BOARD_UNKNOWN] = {
                .name         = "Unknown EM2750/28xx video grabber",
                .is_em2800    = 0,
+               .tuner_type   = TUNER_ABSENT,
        },
        [EM2820_BOARD_KWORLD_PVRTV2800RF] = {
                .name         = "Kworld PVR TV 2800 RF",
                .is_em2800    = 0,
                .vchannels    = 2,
+               .tuner_type   = TUNER_TEMIC_PAL,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .decoder      = EM28XX_SAA7113,
                .input           = { {
                        .type     = EM28XX_VMUX_COMPOSITE1,
@@ -92,7 +116,6 @@ struct em28xx_board em28xx_boards[] = {
                .vchannels    = 3,
                .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -113,7 +136,6 @@ struct em28xx_board em28xx_boards[] = {
                .vchannels    = 3,
                .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -136,7 +158,6 @@ struct em28xx_board em28xx_boards[] = {
                .tda9887_conf = TDA9887_PRESENT |
                                TDA9887_PORT1_ACTIVE|
                                TDA9887_PORT2_ACTIVE,
-               .has_tuner    = 1,
                .decoder      = EM28XX_TVP5150,
                .has_msp34xx  = 1,
                /*FIXME: S-Video not tested */
@@ -156,7 +177,6 @@ struct em28xx_board em28xx_boards[] = {
                .vchannels    = 3,
                .tda9887_conf = TDA9887_PRESENT,
                .tuner_type   = TUNER_XC2028,
-               .has_tuner    = 1,
                .mts_firmware = 1,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
@@ -174,12 +194,13 @@ struct em28xx_board em28xx_boards[] = {
                } },
        },
        [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950] = {
-               .name         = "Hauppauge WinTV HVR 950",
-               .vchannels    = 3,
-               .tda9887_conf = TDA9887_PRESENT,
-               .tuner_type   = TUNER_XC2028,
-               .has_tuner    = 1,
-               .decoder      = EM28XX_TVP5150,
+               .name           = "Hauppauge WinTV HVR 950",
+               .vchannels      = 3,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .tuner_type     = TUNER_XC2028,
+               .mts_firmware   = 1,
+               .has_12mhz_i2s  = 1,
+               .decoder        = EM28XX_TVP5150,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = TVP5150_COMPOSITE0,
@@ -193,12 +214,14 @@ struct em28xx_board em28xx_boards[] = {
                        .vmux     = TVP5150_SVIDEO,
                        .amux     = 1,
                } },
+
+               /* gpio's 4, 1, 0 */
+               .analog_gpio = 0x003d2d,
        },
        [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
                .name         = "Terratec Hybrid XS",
                .vchannels    = 3,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .tuner_type   = TUNER_XC2028,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
@@ -222,7 +245,6 @@ struct em28xx_board em28xx_boards[] = {
                .name         = "Terratec Prodigy XS",
                .vchannels    = 3,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .tuner_type   = TUNER_XC2028,
                .decoder      = EM28XX_TVP5150,
                .input          = { {
@@ -240,26 +262,27 @@ struct em28xx_board em28xx_boards[] = {
                } },
        },
        [EM2820_BOARD_MSI_VOX_USB_2] = {
-               .name           = "MSI VOX USB 2.0",
-               .vchannels      = 3,
-               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf   = TDA9887_PRESENT      |
-                                 TDA9887_PORT1_ACTIVE |
-                                 TDA9887_PORT2_ACTIVE,
-               .has_tuner      = 1,
-               .decoder        = EM28XX_SAA7114,
-               .input          = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE4,
-                       .amux     = 0,
+               .name              = "MSI VOX USB 2.0",
+               .vchannels         = 3,
+               .tuner_type        = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf      = TDA9887_PRESENT      |
+                                    TDA9887_PORT1_ACTIVE |
+                                    TDA9887_PORT2_ACTIVE,
+               .max_range_640_480 = 1,
+
+               .decoder           = EM28XX_SAA7114,
+               .input             = { {
+                       .type      = EM28XX_VMUX_TELEVISION,
+                       .vmux      = SAA7115_COMPOSITE4,
+                       .amux      = 0,
                }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = 1,
+                       .type      = EM28XX_VMUX_COMPOSITE1,
+                       .vmux      = SAA7115_COMPOSITE0,
+                       .amux      = 1,
                }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = 1,
+                       .type      = EM28XX_VMUX_SVIDEO,
+                       .vmux      = SAA7115_SVIDEO3,
+                       .amux      = 1,
                } },
        },
        [EM2800_BOARD_TERRATEC_CINERGY_200] = {
@@ -268,7 +291,6 @@ struct em28xx_board em28xx_boards[] = {
                .vchannels    = 3,
                .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -290,7 +312,6 @@ struct em28xx_board em28xx_boards[] = {
                .vchannels    = 3,
                .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -312,7 +333,6 @@ struct em28xx_board em28xx_boards[] = {
                .vchannels    = 3,
                .tuner_type   = TUNER_PHILIPS_ATSC,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -329,9 +349,9 @@ struct em28xx_board em28xx_boards[] = {
                } },
        },
        [EM2820_BOARD_PINNACLE_DVC_90] = {
-               .name         = "Pinnacle Dazzle DVC 90",
+               .name         = "Pinnacle Dazzle DVC 90/DVC 100",
                .vchannels    = 3,
-               .has_tuner    = 0,
+               .tuner_type   = TUNER_ABSENT,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
                        .type     = EM28XX_VMUX_COMPOSITE1,
@@ -349,7 +369,6 @@ struct em28xx_board em28xx_boards[] = {
                .vchannels    = 3,
                .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
@@ -369,20 +388,20 @@ struct em28xx_board em28xx_boards[] = {
                .name         = "Pixelview Prolink PlayTV USB 2.0",
                .vchannels    = 3,
                .tda9887_conf = TDA9887_PRESENT,
-               .has_tuner    = 1,
+               .tuner_type   = TUNER_YMEC_TVF_5533MF,
                .decoder      = EM28XX_SAA7113,
                .input          = { {
                        .type     = EM28XX_VMUX_TELEVISION,
                        .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = 1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
                }, {
                        .type     = EM28XX_VMUX_COMPOSITE1,
                        .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = 1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
                }, {
                        .type     = EM28XX_VMUX_SVIDEO,
                        .vmux     = SAA7115_SVIDEO3,
-                       .amux     = 1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
                } },
        },
 };
@@ -414,10 +433,16 @@ struct usb_device_id em28xx_id_table [] = {
                        .driver_info = EM2820_BOARD_PINNACLE_USB_2 },
        { USB_DEVICE(0x2040, 0x4200),
                        .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
+       { USB_DEVICE(0x2040, 0x4201),
+                       .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
        { USB_DEVICE(0x2304, 0x0207),
                        .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
+       { USB_DEVICE(0x2304, 0x021a),
+                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
        { USB_DEVICE(0x2040, 0x6500),
                        .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
+       { USB_DEVICE(0x2040, 0x6502),
+                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
        { USB_DEVICE(0x2040, 0x6513),
                        .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 },
        { USB_DEVICE(0x0ccd, 0x0042),
@@ -451,8 +476,18 @@ void em28xx_pre_card_setup(struct em28xx *dev)
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
        case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950:
        case EM2880_BOARD_TERRATEC_HYBRID_XS:
-               /* reset through GPIO? */
-               em28xx_write_regs_req(dev, 0x00, 0x08, "\x7d", 1);
+               em28xx_write_regs(dev, XCLK_REG, "\x27", 1);
+               em28xx_write_regs(dev, I2C_CLK_REG, "\x40", 1);
+               em28xx_write_regs(dev, 0x08, "\xff", 1);
+               em28xx_write_regs(dev, 0x04, "\x00", 1);
+               msleep(100);
+               em28xx_write_regs(dev, 0x04, "\x08", 1);
+               msleep(100);
+               em28xx_write_regs(dev, 0x08, "\xff", 1);
+               msleep(50);
+               em28xx_write_regs(dev, 0x08, "\x2d", 1);
+               msleep(50);
+               em28xx_write_regs(dev, 0x08, "\x3d", 1);
                break;
        }
 }
@@ -467,13 +502,35 @@ static int em28xx_tuner_callback(void *ptr, int command, int arg)
 
        switch (command) {
        case XC2028_TUNER_RESET:
-               /* FIXME: This is device-dependent */
+       {
+               /* GPIO and initialization codes for analog TV and radio
+                  This code should be complemented for DTV, since reset
+                  codes are different.
+                */
+
                dev->em28xx_write_regs_req(dev, 0x00, 0x48, "\x00", 1);
                dev->em28xx_write_regs_req(dev, 0x00, 0x12, "\x67", 1);
 
-               msleep(140);
+               if (dev->analog_gpio) {
+                       char gpio0 = dev->analog_gpio & 0xff;
+                       char gpio1 = (dev->analog_gpio >> 8) & 0xff;
+                       char gpio4 = dev->analog_gpio >> 24;
+
+                       if (gpio4) {
+                               dev->em28xx_write_regs(dev, 0x04, &gpio4, 1);
+                               msleep(140);
+                       }
+
+                       msleep(6);
+                       dev->em28xx_write_regs(dev, 0x08, &gpio0, 1);
+                       msleep(10);
+                       dev->em28xx_write_regs(dev, 0x08, &gpio1, 1);
+                       msleep(5);
+               }
+
                break;
        }
+       }
        return rc;
 }
 
@@ -484,7 +541,7 @@ static void em28xx_config_tuner(struct em28xx *dev)
        struct tuner_setup           tun_setup;
        struct v4l2_frequency        f;
 
-       if (!dev->has_tuner)
+       if (dev->tuner_type == TUNER_ABSENT)
                return;
 
        tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
@@ -601,14 +658,55 @@ static int em28xx_hint_board(struct em28xx *dev)
 static void em28xx_set_model(struct em28xx *dev)
 {
        dev->is_em2800 = em28xx_boards[dev->model].is_em2800;
-       dev->has_tuner = em28xx_boards[dev->model].has_tuner;
        dev->has_msp34xx = em28xx_boards[dev->model].has_msp34xx;
        dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
        dev->decoder = em28xx_boards[dev->model].decoder;
        dev->video_inputs = em28xx_boards[dev->model].vchannels;
+       dev->analog_gpio = em28xx_boards[dev->model].analog_gpio;
+       dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
+       dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
+}
 
-       if (!em28xx_boards[dev->model].has_tuner)
-               dev->tuner_type = UNSET;
+/* ----------------------------------------------------------------------- */
+void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir)
+{
+       if (disable_ir) {
+               ir->get_key = NULL;
+               return ;
+       }
+
+       /* detect & configure */
+       switch (dev->model) {
+       case (EM2800_BOARD_UNKNOWN):
+               break;
+       case (EM2820_BOARD_UNKNOWN):
+               break;
+       case (EM2800_BOARD_TERRATEC_CINERGY_200):
+       case (EM2820_BOARD_TERRATEC_CINERGY_250):
+               ir->ir_codes = ir_codes_em_terratec;
+               ir->get_key = em28xx_get_key_terratec;
+               snprintf(ir->c.name, sizeof(ir->c.name),
+                        "i2c IR (EM28XX Terratec)");
+               break;
+       case (EM2820_BOARD_PINNACLE_USB_2):
+               ir->ir_codes = ir_codes_pinnacle_grey;
+               ir->get_key = em28xx_get_key_pinnacle_usb_grey;
+               snprintf(ir->c.name, sizeof(ir->c.name),
+                        "i2c IR (EM28XX Pinnacle PCTV)");
+               break;
+       case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
+               ir->ir_codes = ir_codes_hauppauge_new;
+               ir->get_key = em28xx_get_key_em_haup;
+               snprintf(ir->c.name, sizeof(ir->c.name),
+                        "i2c IR (EM2840 Hauppauge)");
+               break;
+       case (EM2820_BOARD_MSI_VOX_USB_2):
+               break;
+       case (EM2800_BOARD_LEADTEK_WINFAST_USBII):
+               break;
+       case (EM2800_BOARD_KWORLD_USB2800):
+               break;
+       }
 }
 
 void em28xx_card_setup(struct em28xx *dev)
@@ -633,6 +731,7 @@ void em28xx_card_setup(struct em28xx *dev)
                tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata);
 
                dev->tuner_type = tv.tuner_type;
+
                if (tv.audio_processor == AUDIO_CHIP_MSP34XX) {
                        dev->i2s_speed = 2048000;
                        dev->has_msp34xx = 1;
@@ -641,8 +740,6 @@ void em28xx_card_setup(struct em28xx *dev)
                if (tv.has_ir)
                        request_module("ir-kbd-i2c");
 #endif
-               /* FIXME: Should also retrieve decoder processor type */
-
                break;
        }
        case EM2820_BOARD_KWORLD_PVRTV2800RF:
@@ -667,7 +764,7 @@ void em28xx_card_setup(struct em28xx *dev)
                request_module("saa7115");
        if (dev->decoder == EM28XX_TVP5150)
                request_module("tvp5150");
-       if (dev->has_tuner)
+       if (dev->tuner_type != TUNER_ABSENT)
                request_module("tuner");
 #endif