V4L/DVB (3408): DViCO FusionHDTV DVB-T Hybrid and ZL10353-based FusionHDTV DVB-T...
[safe/jmp/linux-2.6] / drivers / media / video / cx88 / cx88-dvb.c
index c63f20f..2c97d3f 100644 (file)
@@ -40,6 +40,9 @@
 #  include "cx88-vp3054-i2c.h"
 # endif
 #endif
+#ifdef HAVE_ZL10353
+# include "zl10353.h"
+#endif
 #ifdef HAVE_CX22702
 # include "cx22702.h"
 #endif
@@ -111,8 +114,23 @@ static struct videobuf_queue_ops dvb_qops = {
 
 /* ------------------------------------------------------------------ */
 
+#if defined(HAVE_MT352) || defined(HAVE_ZL10353)
+static int zarlink_pll_set(struct dvb_frontend *fe,
+                             struct dvb_frontend_parameters *params,
+                             u8 *pllbuf)
+{
+       struct cx8802_dev *dev = fe->dvb->priv;
+
+       pllbuf[0] = dev->core->pll_addr << 1;
+       dvb_pll_configure(dev->core->pll_desc, pllbuf + 1,
+                         params->frequency,
+                         params->u.ofdm.bandwidth);
+       return 0;
+}
+#endif
+
 #ifdef HAVE_MT352
-static int generic_mt352_demod_init(struct dvb_frontend* fe)
+static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
 {
        static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
        static u8 reset []         = { RESET,      0x80 };
@@ -132,6 +150,27 @@ static int generic_mt352_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
+static int dvico_dual_demod_init(struct dvb_frontend *fe)
+{
+       static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x38 };
+       static u8 reset []         = { RESET,      0x80 };
+       static u8 adc_ctl_1_cfg [] = { ADC_CTL_1,  0x40 };
+       static u8 agc_cfg []       = { AGC_TARGET, 0x28, 0x20 };
+       static u8 gpp_ctl_cfg []   = { GPP_CTL,    0x33 };
+       static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(200);
+       mt352_write(fe, reset,          sizeof(reset));
+       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+
+       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+       mt352_write(fe, gpp_ctl_cfg,    sizeof(gpp_ctl_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+       return 0;
+}
+
 static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
 {
        static u8 clock_config []  = { 0x89, 0x38, 0x39 };
@@ -155,32 +194,48 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int mt352_pll_set(struct dvb_frontend* fe,
-                        struct dvb_frontend_parameters* params,
-                        u8* pllbuf)
-{
-       struct cx8802_dev *dev= fe->dvb->priv;
-
-       pllbuf[0] = dev->core->pll_addr << 1;
-       dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
-                         params->frequency,
-                         params->u.ofdm.bandwidth);
-       return 0;
-}
-
 static struct mt352_config dvico_fusionhdtv = {
        .demod_address = 0x0F,
-       .demod_init    = generic_mt352_demod_init,
-       .pll_set       = mt352_pll_set,
+       .demod_init    = dvico_fusionhdtv_demod_init,
+       .pll_set       = zarlink_pll_set,
 };
 
 static struct mt352_config dntv_live_dvbt_config = {
        .demod_address = 0x0f,
        .demod_init    = dntv_live_dvbt_demod_init,
-       .pll_set       = mt352_pll_set,
+       .pll_set       = zarlink_pll_set,
+};
+
+static struct mt352_config dvico_fusionhdtv_dual = {
+       .demod_address = 0x0F,
+       .demod_init    = dvico_dual_demod_init,
+       .pll_set       = zarlink_pll_set,
 };
 
 #ifdef HAVE_VP3054_I2C
+static int dntv_live_dvbt_pro_demod_init(struct dvb_frontend* fe)
+{
+       static u8 clock_config []  = { 0x89, 0x38, 0x38 };
+       static u8 reset []         = { 0x50, 0x80 };
+       static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+       static u8 agc_cfg []       = { 0x67, 0x10, 0x20, 0x00, 0xFF, 0xFF,
+                                      0x00, 0xFF, 0x00, 0x40, 0x40 };
+       static u8 dntv_extra[]     = { 0xB5, 0x7A };
+       static u8 capt_range_cfg[] = { 0x75, 0x32 };
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(2000);
+       mt352_write(fe, reset,          sizeof(reset));
+       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+
+       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+       udelay(2000);
+       mt352_write(fe, dntv_extra,     sizeof(dntv_extra));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+
+       return 0;
+}
+
 static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
 {
        struct cx8802_dev *dev= fe->dvb->priv;
@@ -238,12 +293,52 @@ static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
 static struct mt352_config dntv_live_dvbt_pro_config = {
        .demod_address = 0x0f,
        .no_tuner      = 1,
-       .demod_init    = generic_mt352_demod_init,
+       .demod_init    = dntv_live_dvbt_pro_demod_init,
        .pll_set       = dntv_live_dvbt_pro_pll_set,
 };
 #endif
 #endif
 
+#ifdef HAVE_ZL10353
+static int dvico_hybrid_tune_pll(struct dvb_frontend *fe,
+                                struct dvb_frontend_parameters *params,
+                                u8 *pllbuf)
+{
+       struct cx8802_dev *dev= fe->dvb->priv;
+       struct i2c_msg msg =
+               { .addr = dev->core->pll_addr, .flags = 0,
+                 .buf = pllbuf + 1, .len = 4 };
+       int err;
+
+       pllbuf[0] = dev->core->pll_addr << 1;
+       dvb_pll_configure(dev->core->pll_desc, pllbuf + 1,
+                         params->frequency,
+                         params->u.ofdm.bandwidth);
+
+       if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+               printk(KERN_WARNING "cx88-dvb: %s error "
+                          "(addr %02x <- %02x, err = %i)\n",
+                          __FUNCTION__, pllbuf[0], pllbuf[1], err);
+               if (err < 0)
+                       return err;
+               else
+                       return -EREMOTEIO;
+       }
+
+       return 0;
+}
+
+static struct zl10353_config dvico_fusionhdtv_hybrid = {
+       .demod_address = 0x0F,
+       .pll_set       = dvico_hybrid_tune_pll,
+};
+
+static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
+       .demod_address = 0x0F,
+       .pll_set       = zarlink_pll_set,
+};
+#endif
+
 #ifdef HAVE_CX22702
 static struct cx22702_config connexant_refboard_config = {
        .demod_address = 0x43,
@@ -439,6 +534,7 @@ static int dvb_register(struct cx8802_dev *dev)
                break;
        case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
        case CX88_BOARD_CONEXANT_DVB_T1:
+       case CX88_BOARD_KWORLD_DVB_T_CX22702:
        case CX88_BOARD_WINFAST_DTV1000:
                dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
                                                   &dev->core->i2c_adap);
@@ -449,16 +545,27 @@ static int dvb_register(struct cx8802_dev *dev)
                                                   &dev->core->i2c_adap);
                break;
 #endif
+#if defined(HAVE_MT352) || defined(HAVE_ZL10353)
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
+               dev->core->pll_addr = 0x60;
+               dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
 #ifdef HAVE_MT352
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
-               dev->core->pll_addr = 0x61;
-               dev->core->pll_desc = &dvb_pll_lg_z201;
                dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
                                                 &dev->core->i2c_adap);
