V4L/DVB (5202): DVB: Use ARRAY_SIZE macro when appropriate
[linux-2.6-block.git] / drivers / media / dvb / bt8xx / dvb-bt8xx.c
index c56f26c93b7a5f6d45584949d1a6bf6bbc61abb7..58f69f6ae3918601e56bc2b10694f7914d3935eb 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -34,7 +35,6 @@
 #include "dvb_frontend.h"
 #include "dvb-bt8xx.h"
 #include "bt878.h"
-#include "dvb-pll.h"
 
 static int debug;
 
@@ -67,7 +67,7 @@ static void dvb_bt8xx_task(unsigned long data)
 
 static int dvb_bt8xx_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
-       struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+       struct dvb_demux*dvbdmx = dvbdmxfeed->demux;
        struct dvb_bt8xx_card *card = dvbdmx->priv;
        int rc;
 
@@ -147,12 +147,15 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
        u32 div;
        unsigned char bs = 0;
        unsigned char cp = 0;
 
+       if (buf_len < 5)
+               return -EINVAL;
+
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
        if (params->frequency < 542000000)
@@ -169,27 +172,25 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
        else
                bs = 0x08;
 
-       pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
+       pllbuf[0] = 0x60;
        pllbuf[1] = div >> 8;
        pllbuf[2] = div & 0xff;
        pllbuf[3] = cp;
        pllbuf[4] = bs;
 
-       return 0;
+       return 5;
 }
 
 static struct mt352_config thomson_dtt7579_config = {
        .demod_address = 0x0f,
        .demod_init = thomson_dtt7579_demod_init,
-       .pll_set = thomson_dtt7579_pll_set,
 };
 
 static struct zl10353_config thomson_dtt7579_zl10353_config = {
        .demod_address = 0x0f,
-       .pll_set = thomson_dtt7579_pll_set,
 };
 
-static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        u32 freq = params->frequency;
 
@@ -213,7 +214,7 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
                freq = 2150000; /* satellite IF is 950..2150MHz */
 
        /* decide which VCO to use for the input frequency */
-       for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
+       for(i = 1; (i < ARRAY_SIZE(osci)) && (osci[i] < freq); i++);
        printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
        band=bandsel[i];
        /* the gain values must be set by SetSymbolrate */
@@ -242,7 +243,7 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
        return 0;
 }
 
-static int pinnsat_pll_init(struct dvb_frontend* fe)
+static int pinnsat_tuner_init(struct dvb_frontend* fe)
 {
        struct dvb_bt8xx_card *card = fe->dvb->priv;
 
@@ -252,7 +253,7 @@ static int pinnsat_pll_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int pinnsat_pll_sleep(struct dvb_frontend* fe)
+static int pinnsat_tuner_sleep(struct dvb_frontend* fe)
 {
        struct dvb_bt8xx_card *card = fe->dvb->priv;
 
@@ -263,12 +264,9 @@ static int pinnsat_pll_sleep(struct dvb_frontend* fe)
 
 static struct cx24110_config pctvsat_config = {
        .demod_address = 0x55,
-       .pll_init = pinnsat_pll_init,
-       .pll_set = cx24108_pll_set,
-       .pll_sleep = pinnsat_pll_sleep,
 };
 
-static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
        u8 cfg, cpump, band_select;
@@ -302,6 +300,8 @@ static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_front
        data[2] = ((div >> 10) & 0x60) | cfg;
        data[3] = (cpump << 6) | band_select;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(card->i2c_adapter, &msg, 1);
        return (div * 166666 - 36000000);
 }
@@ -315,7 +315,6 @@ static int microtune_mt7202dtf_request_firmware(struct dvb_frontend* fe, const s
 
 static struct sp887x_config microtune_mt7202dtf_config = {
        .demod_address = 0x70,
-       .pll_set = microtune_mt7202dtf_pll_set,
        .request_firmware = microtune_mt7202dtf_request_firmware,
 };
 
@@ -342,12 +341,14 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
        u32 div;
        unsigned char bs = 0;
        unsigned char cp = 0;
 
+       if (buf_len < 5) return -EINVAL;
+
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
        if (params->frequency < 150000000)
@@ -388,19 +389,18 @@ static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct
        else
                bs = 0x08;
 
-       pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
+       pllbuf[0] = 0x61;
        pllbuf[1] = div >> 8;
        pllbuf[2] = div & 0xff;
        pllbuf[3] = cp;
        pllbuf[4] = bs;
 
-       return 0;
+       return 5;
 }
 
 static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
        .demod_address = 0x0f,
        .demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
-       .pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
 };
 
 static struct dst_config dst_config = {
@@ -460,7 +460,7 @@ static struct or51211_config or51211_config = {
        .sleep = or51211_sleep,
 };
 
-static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
        struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
        u8 buf[4];
@@ -483,6 +483,8 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        else
                return -EINVAL;
 
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
        i2c_transfer(card->i2c_adapter, &msg, 1);
        return 0;
 }
