]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/staging/tm6000/tm6000-cards.c
V4L/DVB: tm6000: only register after initialized
[net-next-2.6.git] / drivers / staging / tm6000 / tm6000-cards.c
index 9e8f1fbcceb54799ad5e434810eeaaf1c764aca1..43620a3f5ec1c0e2d694fa8acea4c9fbe37c8d99 100644 (file)
@@ -44,6 +44,9 @@
 #define TM6000_BOARD_FREECOM_AND_SIMILAR       7
 #define TM6000_BOARD_ADSTECH_MINI_DUAL_TV      8
 #define TM6010_BOARD_HAUPPAUGE_900H            9
+#define TM6010_BOARD_BEHOLD_WANDER             10
+#define TM6010_BOARD_BEHOLD_VOYAGER            11
+#define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE        12
 
 #define TM6000_MAXBOARDS        16
 static unsigned int card[]     = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET };
@@ -208,7 +211,21 @@ struct tm6000_board tm6000_boards[] = {
                },
                .gpio_addr_tun_reset = TM6000_GPIO_2,
        },
-
+       [TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = {
+               .name         = "Terratec Cinergy Hybrid XE",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+                       .has_remote   = 1,
+               },
+               .gpio_addr_tun_reset = TM6010_GPIO_2,
+       }
 };
 
 /* table of devices that work with this driver */
@@ -221,12 +238,13 @@ struct usb_device_id tm6000_id_table [] = {
        { USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
        { USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER },
        { USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER },
+       { USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
        { },
 };
 
 /* Tuner callback to provide the proper gpio changes needed for xc2028 */
 
-static int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
+int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
 {
        int rc=0;
        struct tm6000_core *dev = ptr;
@@ -279,6 +297,78 @@ static int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
        return (rc);
 }
 
+int tm6000_cards_setup(struct tm6000_core *dev)
+{
+       int i, rc;
+
+       /*
+        * Board-specific initialization sequence. Handles all GPIO
+        * initialization sequences that are board-specific.
+        * Up to now, all found devices use GPIO1 and GPIO4 at the same way.
+        * Probably, they're all based on some reference device. Due to that,
+        * there's a common routine at the end to handle those GPIO's. Devices
+        * that use different pinups or init sequences can just return at
+        * the board-specific session.
+        */
+       switch (dev->model) {
+       case TM6010_BOARD_HAUPPAUGE_900H:
+               /* Turn xceive 3028 on */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6010_GPIO_3, 0x01);
+               msleep(11);
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * Default initialization. Most of the devices seem to use GPIO1
+        * and GPIO4.on the same way, so, this handles the common sequence
+        * used by most devices.
+        * If a device uses a different sequence or different GPIO pins for
+        * reset, just add the code at the board-specific part
+        */
+       for (i = 0; i < 2; i++) {
+               rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                       dev->tuner_reset_gpio, 0x00);
+               if (rc < 0) {
+                       printk(KERN_ERR "Error %i doing GPIO1 reset\n", rc);
+                       return rc;
+               }
+
+               msleep(10); /* Just to be conservative */
+               rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                       dev->tuner_reset_gpio, 0x01);
+               if (rc < 0) {
+                       printk(KERN_ERR "Error %i doing GPIO1 reset\n", rc);
+                       return rc;
+               }
+
+               msleep(10);
+               rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_4, 0);
+               if (rc < 0) {
+                       printk(KERN_ERR "Error %i doing GPIO4 reset\n", rc);
+                       return rc;
+               }
+
+               msleep(10);
+               rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_4, 1);
+               if (rc < 0) {
+                       printk(KERN_ERR "Error %i doing GPIO4 reset\n", rc);
+                       return rc;
+               }
+
+               if (!i) {
+                       rc = tm6000_get_reg16(dev, 0x40, 0, 0);
+                       if (rc >= 0)
+                               printk(KERN_DEBUG "board=%d\n", rc);
+               }
+       }
+
+       msleep(50);
+
+       return 0;
+};
+
 static void tm6000_config_tuner (struct tm6000_core *dev)
 {
        struct tuner_setup           tun_setup;
@@ -290,7 +380,7 @@ static void tm6000_config_tuner (struct tm6000_core *dev)
        memset(&tun_setup, 0, sizeof(tun_setup));
        tun_setup.type   = dev->tuner_type;
        tun_setup.addr   = dev->tuner_addr;
-       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO | T_DIGITAL_TV;
        tun_setup.tuner_callback = tm6000_tuner_callback;
 
        v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
@@ -302,15 +392,18 @@ static void tm6000_config_tuner (struct tm6000_core *dev)
                memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
                memset (&ctl,0,sizeof(ctl));
 
-               ctl.mts   = 1;
-               ctl.read_not_reliable = 1;
+               ctl.input1 = 1;
+               ctl.read_not_reliable = 0;
                ctl.msleep = 10;
-
+               ctl.demod = XC3028_FE_ZARLINK456;
+               ctl.vhfbw7 = 1;
+               ctl.uhfbw8 = 1;
                xc2028_cfg.tuner = TUNER_XC2028;
                xc2028_cfg.priv  = &ctl;
 
                switch(dev->model) {
                case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
                        ctl.fname = "xc3028L-v36.fw";
                        break;
                default:
@@ -360,11 +453,6 @@ static int tm6000_init_dev(struct tm6000_core *dev)
        if (rc<0)
                goto err;
 
-       /* register and initialize V4L2 */
-       rc=tm6000_v4l2_register(dev);
-       if (rc<0)
-               goto err;
-
        /* Default values for STD and resolutions */
        dev->width = 720;
        dev->height = 480;
@@ -387,12 +475,18 @@ static int tm6000_init_dev(struct tm6000_core *dev)
                v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
                        "tvaudio", "tvaudio", I2C_ADDR_TDA9874, NULL);
 
+       /* register and initialize V4L2 */
+       rc=tm6000_v4l2_register(dev);
+       if (rc<0)
+               goto err;
+
        if(dev->caps.has_dvb) {
                dev->dvb = kzalloc(sizeof(*(dev->dvb)), GFP_KERNEL);
                if(!dev->dvb) {
                        rc = -ENOMEM;
                        goto err2;
                }
+
 #ifdef CONFIG_VIDEO_TM6000_DVB
                rc = tm6000_dvb_register(dev);
                if(rc < 0) {
@@ -402,6 +496,7 @@ static int tm6000_init_dev(struct tm6000_core *dev)
                }
 #endif
        }
+       return 0;
 
 err2:
        v4l2_device_unregister(&dev->v4l2_dev);
@@ -459,7 +554,7 @@ static int tm6000_usb_probe(struct usb_interface *interface,
        /* Check to see next free device and mark as used */
        nr=find_first_zero_bit(&tm6000_devused,TM6000_MAXBOARDS);
        if (nr >= TM6000_MAXBOARDS) {
-               printk ("tm6000: Supports only %i em28xx boards.\n",TM6000_MAXBOARDS);
+               printk ("tm6000: Supports only %i tm60xx boards.\n",TM6000_MAXBOARDS);
                usb_put_dev(usbdev);
                return -ENOMEM;
        }