+               if (dev->dvb.frontend != NULL)
+                       break;
+#endif
+#ifdef HAVE_ZL10353
+               /* ZL10353 replaces MT352 on later cards */
+               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
+                                                  &dev->core->i2c_adap);
+#endif
                break;
-       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
-               dev->core->pll_addr = 0x60;
-               dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
+#endif /* HAVE_MT352 || HAVE_ZL10353 */
+#ifdef HAVE_MT352
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
+               dev->core->pll_addr = 0x61;
+               dev->core->pll_desc = &dvb_pll_lg_z201;
                dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
                                                 &dev->core->i2c_adap);
                break;
@@ -480,6 +587,22 @@ static int dvb_register(struct cx8802_dev *dev)
                printk("%s: built without vp3054 support\n", dev->core->name);
 #endif
                break;
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+               /* The tin box says DEE1601, but it seems to be DTT7579
+                * compatible, with a slightly different MT352 AGC gain. */
+               dev->core->pll_addr = 0x61;
+               dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
+               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
+                                                &dev->core->i2c_adap);
+               break;
+#endif
+#ifdef HAVE_ZL10353
+       case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
+               dev->core->pll_addr = 0x61;
+               dev->core->pll_desc = &dvb_pll_unknown_fe6600;
+               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid,
+                                                  &dev->core->i2c_adap);
+               break;
 #endif
 #ifdef HAVE_OR51132
        case CX88_BOARD_PCHDTV_HD3000:
@@ -598,10 +721,9 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
                goto fail_core;
 
        err = -ENOMEM;
-       dev = kmalloc(sizeof(*dev),GFP_KERNEL);
+       dev = kzalloc(sizeof(*dev),GFP_KERNEL);
        if (NULL == dev)
                goto fail_core;
-       memset(dev,0,sizeof(*dev));
        dev->pci = pci_dev;
        dev->core = core;