@@ -490,7 +492,6 @@ static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
 static struct nxt6000_config vp3021_alps_tded4_config = {
        .demod_address = 0x0a,
        .clock_inversion = 1,
-       .pll_set = vp3021_alps_tded4_pll_set,
 };
 
 static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
@@ -511,14 +512,17 @@ static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
        return 0;
 }
 
-static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
        u32 div;
        struct dvb_ofdm_parameters *op = &params->u.ofdm;
 
+       if (buf_len < 5)
+               return -EINVAL;
+
        div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
-       pllbuf[0] = 0xc2;
+       pllbuf[0] = 0x61;
        pllbuf[1] = (div >> 8) & 0x7F;
        pllbuf[2] = div & 0xFF;
        pllbuf[3] = 0x85;
@@ -535,7 +539,7 @@ static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_fronten
        if (op->bandwidth == 8)
                pllbuf[4] |= 0x04;
 
-       return 0;
+       return 5;
 }
 
 static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
@@ -562,20 +566,12 @@ static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
 static struct mt352_config digitv_alps_tded4_config = {
        .demod_address = 0x0a,
        .demod_init = digitv_alps_tded4_demod_init,
-       .pll_set = digitv_alps_tded4_pll_set,
 };
 
-static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
-{
-       struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
-       return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
-}
-
 static struct lgdt330x_config tdvs_tua6034_config = {
        .demod_address    = 0x0e,
        .demod_chip       = LGDT3303,
        .serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-       .pll_set          = tdvs_tua6034_pll_set,
 };
 
 static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
@@ -593,28 +589,30 @@ static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
 
 static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 {
-       int ret;
        struct dst_state* state = NULL;
 
        switch(type) {
        case BTTV_BOARD_DVICO_DVBT_LITE:
-               card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &thomson_dtt7579_config, card->i2c_adapter);
 
                if (card->fe == NULL)
-                       card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
+                       card->fe = dvb_attach(zl10353_attach, &thomson_dtt7579_zl10353_config,
                                                  card->i2c_adapter);
 
                if (card->fe != NULL) {
-                       card->fe->ops->info.frequency_min = 174000000;
-                       card->fe->ops->info.frequency_max = 862000000;
+                       card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;
+                       card->fe->ops.info.frequency_min = 174000000;
+                       card->fe->ops.info.frequency_max = 862000000;
                }
                break;
 
        case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
                lgdt330x_reset(card);
-               card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
-               if (card->fe != NULL)
+               card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter);
+               if (card->fe != NULL) {
+                       dvb_attach(lgh06xf_attach, card->fe, card->i2c_adapter);
                        dprintk ("dvb_bt8xx: lgdt330x detected\n");
+               }
                break;
 
        case BTTV_BOARD_NEBULA_DIGITV:
