#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 };
},
.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 */
{ 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;
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;
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);
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:
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;
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) {
}
#endif
}
+ return 0;
err2:
v4l2_device_unregister(&dev->v4l2_dev);
/* 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;
}