@@ -625,59 +623,74 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
 
                /* Old Nebula (marked (c)2003 on high profile pci card) has nxt6000 demod */
                digitv_alps_tded4_reset(card);
-               card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
+               card->fe = dvb_attach(nxt6000_attach, &vp3021_alps_tded4_config, card->i2c_adapter);
                if (card->fe != NULL) {
+                       card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
                        dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
                        break;
                }
 
                /* New Nebula (marked (c)2005 on low profile pci card) has mt352 demod */
                digitv_alps_tded4_reset(card);
-               card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &digitv_alps_tded4_config, card->i2c_adapter);
 
-               if (card->fe != NULL)
+               if (card->fe != NULL) {
+                       card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
                        dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
+               }
                break;
 
        case BTTV_BOARD_AVDVBT_761:
-               card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
+               card->fe = dvb_attach(sp887x_attach, &microtune_mt7202dtf_config, card->i2c_adapter);
+               if (card->fe) {
+                       card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
+               }
                break;
 
        case BTTV_BOARD_AVDVBT_771:
-               card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
+               card->fe = dvb_attach(mt352_attach, &advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
                if (card->fe != NULL) {
-                       card->fe->ops->info.frequency_min = 174000000;
-                       card->fe->ops->info.frequency_max = 862000000;
+                       card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
+                       card->fe->ops.info.frequency_min = 174000000;
+                       card->fe->ops.info.frequency_max = 862000000;
                }
                break;
 
        case BTTV_BOARD_TWINHAN_DST:
                /*      DST is not a frontend driver !!!                */
-               state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL);
+               state = kmalloc(sizeof (struct dst_state), GFP_KERNEL);
+               if (!state) {
+                       printk("dvb_bt8xx: No memory\n");
+                       break;
+               }
                /*      Setup the Card                                  */
                state->config = &dst_config;
                state->i2c = card->i2c_adapter;
                state->bt = card->bt;
-
+               state->dst_ca = NULL;
                /*      DST is not a frontend, attaching the ASIC       */
-               if ((dst_attach(state, &card->dvb_adapter)) == NULL) {
+               if (dvb_attach(dst_attach, state, &card->dvb_adapter) == NULL) {
                        printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
                        break;
                }
-               card->fe = &state->frontend;
-
                /*      Attach other DST peripherals if any             */
                /*      Conditional Access device                       */
+               card->fe = &state->frontend;
                if (state->dst_hw_cap & DST_TYPE_HAS_CA)
-                       ret = dst_ca_attach(state, &card->dvb_adapter);
+                       dvb_attach(dst_ca_attach, state, &card->dvb_adapter);
                break;
 
        case BTTV_BOARD_PINNACLESAT:
-               card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
+               card->fe = dvb_attach(cx24110_attach, &pctvsat_config, card->i2c_adapter);
+               if (card->fe) {
+                       card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
+                       card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
+                       card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;
+               }
                break;
 
        case BTTV_BOARD_PC_HDTV:
-               card->fe = or51211_attach(&or51211_config, card->i2c_adapter);
+               card->fe = dvb_attach(or51211_attach, &or51211_config, card->i2c_adapter);
                break;
        }
 
@@ -690,8 +703,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
        else
                if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
                        printk("dvb-bt8xx: Frontend registration failed!\n");
-                       if (card->fe->ops->release)
-                               card->fe->ops->release(card->fe);
+                       dvb_frontend_detach(card->fe);
                        card->fe = NULL;
                }
 }
@@ -908,8 +920,10 @@ static void dvb_bt8xx_remove(struct bttv_sub_device *sub)
        card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
        dvb_dmxdev_release(&card->dmxdev);
        dvb_dmx_release(&card->demux);
-       if (card->fe)
+       if (card->fe) {
                dvb_unregister_frontend(card->fe);
+               dvb_frontend_detach(card->fe);
+       }
        dvb_unregister_adapter(&card->dvb_adapter);
 
        kfree(card);