diff options
Diffstat (limited to 'linux/drivers/media/dvb')
101 files changed, 2513 insertions, 1829 deletions
diff --git a/linux/drivers/media/dvb/b2c2/Kconfig b/linux/drivers/media/dvb/b2c2/Kconfig index d7f1fd5b7..13819e2e0 100644 --- a/linux/drivers/media/dvb/b2c2/Kconfig +++ b/linux/drivers/media/dvb/b2c2/Kconfig @@ -1,13 +1,13 @@ config DVB_B2C2_FLEXCOP tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters" depends on DVB_CORE && I2C - select DVB_STV0299 - select DVB_MT352 - select DVB_MT312 - select DVB_NXT200X - select DVB_STV0297 - select DVB_BCM3510 - select DVB_LGDT330X + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_MT352 if !DVB_FE_CUSTOMISE + select DVB_MT312 if !DVB_FE_CUSTOMISE + select DVB_NXT200X if !DVB_FE_CUSTOMISE + select DVB_STV0297 if !DVB_FE_CUSTOMISE + select DVB_BCM3510 if !DVB_FE_CUSTOMISE + select DVB_LGDT330X if !DVB_FE_CUSTOMISE help Support for the digital TV receiver chip made by B2C2 Inc. included in Technisats PCI cards and USB boxes. diff --git a/linux/drivers/media/dvb/b2c2/flexcop-common.h b/linux/drivers/media/dvb/b2c2/flexcop-common.h index 6162c04bd..49852ba16 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-common.h +++ b/linux/drivers/media/dvb/b2c2/flexcop-common.h @@ -8,7 +8,6 @@ #ifndef __FLEXCOP_COMMON_H__ #define __FLEXCOP_COMMON_H__ -#include <linux/config.h> #include <linux/pci.h> #include "compat.h" #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) diff --git a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 150e75082..d8137a9b4 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -516,7 +516,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) struct dvb_frontend_ops *ops; /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */ - if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = dvb_attach(stv0299_attach, &samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) { ops = &fc->fe->ops; ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params; @@ -530,40 +530,40 @@ int flexcop_frontend_init(struct flexcop_device *fc) info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address); } else /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */ - if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) { + if ((fc->fe = dvb_attach(mt352_attach, &samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) { fc->dev_type = FC_AIR_DVB; fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs; info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address); } else /* try the air atsc 2nd generation (nxt2002) */ - if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = dvb_attach(nxt200x_attach, &samsung_tbmv_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC2; - dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv); + dvb_attach(dvb_pll_attach, fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv); info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address); } else /* try the air atsc 3nd generation (lgdt3303) */ - if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = dvb_attach(lgdt330x_attach, &air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC3; fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address); } else /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */ - if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = dvb_attach(bcm3510_attach, &air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) { fc->dev_type = FC_AIR_ATSC1; info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address); } else /* try the cable dvb (stv0297) */ #ifdef STV0297_CS2 - if ((fc->fe = stv0297_cs2_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = dvb_attach(stv0297_cs2_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) { #else - if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) { #endif fc->dev_type = FC_CABLE; fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address); } else /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ - if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { + if ((fc->fe = dvb_attach(vp310_mt312_attach, &skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) { ops = &fc->fe->ops; ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params; @@ -586,9 +586,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) } else { if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) { err("frontend registration failed!"); - ops = &fc->fe->ops; - if (ops->release != NULL) - ops->release(fc->fe); + dvb_frontend_detach(fc->fe); fc->fe = NULL; return -EINVAL; } @@ -599,8 +597,10 @@ int flexcop_frontend_init(struct flexcop_device *fc) void flexcop_frontend_exit(struct flexcop_device *fc) { - if (fc->init_state & FC_STATE_FE_INIT) + if (fc->init_state & FC_STATE_FE_INIT) { dvb_unregister_frontend(fc->fe); + dvb_frontend_detach(fc->fe); + } fc->init_state &= ~FC_STATE_FE_INIT; } diff --git a/linux/drivers/media/dvb/b2c2/flexcop-pci.c b/linux/drivers/media/dvb/b2c2/flexcop-pci.c index f04041702..eb2e6432c 100644 --- a/linux/drivers/media/dvb/b2c2/flexcop-pci.c +++ b/linux/drivers/media/dvb/b2c2/flexcop-pci.c @@ -294,7 +294,7 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci) pci_set_drvdata(fc_pci->pdev, fc_pci); if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr, - SA_SHIRQ, DRIVER_NAME, fc_pci)) != 0) + IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0) goto err_pci_iounmap; spin_lock_init(&fc_pci->irq_lock); diff --git a/linux/drivers/media/dvb/bt8xx/Kconfig b/linux/drivers/media/dvb/bt8xx/Kconfig index f39400211..fc82b9842 100644 --- a/linux/drivers/media/dvb/bt8xx/Kconfig +++ b/linux/drivers/media/dvb/bt8xx/Kconfig @@ -1,13 +1,13 @@ config DVB_BT8XX tristate "BT8xx based PCI cards" depends on DVB_CORE && PCI && I2C && VIDEO_BT848 - select DVB_MT352 - select DVB_SP887X - select DVB_NXT6000 - select DVB_CX24110 - select DVB_OR51211 - select DVB_LGDT330X - select DVB_ZL10353 + select DVB_MT352 if !DVB_FE_CUSTOMISE + select DVB_SP887X if !DVB_FE_CUSTOMISE + select DVB_NXT6000 if !DVB_FE_CUSTOMISE + select DVB_CX24110 if !DVB_FE_CUSTOMISE + select DVB_OR51211 if !DVB_FE_CUSTOMISE + select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_ZL10353 if !DVB_FE_CUSTOMISE select FW_LOADER help Support for PCI cards based on the Bt8xx PCI bridge. Examples are diff --git a/linux/drivers/media/dvb/bt8xx/bt878.c b/linux/drivers/media/dvb/bt8xx/bt878.c index 761fa6e7d..755822ee6 100644 --- a/linux/drivers/media/dvb/bt8xx/bt878.c +++ b/linux/drivers/media/dvb/bt8xx/bt878.c @@ -488,7 +488,7 @@ static int __devinit bt878_probe(struct pci_dev *dev, btwrite(0, BT848_INT_MASK); result = request_irq(bt->irq, bt878_irq, - SA_SHIRQ | SA_INTERRUPT, "bt878", + IRQF_SHARED | IRQF_DISABLED, "bt878", (void *) bt); if (result == -EINVAL) { printk(KERN_ERR "bt878(%d): Bad irq number or handler\n", diff --git a/linux/drivers/media/dvb/bt8xx/dst.c b/linux/drivers/media/dvb/bt8xx/dst.c index d687a14ec..35278d64b 100644 --- a/linux/drivers/media/dvb/bt8xx/dst.c +++ b/linux/drivers/media/dvb/bt8xx/dst.c @@ -1756,6 +1756,11 @@ struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_ad } state->frontend.demodulator_priv = state; + /* Attach other DST peripherals if any */ + /* Conditional Access device */ + if (state->dst_hw_cap & DST_TYPE_HAS_CA) + dst_ca_attach(state, dvb_adapter); + return state; /* Manu (DST is a card not a frontend) */ } diff --git a/linux/drivers/media/dvb/bt8xx/dst_ca.c b/linux/drivers/media/dvb/bt8xx/dst_ca.c index 199320a40..410fa9096 100644 --- a/linux/drivers/media/dvb/bt8xx/dst_ca.c +++ b/linux/drivers/media/dvb/bt8xx/dst_ca.c @@ -795,12 +795,11 @@ static struct dvb_device dvbdev_ca = { .fops = &dst_ca_fops }; -int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter) +void dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter) { struct dvb_device *dvbdev; dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device"); dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA); - return 0; } EXPORT_SYMBOL(dst_ca_attach); diff --git a/linux/drivers/media/dvb/bt8xx/dst_common.h b/linux/drivers/media/dvb/bt8xx/dst_common.h index c30739587..21d9dc516 100644 --- a/linux/drivers/media/dvb/bt8xx/dst_common.h +++ b/linux/drivers/media/dvb/bt8xx/dst_common.h @@ -185,7 +185,7 @@ int write_dst(struct dst_state *state, u8 * data, u8 len); int read_dst(struct dst_state *state, u8 * ret, u8 len); u8 dst_check_sum(u8 * buf, u32 len); struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter); -int dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter); +void dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter); int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay); int dst_command(struct dst_state* state, u8 * data, u8 len); diff --git a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c index fcc284274..619f8c9df 100644 --- a/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/linux/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -68,7 +68,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; @@ -596,15 +596,14 @@ 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) { @@ -616,7 +615,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE: lgdt330x_reset(card); - card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter); + card->fe = dvb_attach(lgdt330x_attach, &tdvs_tua6034_config, card->i2c_adapter); if (card->fe != NULL) { card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params; dprintk ("dvb_bt8xx: lgdt330x detected\n"); @@ -631,7 +630,7 @@ 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"); @@ -640,7 +639,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) /* 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) { card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs; @@ -649,14 +648,14 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) break; case BTTV_BOARD_AVDVBT_761: - card->fe = sp887x_attach(µtune_mt7202dtf_config, card->i2c_adapter); + card->fe = dvb_attach(sp887x_attach, µtune_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.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs; card->fe->ops.info.frequency_min = 174000000; @@ -673,20 +672,15 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) state->bt = card->bt; /* 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 */ - if (state->dst_hw_cap & DST_TYPE_HAS_CA) - ret = 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; @@ -695,7 +689,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) 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; } @@ -708,8 +702,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; } } @@ -945,8 +938,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); diff --git a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c index 631120de7..48569a792 100644 --- a/linux/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/linux/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -22,7 +22,6 @@ * */ -#include <linux/config.h> #include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> diff --git a/linux/drivers/media/dvb/dvb-core/Kconfig b/linux/drivers/media/dvb/dvb-core/Kconfig index 12ee912a5..785388061 100644 --- a/linux/drivers/media/dvb/dvb-core/Kconfig +++ b/linux/drivers/media/dvb/dvb-core/Kconfig @@ -9,3 +9,14 @@ config DVB_CORE in-kernel drivers will select this automatically if needed. If unsure say N. +config DVB_CORE_ATTACH + bool "Load and attach frontend modules as needed" + depends on DVB_CORE + depends on MODULES + help + Remove the static dependency of DVB card drivers on all + frontend modules for all possible card variants. Instead, + allow the card drivers to only load the frontend modules + they require. This saves several KBytes of memory. + + If unsure say Y. diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c index 2f992b982..ba5ffa981 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1111,18 +1111,42 @@ int dvb_unregister_frontend(struct dvb_frontend* fe) mutex_lock(&frontend_mutex); dvb_unregister_device (fepriv->dvbdev); dvb_frontend_stop (fe); - if (fe->ops.tuner_ops.release) { - fe->ops.tuner_ops.release(fe); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - } - if (fe->ops.release) - fe->ops.release(fe); - else - printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name); + /* fe is invalid now */ kfree(fepriv); mutex_unlock(&frontend_mutex); return 0; } EXPORT_SYMBOL(dvb_unregister_frontend); + +#ifdef CONFIG_DVB_DETACH +void dvb_frontend_detach(struct dvb_frontend* fe) +{ + void *ptr; + + if (fe->ops.release_sec) { + fe->ops.release_sec(fe); + symbol_put_addr(fe->ops.release_sec); + } + if (fe->ops.tuner_ops.release) { + fe->ops.tuner_ops.release(fe); + symbol_put_addr(fe->ops.tuner_ops.release); + } + ptr = (void*)fe->ops.release; + if (ptr) { + fe->ops.release(fe); + symbol_put_addr(ptr); + } +} +#else +void dvb_frontend_detach(struct dvb_frontend* fe) +{ + if (fe->ops.release_sec) + fe->ops.release_sec(fe); + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); + if (fe->ops.release) + fe->ops.release(fe); +} +#endif +EXPORT_SYMBOL(dvb_frontend_detach); diff --git a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h index 2887e2b86..e5d5028b3 100644 --- a/linux/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/linux/drivers/media/dvb/dvb-core/dvb_frontend.h @@ -92,10 +92,13 @@ struct dvb_frontend_ops { struct dvb_frontend_info info; void (*release)(struct dvb_frontend* fe); + void (*release_sec)(struct dvb_frontend* fe); int (*init)(struct dvb_frontend* fe); int (*sleep)(struct dvb_frontend* fe); + int (*write)(struct dvb_frontend* fe, u8* buf, int len); + /* if this is set, it overrides the default swzigzag */ int (*tune)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, @@ -147,7 +150,7 @@ struct dvb_frontend { void* demodulator_priv; void* tuner_priv; void* frontend_priv; - void* misc_priv; + void* sec_priv; }; extern int dvb_register_frontend(struct dvb_adapter* dvb, @@ -155,6 +158,8 @@ extern int dvb_register_frontend(struct dvb_adapter* dvb, extern int dvb_unregister_frontend(struct dvb_frontend* fe); +extern void dvb_frontend_detach(struct dvb_frontend* fe); + extern void dvb_frontend_reinitialise(struct dvb_frontend *fe); extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec); diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index 66d9ffdb4..498b1e1be 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -242,10 +242,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, mutex_unlock(&dvbdev_register_lock); - devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), - S_IFCHR | S_IRUSR | S_IWUSR, - "dvb/adapter%d/%s%d", adap->num, dnames[type], id); - class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), adap->device, "dvb%d.%s%d", adap->num, dnames[type], id); @@ -263,9 +259,6 @@ void dvb_unregister_device(struct dvb_device *dvbdev) if (!dvbdev) return; - devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num, - dnames[dvbdev->type], dvbdev->id); - class_device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num, dvbdev->type, dvbdev->id))); @@ -313,7 +306,6 @@ int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct modu printk ("DVB: registering new adapter (%s).\n", name); - devfs_mk_dir("dvb/adapter%d", num); adap->num = num; adap->name = name; adap->module = module; @@ -330,8 +322,6 @@ EXPORT_SYMBOL(dvb_register_adapter); int dvb_unregister_adapter(struct dvb_adapter *adap) { - devfs_remove("dvb/adapter%d", adap->num); - if (mutex_lock_interruptible(&dvbdev_register_lock)) return -ERESTARTSYS; list_del (&adap->list_head); @@ -421,8 +411,6 @@ static int __init init_dvbdev(void) goto error; } - devfs_mk_dir("dvb"); - dvb_class = class_create(THIS_MODULE, "dvb"); if (IS_ERR(dvb_class)) { retval = PTR_ERR(dvb_class); @@ -439,7 +427,6 @@ error: static void __exit exit_dvbdev(void) { - devfs_remove("dvb"); class_destroy(dvb_class); cdev_del(&dvb_device_cdev); unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.h b/linux/drivers/media/dvb/dvb-core/dvbdev.h index 9ec9cecf5..26e4a9135 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.h +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.h @@ -27,7 +27,6 @@ #include <linux/poll.h> #include <linux/fs.h> #include <linux/list.h> -#include <linux/devfs_fs_kernel.h> #include <linux/smp_lock.h> #include "compat.h" @@ -104,4 +103,26 @@ extern int dvb_usercopy(struct inode *inode, struct file *file, int (*func)(struct inode *inode, struct file *file, unsigned int cmd, void *arg)); +/** generic DVB attach function. */ +#ifdef CONFIG_DVB_CORE_ATTACH +#define dvb_attach(FUNCTION, ARGS...) ({ \ + void *__r = NULL; \ + typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ + if (__a) { \ + __r = (void *) __a(ARGS); \ + if (__r == NULL) \ + symbol_put(FUNCTION); \ + } else { \ + printk(KERN_ERR "DVB: Unable to find symbol "#FUNCTION"()\n"); \ + } \ + __r; \ +}) + +#else +#define dvb_attach(FUNCTION, ARGS...) ({ \ + FUNCTION(ARGS); \ +}) + +#endif + #endif /* #ifndef _DVBDEV_H_ */ diff --git a/linux/drivers/media/dvb/dvb-usb/Kconfig b/linux/drivers/media/dvb/dvb-usb/Kconfig index 3bc6722a6..f378a1fe8 100644 --- a/linux/drivers/media/dvb/dvb-usb/Kconfig +++ b/linux/drivers/media/dvb/dvb-usb/Kconfig @@ -25,6 +25,7 @@ config DVB_USB_A800 tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" depends on DVB_USB select DVB_DIB3000MC + select DVB_TUNER_MT2060 help Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. @@ -32,6 +33,7 @@ config DVB_USB_DIBUSB_MB tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" depends on DVB_USB select DVB_DIB3000MB + select DVB_TUNER_MT2060 help Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. @@ -64,6 +66,7 @@ config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB select DVB_DIB3000MC + select DVB_TUNER_MT2060 help Support for 2.0 DVB-T receivers based on reference designs made by DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. @@ -79,16 +82,17 @@ config DVB_USB_UMT_010 tristate "HanfTek UMT-010 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC + select DVB_TUNER_MT2060 help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. config DVB_USB_CXUSB tristate "Conexant USB2.0 hybrid reference design support" depends on DVB_USB - select DVB_CX22702 - select DVB_LGDT330X - select DVB_MT352 - select DVB_ZL10353 + select DVB_CX22702 if !DVB_FE_CUSTOMISE + select DVB_LGDT330X if !DVB_FE_CUSTOMISE + select DVB_MT352 if !DVB_FE_CUSTOMISE + select DVB_ZL10353 if !DVB_FE_CUSTOMISE help Say Y here to support the Conexant USB2.0 hybrid reference design. Currently, only DVB and ATSC modes are supported, analog mode @@ -100,8 +104,8 @@ config DVB_USB_CXUSB config DVB_USB_DIGITV tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support" depends on DVB_USB - select DVB_NXT6000 - select DVB_MT352 + select DVB_NXT6000 if !DVB_FE_CUSTOMISE + select DVB_MT352 if !DVB_FE_CUSTOMISE help Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver. @@ -144,6 +148,7 @@ config DVB_USB_NOVA_T_USB2 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC + select DVB_TUNER_MT2060 help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. diff --git a/linux/drivers/media/dvb/dvb-usb/cxusb.c b/linux/drivers/media/dvb/dvb-usb/cxusb.c index 98dc9914a..addc51391 100644 --- a/linux/drivers/media/dvb/dvb-usb/cxusb.c +++ b/linux/drivers/media/dvb/dvb-usb/cxusb.c @@ -409,7 +409,7 @@ static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d) cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, &b, 1); - if ((d->fe = cx22702_attach(&cxusb_cx22702_config, &d->i2c_adap)) != NULL) + if ((d->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &d->i2c_adap)) != NULL) return 0; return -EIO; @@ -422,7 +422,7 @@ static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_device *d) cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0); - if ((d->fe = lgdt330x_attach(&cxusb_lgdt3303_config, &d->i2c_adap)) != NULL) + if ((d->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &d->i2c_adap)) != NULL) return 0; return -EIO; @@ -435,7 +435,7 @@ static int cxusb_mt352_frontend_attach(struct dvb_usb_device *d) cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0); - if ((d->fe = mt352_attach(&cxusb_mt352_config, &d->i2c_adap)) != NULL) + if ((d->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &d->i2c_adap)) != NULL) return 0; return -EIO; @@ -448,8 +448,8 @@ static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d) cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0); - if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) || - ((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL)) + if (((d->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &d->i2c_adap)) != NULL) || + ((d->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL)) return 0; return -EIO; diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c index abd75b4a3..21e7f4f05 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-common.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-common.c @@ -131,9 +131,6 @@ static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EAGAIN; - if (num > 2) - warn("more than 2 i2c messages at a time is not handled yet. TODO."); - for (i = 0; i < num; i++) { /* write/read request */ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) { @@ -168,31 +165,136 @@ int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val) } EXPORT_SYMBOL(dibusb_read_eeprom_byte); +/* 3000MC/P stuff */ +// Config Adjacent channels Perf -cal22 +static struct dibx000_agc_config dib3000p_mt2060_agc_config = { + .band_caps = BAND_VHF | BAND_UHF, + .setup = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0), + + .agc1_max = 48497, + .agc1_min = 23593, + .agc2_max = 46531, + .agc2_min = 24904, + + .agc1_pt1 = 0x65, + .agc1_pt2 = 0x69, + + .agc1_slope1 = 0x51, + .agc1_slope2 = 0x27, + + .agc2_pt1 = 0, + .agc2_pt2 = 0x33, + + .agc2_slope1 = 0x35, + .agc2_slope2 = 0x37, +}; + +static struct dib3000mc_config stk3000p_dib3000p_config = { + &dib3000p_mt2060_agc_config, + + .max_time = 0x196, + .ln_adc_level = 0x1cc7, + + .output_mpeg2_in_188_bytes = 1, +}; + +static struct dibx000_agc_config dib3000p_panasonic_agc_config = { + .setup = (0 << 15) | (0 << 14) | (1 << 13) | (1 << 12) | (29 << 0), + + .agc1_max = 56361, + .agc1_min = 22282, + .agc2_max = 43254, + .agc2_min = 36045, + + .agc1_pt1 = 0x65, + .agc1_pt2 = 0xff, + + .agc1_slope1 = 0x40, + .agc1_slope2 = 0xff, + + .agc2_pt1 = 0, + .agc2_pt2 = 0x8a, + + .agc2_slope1 = 0x11, + .agc2_slope2 = 0x14, +}; + +static struct dib3000mc_config mod3000p_dib3000p_config = { + &dib3000p_panasonic_agc_config, + + .max_time = 0x51, + .ln_adc_level = 0x1cc7, + + .output_mpeg2_in_188_bytes = 1, +}; + int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d) { - struct dib3000_config demod_cfg; - struct dibusb_state *st = d->priv; - - for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++) - if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) { - d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c; - d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c; - d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl; - return 0; + if (dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000P_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0) { + if (d->priv != NULL) { + struct dibusb_state *st = d->priv; + st->ops.pid_parse = dib3000mc_pid_parse; + st->ops.pid_ctrl = dib3000mc_pid_control; } - + return 0; + } return -ENODEV; } EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach); +static struct mt2060_config stk3000p_mt2060_config = { + 0x60 +}; + int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d) { - d->pll_addr = 0x60; - d->pll_desc = &dvb_pll_env57h1xd5; - - d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c; - d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c; + struct dibusb_state *st = d->priv; + int ret; + u8 a,b; + u16 if1 = 1220; + struct i2c_adapter *tun_i2c; + + // First IF calibration for Liteon Sticks + if (d->udev->descriptor.idVendor == USB_VID_LITEON && + d->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) { + + dibusb_read_eeprom_byte(d,0x7E,&a); + dibusb_read_eeprom_byte(d,0x7F,&b); + + if (a == 0x00) + if1 += b; + else if (a == 0x80) + if1 -= b; + else + warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b); + + } else if (d->udev->descriptor.idVendor == USB_VID_DIBCOM && + d->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) { + u8 desc; + dibusb_read_eeprom_byte(d, 7, &desc); + if (desc == 2) { + a = 127; + do { + dibusb_read_eeprom_byte(d, a, &desc); + a--; + } while (a > 7 && (desc == 0xff || desc == 0x00)); + if (desc & 0x80) + if1 -= (0xff - desc); + else + if1 += desc; + } + } + tun_i2c = dib3000mc_get_tuner_i2c_master(d->fe, 1); + if ((ret = mt2060_attach(d->fe, tun_i2c, &stk3000p_mt2060_config, if1)) != 0) { + /* not found - use panasonic pll parameters */ + if ((ret = dvb_pll_attach(d->fe, 0x60, tun_i2c, &dvb_pll_env57h1xd5)) != 0) + return ret; + } else { + st->mt2060_present = 1; + /* set the correct parameters for the dib3000p */ + dib3000mc_set_config(d->fe, &stk3000p_dib3000p_config); + } return 0; } EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach); @@ -267,6 +369,67 @@ struct dvb_usb_rc_key dibusb_rc_keys[] = { { 0x86, 0x1e, KEY_DOWN }, { 0x86, 0x1f, KEY_LEFT }, { 0x86, 0x1b, KEY_RIGHT }, + + /* Key codes for the DiBcom MOD3000 remote. */ + { 0x80, 0x00, KEY_MUTE }, + { 0x80, 0x01, KEY_TEXT }, + { 0x80, 0x02, KEY_HOME }, + { 0x80, 0x03, KEY_POWER }, + + { 0x80, 0x04, KEY_RED }, + { 0x80, 0x05, KEY_GREEN }, + { 0x80, 0x06, KEY_YELLOW }, + { 0x80, 0x07, KEY_BLUE }, + + { 0x80, 0x08, KEY_DVD }, + { 0x80, 0x09, KEY_AUDIO }, + { 0x80, 0x0a, KEY_MEDIA }, /* Pictures */ + { 0x80, 0x0b, KEY_VIDEO }, + + { 0x80, 0x0c, KEY_BACK }, + { 0x80, 0x0d, KEY_UP }, + { 0x80, 0x0e, KEY_RADIO }, + { 0x80, 0x0f, KEY_EPG }, + + { 0x80, 0x10, KEY_LEFT }, + { 0x80, 0x11, KEY_OK }, + { 0x80, 0x12, KEY_RIGHT }, + { 0x80, 0x13, KEY_UNKNOWN }, /* SAP */ + + { 0x80, 0x14, KEY_TV }, + { 0x80, 0x15, KEY_DOWN }, + { 0x80, 0x16, KEY_MENU }, /* DVD Menu */ + { 0x80, 0x17, KEY_LAST }, + + { 0x80, 0x18, KEY_RECORD }, + { 0x80, 0x19, KEY_STOP }, + { 0x80, 0x1a, KEY_PAUSE }, + { 0x80, 0x1b, KEY_PLAY }, + + { 0x80, 0x1c, KEY_PREVIOUS }, + { 0x80, 0x1d, KEY_REWIND }, + { 0x80, 0x1e, KEY_FASTFORWARD }, + { 0x80, 0x1f, KEY_NEXT}, + + { 0x80, 0x40, KEY_1 }, + { 0x80, 0x41, KEY_2 }, + { 0x80, 0x42, KEY_3 }, + { 0x80, 0x43, KEY_CHANNELUP }, + + { 0x80, 0x44, KEY_4 }, + { 0x80, 0x45, KEY_5 }, + { 0x80, 0x46, KEY_6 }, + { 0x80, 0x47, KEY_CHANNELDOWN }, + + { 0x80, 0x48, KEY_7 }, + { 0x80, 0x49, KEY_8 }, + { 0x80, 0x4a, KEY_9 }, + { 0x80, 0x4b, KEY_VOLUMEUP }, + + { 0x80, 0x4c, KEY_CLEAR }, + { 0x80, 0x4d, KEY_0 }, + { 0x80, 0x4e, KEY_ENTER }, + { 0x80, 0x4f, KEY_VOLUMEDOWN }, }; EXPORT_SYMBOL(dibusb_rc_keys); diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c b/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c index 78acd6540..b4efa3772 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-mb.c @@ -169,7 +169,7 @@ static struct dvb_usb_properties dibusb1_1_properties = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dibusb_rc_keys, - .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ .rc_query = dibusb_rc_query, .i2c_algo = &dibusb_i2c_algo, @@ -247,7 +247,7 @@ static struct dvb_usb_properties dibusb1_1_an2235_properties = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dibusb_rc_keys, - .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ .rc_query = dibusb_rc_query, .i2c_algo = &dibusb_i2c_algo, @@ -304,7 +304,7 @@ static struct dvb_usb_properties dibusb2_0b_properties = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dibusb_rc_keys, - .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ .rc_query = dibusb_rc_query, .i2c_algo = &dibusb_i2c_algo, @@ -355,7 +355,7 @@ static struct dvb_usb_properties artec_t1_usb2_properties = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dibusb_rc_keys, - .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */ + .rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */ .rc_query = dibusb_rc_query, .i2c_algo = &dibusb_i2c_algo, diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c index 87fc1de1f..4c208baad 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c +++ b/linux/drivers/media/dvb/dvb-usb/dibusb-mc.c @@ -28,6 +28,17 @@ static struct usb_device_id dibusb_dib3000mc_table [] = { /* 00 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) }, /* 01 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) }, /* 02 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) }, +/* 03 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_WARM) }, // ( ? ) +/* 04 */ { USB_DEVICE(USB_VID_LITEON, USB_PID_LITEON_DVB_T_COLD) }, +/* 05 */ { USB_DEVICE(USB_VID_LITEON, USB_PID_LITEON_DVB_T_WARM) }, +/* 06 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_DIGIVOX_MINI_SL_COLD) }, +/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_DIGIVOX_MINI_SL_WARM) }, +/* 08 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB2_COLD) }, +/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB2_WARM) }, +/* 10 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_COLD) }, +/* 11 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ARTEC_T14_WARM) }, +/* 12 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_COLD) }, +/* 13 */ { USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_WARM) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table); @@ -50,7 +61,7 @@ static struct dvb_usb_properties dibusb_mc_properties = { .rc_interval = DEFAULT_RC_INTERVAL, .rc_key_map = dibusb_rc_keys, - .rc_key_map_size = 63, /* FIXME */ + .rc_key_map_size = 111, /* FIXME */ .rc_query = dibusb_rc_query, .i2c_algo = &dibusb_i2c_algo, @@ -68,16 +79,38 @@ static struct dvb_usb_properties dibusb_mc_properties = { } }, - .num_device_descs = 2, + .num_device_descs = 7, .devices = { { "DiBcom USB2.0 DVB-T reference design (MOD3000P)", { &dibusb_dib3000mc_table[0], NULL }, { &dibusb_dib3000mc_table[1], NULL }, }, - { "Artec T1 USB2.0 TVBOX (please report the warm ID)", + { "Artec T1 USB2.0 TVBOX (please check the warm ID)", { &dibusb_dib3000mc_table[2], NULL }, - { NULL }, + { &dibusb_dib3000mc_table[3], NULL }, }, + { "LITE-ON USB2.0 DVB-T Tuner", + /* Also rebranded as Intuix S800, Toshiba */ + { &dibusb_dib3000mc_table[4], NULL }, + { &dibusb_dib3000mc_table[5], NULL }, + }, + { "MSI Digivox Mini SL", + { &dibusb_dib3000mc_table[6], NULL }, + { &dibusb_dib3000mc_table[7], NULL }, + }, + { "GRAND - USB2.0 DVB-T adapter", + { &dibusb_dib3000mc_table[8], NULL }, + { &dibusb_dib3000mc_table[9], NULL }, + }, + { "Artec T14 - USB2.0 DVB-T", + { &dibusb_dib3000mc_table[10], NULL }, + { &dibusb_dib3000mc_table[11], NULL }, + }, + { "Leadtek - USB2.0 Winfast DTV dongle", + { &dibusb_dib3000mc_table[12], NULL }, + { &dibusb_dib3000mc_table[13], NULL }, + }, + { NULL }, } }; diff --git a/linux/drivers/media/dvb/dvb-usb/dibusb.h b/linux/drivers/media/dvb/dvb-usb/dibusb.h index 2d99d05c7..a43f87480 100644 --- a/linux/drivers/media/dvb/dvb-usb/dibusb.h +++ b/linux/drivers/media/dvb/dvb-usb/dibusb.h @@ -17,6 +17,8 @@ #include "dvb-usb.h" #include "dib3000.h" +#include "dib3000mc.h" +#include "mt2060.h" /* * protocol of all dibusb related devices @@ -96,6 +98,7 @@ struct dibusb_state { struct dib_fe_xfer_ops ops; + int mt2060_present; /* for RC5 remote control */ int old_toggle; diff --git a/linux/drivers/media/dvb/dvb-usb/digitv.c b/linux/drivers/media/dvb/dvb-usb/digitv.c index 9881e2720..0cea07516 100644 --- a/linux/drivers/media/dvb/dvb-usb/digitv.c +++ b/linux/drivers/media/dvb/dvb-usb/digitv.c @@ -128,11 +128,11 @@ static struct nxt6000_config digitv_nxt6000_config = { static int digitv_frontend_attach(struct dvb_usb_device *d) { - if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) { + if ((d->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &d->i2c_adap)) != NULL) { d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs; return 0; } - if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) { + if ((d->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &d->i2c_adap)) != NULL) { d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params; return 0; } diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c index ec631708c..48ceba61e 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c @@ -179,17 +179,14 @@ int dvb_usb_fe_init(struct dvb_usb_device* d) return 0; } - d->props.frontend_attach(d); - /* re-assign sleep and wakeup functions */ - if (d->fe != NULL) { + if (d->props.frontend_attach(d) == 0 && d->fe != NULL) { d->fe_init = d->fe->ops.init; d->fe->ops.init = dvb_usb_fe_wakeup; d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep; if (dvb_register_frontend(&d->dvb_adap, d->fe)) { err("Frontend registration failed."); - if (d->fe->ops.release) - d->fe->ops.release(d->fe); + dvb_frontend_detach(d->fe); d->fe = NULL; return -ENODEV; } @@ -204,7 +201,9 @@ int dvb_usb_fe_init(struct dvb_usb_device* d) int dvb_usb_fe_exit(struct dvb_usb_device *d) { - if (d->fe != NULL) + if (d->fe != NULL) { dvb_unregister_frontend(d->fe); + dvb_frontend_detach(d->fe); + } return 0; } diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h index f10f49ad9..f841663dd 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb-ids.h @@ -10,51 +10,53 @@ #define _DVB_USB_IDS_H_ /* Vendor IDs */ -#define USB_VID_ADSTECH 0x06e1 -#define USB_VID_ANCHOR 0x0547 -#define USB_VID_WIDEVIEW 0x14aa -#define USB_VID_AVERMEDIA 0x07ca -#define USB_VID_COMPRO 0x185b -#define USB_VID_COMPRO_UNK 0x145f -#define USB_VID_CYPRESS 0x04b4 -#define USB_VID_DIBCOM 0x10b8 -#define USB_VID_DVICO 0x0fe9 -#define USB_VID_EMPIA 0xeb1a -#define USB_VID_GRANDTEC 0x5032 -#define USB_VID_HANFTEK 0x15f4 -#define USB_VID_HAUPPAUGE 0x2040 -#define USB_VID_HYPER_PALTEK 0x1025 -#define USB_VID_KWORLD 0xeb2a -#define USB_VID_KYE 0x0458 -#define USB_VID_MEDION 0x1660 -#define USB_VID_PINNACLE 0x2304 -#define USB_VID_VISIONPLUS 0x13d3 -#define USB_VID_TWINHAN 0x1822 -#define USB_VID_ULTIMA_ELECTRONIC 0x05d8 -#define USB_VID_GENPIX 0x09c0 +#define USB_VID_ADSTECH 0x06e1 +#define USB_VID_ANCHOR 0x0547 +#define USB_VID_AVERMEDIA 0x07ca +#define USB_VID_COMPRO 0x185b +#define USB_VID_COMPRO_UNK 0x145f +#define USB_VID_CYPRESS 0x04b4 +#define USB_VID_DIBCOM 0x10b8 +#define USB_VID_DVICO 0x0fe9 +#define USB_VID_EMPIA 0xeb1a +#define USB_VID_GENPIX 0x09c0 +#define USB_VID_GRANDTEC 0x5032 +#define USB_VID_HANFTEK 0x15f4 +#define USB_VID_HAUPPAUGE 0x2040 +#define USB_VID_HYPER_PALTEK 0x1025 +#define USB_VID_KWORLD 0xeb2a +#define USB_VID_KYE 0x0458 +#define USB_VID_LEADTEK 0x0413 +#define USB_VID_LITEON 0x04ca +#define USB_VID_MEDION 0x1660 +#define USB_VID_PINNACLE 0x2304 +#define USB_VID_VISIONPLUS 0x13d3 +#define USB_VID_TWINHAN 0x1822 +#define USB_VID_ULTIMA_ELECTRONIC 0x05d8 +#define USB_VID_WIDEVIEW 0x14aa /* Product IDs */ #define USB_PID_ADSTECH_USB2_COLD 0xa333 #define USB_PID_ADSTECH_USB2_WARM 0xa334 -#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 -#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 -#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 -#define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801 -#define USB_PID_COMPRO_DVBU2000_COLD 0xd000 -#define USB_PID_COMPRO_DVBU2000_WARM 0xd001 -#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c -#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d +#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001 +#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002 +#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800 +#define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801 +#define USB_PID_COMPRO_DVBU2000_COLD 0xd000 +#define USB_PID_COMPRO_DVBU2000_WARM 0xd001 +#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c +#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d #define USB_PID_DIBCOM_HOOK_DEFAULT 0x0064 -#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 +#define USB_PID_DIBCOM_HOOK_DEFAULT_REENUM 0x0065 #define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8 #define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9 #define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6 #define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7 #define USB_PID_DIBCOM_STK7700 0x1e14 -#define USB_PID_DIBCOM_STK7700_REENUM 0x1e15 -#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 -#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 -#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 +#define USB_PID_DIBCOM_STK7700_REENUM 0x1e15 +#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131 +#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0 +#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1 #define USB_PID_KWORLD_VSTREAM_COLD 0x17de #define USB_PID_KWORLD_VSTREAM_WARM 0x17df #define USB_PID_TWINHAN_VP7041_COLD 0x3201 @@ -69,27 +71,29 @@ #define USB_PID_DNTV_TINYUSB2_WARM 0x3224 #define USB_PID_ULTIMA_TVBOX_COLD 0x8105 #define USB_PID_ULTIMA_TVBOX_WARM 0x8106 -#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 -#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 -#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 -#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 -#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a -#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 -#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 -#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e -#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f -#define USB_PID_HANFTEK_UMT_010_COLD 0x0001 -#define USB_PID_HANFTEK_UMT_010_WARM 0x0015 +#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107 +#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108 +#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235 +#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109 +#define USB_PID_ULTIMA_TVBOX_USB2_WARM 0x810a +#define USB_PID_ARTEC_T14_COLD 0x810b +#define USB_PID_ARTEC_T14_WARM 0x810c +#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613 +#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002 +#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e +#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f +#define USB_PID_HANFTEK_UMT_010_COLD 0x0001 +#define USB_PID_HANFTEK_UMT_010_WARM 0x0015 #define USB_PID_DTT200U_COLD 0x0201 #define USB_PID_DTT200U_WARM 0x0301 -#define USB_PID_WT220U_COLD 0x0222 -#define USB_PID_WT220U_WARM 0x0221 -#define USB_PID_WT220U_FC_COLD 0x0225 -#define USB_PID_WT220U_FC_WARM 0x0226 +#define USB_PID_WT220U_COLD 0x0222 +#define USB_PID_WT220U_WARM 0x0221 +#define USB_PID_WT220U_FC_COLD 0x0225 +#define USB_PID_WT220U_FC_WARM 0x0226 #define USB_PID_WT220U_ZL0353_COLD 0x022a #define USB_PID_WT220U_ZL0353_WARM 0x022b -#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 -#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 +#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300 +#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301 #define USB_PID_NEBULA_DIGITV 0x0201 #define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD 0xd500 @@ -105,8 +109,17 @@ #define USB_PID_MEDION_MD95700 0x0932 #define USB_PID_KYE_DVB_T_COLD 0x701e #define USB_PID_KYE_DVB_T_WARM 0x701f -#define USB_PID_PCTV_200E 0x020e -#define USB_PID_PCTV_400E 0x020f -#define USB_PID_GENPIX_8PSK_COLD 0x0200 -#define USB_PID_GENPIX_8PSK_WARM 0x0201 +#define USB_PID_PCTV_200E 0x020e +#define USB_PID_PCTV_400E 0x020f +#define USB_PID_LITEON_DVB_T_COLD 0xf000 +#define USB_PID_LITEON_DVB_T_WARM 0xf001 +#define USB_PID_DIGIVOX_MINI_SL_COLD 0xe360 +#define USB_PID_DIGIVOX_MINI_SL_WARM 0xe361 +#define USB_PID_GRANDTEC_DVBT_USB2_COLD 0x0bc6 +#define USB_PID_GRANDTEC_DVBT_USB2_WARM 0x0bc7 +#define USB_PID_WINFAST_DTV_DONGLE_COLD 0x6025 +#define USB_PID_WINFAST_DTV_DONGLE_WARM 0x6026 +#define USB_PID_GENPIX_8PSK_COLD 0x0200 +#define USB_PID_GENPIX_8PSK_WARM 0x0201 + #endif diff --git a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h index bf342faa4..4d1913852 100644 --- a/linux/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/linux/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -8,7 +8,6 @@ #ifndef __DVB_USB_H__ #define __DVB_USB_H__ -#include <linux/config.h> #include <linux/input.h> #include <linux/usb.h> #include <linux/firmware.h> diff --git a/linux/drivers/media/dvb/dvb-usb/umt-010.c b/linux/drivers/media/dvb/dvb-usb/umt-010.c index 33343968a..7e94ead18 100644 --- a/linux/drivers/media/dvb/dvb-usb/umt-010.c +++ b/linux/drivers/media/dvb/dvb-usb/umt-010.c @@ -58,7 +58,7 @@ static int umt_mt352_frontend_attach(struct dvb_usb_device *d) umt_config.demod_init = umt_mt352_demod_init; umt_config.demod_address = 0xf; - d->fe = mt352_attach(&umt_config, &d->i2c_adap); + d->fe = dvb_attach(mt352_attach, &umt_config, &d->i2c_adap); return 0; } diff --git a/linux/drivers/media/dvb/frontends/Kconfig b/linux/drivers/media/dvb/frontends/Kconfig index 0ef361f03..191fa4de7 100644 --- a/linux/drivers/media/dvb/frontends/Kconfig +++ b/linux/drivers/media/dvb/frontends/Kconfig @@ -1,48 +1,66 @@ menu "Customise DVB Frontends" depends on DVB_CORE +config DVB_FE_CUSTOMISE + bool "Customise the frontend modules to build" + default N + help + This allows the user to deselect frontend drivers unnecessary + for their hardware from the build. Use this option with care + as deselecting frontends which are in fact necessary will result + in DVB devices which cannot be tuned due to lack of driver support. + + If unsure say N. + comment "DVB-S (satellite) frontends" depends on DVB_CORE config DVB_STV0299 tristate "ST STV0299 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_CX24110 tristate "Conexant CX24110 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_CX24123 tristate "Conexant CX24123 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_TDA8083 tristate "Philips TDA8083 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_MT312 tristate "Zarlink VP310/MT312 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_VES1X93 tristate "VLSI VES1893 or VES1993 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_S5H1420 tristate "Samsung S5H1420 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-S tuner module. Say Y when you want to support this frontend. @@ -52,6 +70,7 @@ comment "DVB-T (terrestrial) frontends" config DVB_SP8870 tristate "Spase sp8870 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE select FW_LOADER help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -64,6 +83,7 @@ config DVB_SP8870 config DVB_SP887X tristate "Spase sp887x based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE select FW_LOADER help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -76,24 +96,28 @@ config DVB_SP887X config DVB_CX22700 tristate "Conexant CX22700 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_CX22702 tristate "Conexant cx22702 demodulator (OFDM)" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_L64781 tristate "LSI L64781" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_TDA1004X tristate "Philips TDA10045H/TDA10046H based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE select FW_LOADER help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -107,24 +131,28 @@ config DVB_TDA1004X config DVB_NXT6000 tristate "NxtWave Communications NXT6000 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_MT352 tristate "Zarlink MT352 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_ZL10353 tristate "Zarlink ZL10353 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_DIB3000MB tristate "DiBcom 3000M-B" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. @@ -132,6 +160,7 @@ config DVB_DIB3000MB config DVB_DIB3000MC tristate "DiBcom 3000P/M-C" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. @@ -142,18 +171,21 @@ comment "DVB-C (cable) frontends" config DVB_VES1820 tristate "VLSI VES1820 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_TDA10021 tristate "Philips TDA10021 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_STV0297 tristate "ST STV0297 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help A DVB-C tuner module. Say Y when you want to support this frontend. @@ -163,6 +195,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends" config DVB_NXT200X tristate "NxtWave Communications NXT2002/NXT2004 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE select FW_LOADER help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want @@ -177,6 +210,7 @@ config DVB_NXT200X config DVB_OR51211 tristate "Oren OR51211 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE select FW_LOADER help An ATSC 8VSB tuner module. Say Y when you want to support this frontend. @@ -189,6 +223,7 @@ config DVB_OR51211 config DVB_OR51132 tristate "Oren OR51132 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE select FW_LOADER help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want @@ -204,6 +239,7 @@ config DVB_OR51132 config DVB_BCM3510 tristate "Broadcom BCM3510" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE select FW_LOADER help An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to @@ -212,24 +248,31 @@ config DVB_BCM3510 config DVB_LGDT330X tristate "LG Electronics LGDT3302/LGDT3303 based" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. - comment "Miscellaneous devices" depends on DVB_CORE config DVB_LNBP21 tristate "LNBP21 SEC controller" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help An SEC control chip. config DVB_ISL6421 tristate "ISL6421 SEC controller" depends on DVB_CORE + default m if DVB_FE_CUSTOMISE help An SEC control chip. +config DVB_TUNER_MT2060 + tristate "Microtune MT2060 silicon IF tuner" + help + A driver for the silicon IF tuner MT2060 from Microtune. + endmenu diff --git a/linux/drivers/media/dvb/frontends/Makefile b/linux/drivers/media/dvb/frontends/Makefile index 5222245c7..a7fbd0fab 100644 --- a/linux/drivers/media/dvb/frontends/Makefile +++ b/linux/drivers/media/dvb/frontends/Makefile @@ -11,8 +11,8 @@ obj-$(CONFIG_DVB_CX22700) += cx22700.o obj-$(CONFIG_DVB_CX24110) += cx24110.o obj-$(CONFIG_DVB_TDA8083) += tda8083.o obj-$(CONFIG_DVB_L64781) += l64781.o -obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o dib3000-common.o -obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dib3000-common.o +obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o +obj-$(CONFIG_DVB_DIB3000MC) += dib3000mc.o dibx000_common.o obj-$(CONFIG_DVB_MT312) += mt312.o obj-$(CONFIG_DVB_VES1820) += ves1820.o obj-$(CONFIG_DVB_VES1X93) += ves1x93.o @@ -33,3 +33,4 @@ obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o obj-$(CONFIG_DVB_CX24123) += cx24123.o obj-$(CONFIG_DVB_LNBP21) += lnbp21.o obj-$(CONFIG_DVB_ISL6421) += isl6421.o +obj-$(CONFIG_DVB_TUNER_MT2060) += mt2060.o diff --git a/linux/drivers/media/dvb/frontends/at76c651.h b/linux/drivers/media/dvb/frontends/at76c651.h index c31db11a2..32b26e368 100644 --- a/linux/drivers/media/dvb/frontends/at76c651.h +++ b/linux/drivers/media/dvb/frontends/at76c651.h @@ -37,7 +37,16 @@ struct at76c651_config u8 demod_address; }; +#if defined(CONFIG_DVB_AT76C651) || defined(CONFIG_DVB_AT76C651_MODULE) extern struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* at76c651_attach(const struct at76c651_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_AT76C651 #endif // AT76C651_H diff --git a/linux/drivers/media/dvb/frontends/bcm3510.h b/linux/drivers/media/dvb/frontends/bcm3510.h index 80f5d0953..6dfa839a7 100644 --- a/linux/drivers/media/dvb/frontends/bcm3510.h +++ b/linux/drivers/media/dvb/frontends/bcm3510.h @@ -34,7 +34,16 @@ struct bcm3510_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; +#if defined(CONFIG_DVB_BCM3510) || defined(CONFIG_DVB_BCM3510_MODULE) extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_BCM3510 #endif diff --git a/linux/drivers/media/dvb/frontends/cx22700.h b/linux/drivers/media/dvb/frontends/cx22700.h index dcd8979c1..10286cc29 100644 --- a/linux/drivers/media/dvb/frontends/cx22700.h +++ b/linux/drivers/media/dvb/frontends/cx22700.h @@ -31,7 +31,16 @@ struct cx22700_config u8 demod_address; }; +#if defined(CONFIG_DVB_CX22700) || defined(CONFIG_DVB_CX22700_MODULE) extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_CX22700 #endif // CX22700_H diff --git a/linux/drivers/media/dvb/frontends/cx22702.h b/linux/drivers/media/dvb/frontends/cx22702.h index 7f2f241e5..bc217ddf0 100644 --- a/linux/drivers/media/dvb/frontends/cx22702.h +++ b/linux/drivers/media/dvb/frontends/cx22702.h @@ -41,7 +41,16 @@ struct cx22702_config u8 output_mode; }; +#if defined(CONFIG_DVB_CX22702) || defined(CONFIG_DVB_CX22702_MODULE) extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_CX22702 #endif // CX22702_H diff --git a/linux/drivers/media/dvb/frontends/cx24110.c b/linux/drivers/media/dvb/frontends/cx24110.c index ce3c7398b..ae9639521 100644 --- a/linux/drivers/media/dvb/frontends/cx24110.c +++ b/linux/drivers/media/dvb/frontends/cx24110.c @@ -1,4 +1,4 @@ -/* + /* cx24110 - Single Chip Satellite Channel Receiver driver module Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@htp-tel.de> based on @@ -311,16 +311,17 @@ static int cx24110_set_symbolrate (struct cx24110_state* state, u32 srate) } -int cx24110_pll_write (struct dvb_frontend* fe, u32 data) +static int _cx24110_pll_write (struct dvb_frontend* fe, u8 *buf, int len) { struct cx24110_state *state = fe->demodulator_priv; + if (len != 3) + return -EINVAL; + /* tuner data is 21 bits long, must be left-aligned in data */ /* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */ /* FIXME (low): add error handling, avoid infinite loops if HW fails... */ - dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data); - cx24110_writereg(state,0x6d,0x30); /* auto mode at 62kHz */ cx24110_writereg(state,0x70,0x15); /* auto mode 21 bits */ @@ -329,19 +330,19 @@ int cx24110_pll_write (struct dvb_frontend* fe, u32 data) cx24110_writereg(state,0x72,0); /* write the topmost 8 bits */ - cx24110_writereg(state,0x72,(data>>24)&0xff); + cx24110_writereg(state,0x72,buf[0]); /* wait for the send to be completed */ while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) ; /* send another 8 bytes */ - cx24110_writereg(state,0x72,(data>>16)&0xff); + cx24110_writereg(state,0x72,buf[1]); while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) ; /* and the topmost 5 bits of this byte */ - cx24110_writereg(state,0x72,(data>>8)&0xff); + cx24110_writereg(state,0x72,buf[2]); while ((cx24110_readreg(state,0x6d)&0xc0)==0x80) ; @@ -642,6 +643,7 @@ static struct dvb_frontend_ops cx24110_ops = { .release = cx24110_release, .init = cx24110_initfe, + .write = _cx24110_pll_write, .set_frontend = cx24110_set_frontend, .get_frontend = cx24110_get_frontend, .read_status = cx24110_read_status, @@ -664,4 +666,3 @@ MODULE_AUTHOR("Peter Hettkamp"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(cx24110_attach); -EXPORT_SYMBOL(cx24110_pll_write); diff --git a/linux/drivers/media/dvb/frontends/cx24110.h b/linux/drivers/media/dvb/frontends/cx24110.h index b354a64e0..c9d5ae250 100644 --- a/linux/drivers/media/dvb/frontends/cx24110.h +++ b/linux/drivers/media/dvb/frontends/cx24110.h @@ -33,9 +33,24 @@ struct cx24110_config u8 demod_address; }; +static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) { + int r = 0; + u8 buf[] = {(u8) (val>>24), (u8) (val>>16), (u8) (val>>8)}; + if (fe->ops.write) + r = fe->ops.write(fe, buf, 3); + return r; +} + +#if defined(CONFIG_DVB_CX24110) || defined(CONFIG_DVB_CX24110_MODULE) extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, struct i2c_adapter* i2c); - -extern int cx24110_pll_write(struct dvb_frontend* fe, u32 data); +#else +static inline struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_CX24110 #endif // CX24110_H diff --git a/linux/drivers/media/dvb/frontends/cx24123.h b/linux/drivers/media/dvb/frontends/cx24123.h index 9606f8259..6a8cb4c41 100644 --- a/linux/drivers/media/dvb/frontends/cx24123.h +++ b/linux/drivers/media/dvb/frontends/cx24123.h @@ -32,7 +32,16 @@ struct cx24123_config int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); }; +#if defined(CONFIG_DVB_CX24123) || defined(CONFIG_DVB_CX24123_MODULE) extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_CX24123 #endif /* CX24123_H */ diff --git a/linux/drivers/media/dvb/frontends/dib3000-common.c b/linux/drivers/media/dvb/frontends/dib3000-common.c deleted file mode 100644 index 1a4f1f7c2..000000000 --- a/linux/drivers/media/dvb/frontends/dib3000-common.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "dib3000-common.h" - -#ifdef CONFIG_DVB_DIBCOM_DEBUG -static int debug; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able))."); -#endif -#define deb_info(args...) dprintk(0x01,args) -#define deb_i2c(args...) dprintk(0x02,args) -#define deb_srch(args...) dprintk(0x04,args) - - -int dib3000_read_reg(struct dib3000_state *state, u16 reg) -{ - u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff }; - u8 rb[2]; - struct i2c_msg msg[] = { - { .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 }, - { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 }, - }; - - if (i2c_transfer(state->i2c, msg, 2) != 2) - deb_i2c("i2c read error\n"); - - deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg, - (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]); - - return (rb[0] << 8) | rb[1]; -} - -int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val) -{ - u8 b[] = { - (reg >> 8) & 0xff, reg & 0xff, - (val >> 8) & 0xff, val & 0xff, - }; - struct i2c_msg msg[] = { - { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 } - }; - deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val); - - return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0; -} - -int dib3000_search_status(u16 irq,u16 lock) -{ - if (irq & 0x02) { - if (lock & 0x01) { - deb_srch("auto search succeeded\n"); - return 1; // auto search succeeded - } else { - deb_srch("auto search not successful\n"); - return 0; // auto search failed - } - } else if (irq & 0x01) { - deb_srch("auto search failed\n"); - return 0; // auto search failed - } - return -1; // try again -} - -/* for auto search */ -u16 dib3000_seq[2][2][2] = /* fft,gua, inv */ - { /* fft */ - { /* gua */ - { 0, 1 }, /* 0 0 { 0,1 } */ - { 3, 9 }, /* 0 1 { 0,1 } */ - }, - { - { 2, 5 }, /* 1 0 { 0,1 } */ - { 6, 11 }, /* 1 1 { 0,1 } */ - } - }; - -MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de"); -MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(dib3000_seq); - -EXPORT_SYMBOL(dib3000_read_reg); -EXPORT_SYMBOL(dib3000_write_reg); -EXPORT_SYMBOL(dib3000_search_status); diff --git a/linux/drivers/media/dvb/frontends/dib3000-common.h b/linux/drivers/media/dvb/frontends/dib3000-common.h deleted file mode 100644 index be1c0d3e1..000000000 --- a/linux/drivers/media/dvb/frontends/dib3000-common.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * .h-files for the common use of the frontend drivers made by DiBcom - * DiBcom 3000M-B/C, 3000P - * - * DiBcom (http://www.dibcom.fr/) - * - * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) - * - * based on GPL code from DibCom, which has - * - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - * Acknowledgements - * - * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver - * sources, on which this driver (and the dvb-dibusb) are based. - * - * see Documentation/dvb/README.dibusb for more information - * - */ - -#ifndef DIB3000_COMMON_H -#define DIB3000_COMMON_H - -#include "dvb_frontend.h" -#include "dib3000.h" - -/* info and err, taken from usb.h, if there is anything available like by default. */ -#define err(format, arg...) printk(KERN_ERR "dib3000: " format "\n" , ## arg) -#define info(format, arg...) printk(KERN_INFO "dib3000: " format "\n" , ## arg) -#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg) - -/* frontend state */ -struct dib3000_state { - struct i2c_adapter* i2c; - -/* configuration settings */ - struct dib3000_config config; - - struct dvb_frontend frontend; - int timing_offset; - int timing_offset_comp_done; - - fe_bandwidth_t last_tuned_bw; - u32 last_tuned_freq; -}; - -/* commonly used methods by the dib3000mb/mc/p frontend */ -extern int dib3000_read_reg(struct dib3000_state *state, u16 reg); -extern int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val); - -extern int dib3000_search_status(u16 irq,u16 lock); - -/* handy shortcuts */ -#define rd(reg) dib3000_read_reg(state,reg) - -#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \ - { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; } - -#define wr_foreach(a,v) { int i; \ - if (sizeof(a) != sizeof(v)) \ - err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\ - for (i=0; i < sizeof(a)/sizeof(u16); i++) \ - wr(a[i],v[i]); \ - } - -#define set_or(reg,val) wr(reg,rd(reg) | val) - -#define set_and(reg,val) wr(reg,rd(reg) & val) - - -/* debug */ - -#ifdef CONFIG_DVB_DIBCOM_DEBUG -#define dprintk(level,args...) \ - do { if ((debug & level)) { printk(args); } } while (0) -#else -#define dprintk(args...) do { } while (0) -#endif - -/* mask for enabling a specific pid for the pid_filter */ -#define DIB3000_ACTIVATE_PID_FILTERING (0x2000) - -/* common values for tuning */ -#define DIB3000_ALPHA_0 ( 0) -#define DIB3000_ALPHA_1 ( 1) -#define DIB3000_ALPHA_2 ( 2) -#define DIB3000_ALPHA_4 ( 4) - -#define DIB3000_CONSTELLATION_QPSK ( 0) -#define DIB3000_CONSTELLATION_16QAM ( 1) -#define DIB3000_CONSTELLATION_64QAM ( 2) - -#define DIB3000_GUARD_TIME_1_32 ( 0) -#define DIB3000_GUARD_TIME_1_16 ( 1) -#define DIB3000_GUARD_TIME_1_8 ( 2) -#define DIB3000_GUARD_TIME_1_4 ( 3) - -#define DIB3000_TRANSMISSION_MODE_2K ( 0) -#define DIB3000_TRANSMISSION_MODE_8K ( 1) - -#define DIB3000_SELECT_LP ( 0) -#define DIB3000_SELECT_HP ( 1) - -#define DIB3000_FEC_1_2 ( 1) -#define DIB3000_FEC_2_3 ( 2) -#define DIB3000_FEC_3_4 ( 3) -#define DIB3000_FEC_5_6 ( 5) -#define DIB3000_FEC_7_8 ( 7) - -#define DIB3000_HRCH_OFF ( 0) -#define DIB3000_HRCH_ON ( 1) - -#define DIB3000_DDS_INVERSION_OFF ( 0) -#define DIB3000_DDS_INVERSION_ON ( 1) - -#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8)) -#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7))) - -/* for auto search */ -extern u16 dib3000_seq[2][2][2]; - -#define DIB3000_REG_MANUFACTOR_ID ( 1025) -#define DIB3000_I2C_ID_DIBCOM (0x01b3) - -#define DIB3000_REG_DEVICE_ID ( 1026) -#define DIB3000MB_DEVICE_ID (0x3000) -#define DIB3000MC_DEVICE_ID (0x3001) -#define DIB3000P_DEVICE_ID (0x3002) - -#endif // DIB3000_COMMON_H diff --git a/linux/drivers/media/dvb/frontends/dib3000.h b/linux/drivers/media/dvb/frontends/dib3000.h index ec927628d..0caac3f0f 100644 --- a/linux/drivers/media/dvb/frontends/dib3000.h +++ b/linux/drivers/media/dvb/frontends/dib3000.h @@ -41,9 +41,16 @@ struct dib_fe_xfer_ops int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl); }; +#if defined(CONFIG_DVB_DIB3000MB) || defined(CONFIG_DVB_DIB3000MB_MODULE) extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops); +#else +static inline struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, + struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_DIB3000MB -extern struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config, - struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops); #endif // DIB3000_H diff --git a/linux/drivers/media/dvb/frontends/dib3000mb.c b/linux/drivers/media/dvb/frontends/dib3000mb.c index 7c6dc7e30..adbabfdb0 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mb.c +++ b/linux/drivers/media/dvb/frontends/dib3000mb.c @@ -21,7 +21,6 @@ * */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> @@ -30,9 +29,10 @@ #include <linux/string.h> #include <linux/slab.h> -#include "dib3000-common.h" -#include "dib3000mb_priv.h" +#include "dvb_frontend.h" + #include "dib3000.h" +#include "dib3000mb_priv.h" /* Version information */ #define DRIVER_VERSION "0.1" @@ -45,10 +45,81 @@ module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able))."); #endif #define deb_info(args...) dprintk(0x01,args) +#define deb_i2c(args...) dprintk(0x02,args) +#define deb_srch(args...) dprintk(0x04,args) +#define deb_info(args...) dprintk(0x01,args) #define deb_xfer(args...) dprintk(0x02,args) #define deb_setf(args...) dprintk(0x04,args) #define deb_getf(args...) dprintk(0x08,args) +#ifdef CONFIG_DVB_DIBCOM_DEBUG +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able))."); +#endif + +static int dib3000_read_reg(struct dib3000_state *state, u16 reg) +{ + u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff }; + u8 rb[2]; + struct i2c_msg msg[] = { + { .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 }, + { .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 }, + }; + + if (i2c_transfer(state->i2c, msg, 2) != 2) + deb_i2c("i2c read error\n"); + + deb_i2c("reading i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg, + (rb[0] << 8) | rb[1],(rb[0] << 8) | rb[1]); + + return (rb[0] << 8) | rb[1]; +} + +static int dib3000_write_reg(struct dib3000_state *state, u16 reg, u16 val) +{ + u8 b[] = { + (reg >> 8) & 0xff, reg & 0xff, + (val >> 8) & 0xff, val & 0xff, + }; + struct i2c_msg msg[] = { + { .addr = state->config.demod_address, .flags = 0, .buf = b, .len = 4 } + }; + deb_i2c("writing i2c bus (reg: %5d 0x%04x, val: %5d 0x%04x)\n",reg,reg,val,val); + + return i2c_transfer(state->i2c,msg, 1) != 1 ? -EREMOTEIO : 0; +} + +static int dib3000_search_status(u16 irq,u16 lock) +{ + if (irq & 0x02) { + if (lock & 0x01) { + deb_srch("auto search succeeded\n"); + return 1; // auto search succeeded + } else { + deb_srch("auto search not successful\n"); + return 0; // auto search failed + } + } else if (irq & 0x01) { + deb_srch("auto search failed\n"); + return 0; // auto search failed + } + return -1; // try again +} + +/* for auto search */ +static u16 dib3000_seq[2][2][2] = /* fft,gua, inv */ + { /* fft */ + { /* gua */ + { 0, 1 }, /* 0 0 { 0,1 } */ + { 3, 9 }, /* 0 1 { 0,1 } */ + }, + { + { 2, 5 }, /* 1 0 { 0,1 } */ + { 6, 11 }, /* 1 1 { 0,1 } */ + } + }; + static int dib3000mb_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep); diff --git a/linux/drivers/media/dvb/frontends/dib3000mb_priv.h b/linux/drivers/media/dvb/frontends/dib3000mb_priv.h index 999b19047..1a12747fd 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mb_priv.h +++ b/linux/drivers/media/dvb/frontends/dib3000mb_priv.h @@ -13,6 +13,99 @@ #ifndef __DIB3000MB_PRIV_H_INCLUDED__ #define __DIB3000MB_PRIV_H_INCLUDED__ +/* info and err, taken from usb.h, if there is anything available like by default. */ +#define err(format, arg...) printk(KERN_ERR "dib3000: " format "\n" , ## arg) +#define info(format, arg...) printk(KERN_INFO "dib3000: " format "\n" , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "dib3000: " format "\n" , ## arg) + +/* handy shortcuts */ +#define rd(reg) dib3000_read_reg(state,reg) + +#define wr(reg,val) if (dib3000_write_reg(state,reg,val)) \ + { err("while sending 0x%04x to 0x%04x.",val,reg); return -EREMOTEIO; } + +#define wr_foreach(a,v) { int i; \ + if (sizeof(a) != sizeof(v)) \ + err("sizeof: %zu %zu is different",sizeof(a),sizeof(v));\ + for (i=0; i < sizeof(a)/sizeof(u16); i++) \ + wr(a[i],v[i]); \ + } + +#define set_or(reg,val) wr(reg,rd(reg) | val) + +#define set_and(reg,val) wr(reg,rd(reg) & val) + +/* debug */ + +#ifdef CONFIG_DVB_DIBCOM_DEBUG +#define dprintk(level,args...) \ + do { if ((debug & level)) { printk(args); } } while (0) +#else +#define dprintk(args...) do { } while (0) +#endif + +/* mask for enabling a specific pid for the pid_filter */ +#define DIB3000_ACTIVATE_PID_FILTERING (0x2000) + +/* common values for tuning */ +#define DIB3000_ALPHA_0 ( 0) +#define DIB3000_ALPHA_1 ( 1) +#define DIB3000_ALPHA_2 ( 2) +#define DIB3000_ALPHA_4 ( 4) + +#define DIB3000_CONSTELLATION_QPSK ( 0) +#define DIB3000_CONSTELLATION_16QAM ( 1) +#define DIB3000_CONSTELLATION_64QAM ( 2) + +#define DIB3000_GUARD_TIME_1_32 ( 0) +#define DIB3000_GUARD_TIME_1_16 ( 1) +#define DIB3000_GUARD_TIME_1_8 ( 2) +#define DIB3000_GUARD_TIME_1_4 ( 3) + +#define DIB3000_TRANSMISSION_MODE_2K ( 0) +#define DIB3000_TRANSMISSION_MODE_8K ( 1) + +#define DIB3000_SELECT_LP ( 0) +#define DIB3000_SELECT_HP ( 1) + +#define DIB3000_FEC_1_2 ( 1) +#define DIB3000_FEC_2_3 ( 2) +#define DIB3000_FEC_3_4 ( 3) +#define DIB3000_FEC_5_6 ( 5) +#define DIB3000_FEC_7_8 ( 7) + +#define DIB3000_HRCH_OFF ( 0) +#define DIB3000_HRCH_ON ( 1) + +#define DIB3000_DDS_INVERSION_OFF ( 0) +#define DIB3000_DDS_INVERSION_ON ( 1) + +#define DIB3000_TUNER_WRITE_ENABLE(a) (0xffff & (a << 8)) +#define DIB3000_TUNER_WRITE_DISABLE(a) (0xffff & ((a << 8) | (1 << 7))) + +#define DIB3000_REG_MANUFACTOR_ID ( 1025) +#define DIB3000_I2C_ID_DIBCOM (0x01b3) + +#define DIB3000_REG_DEVICE_ID ( 1026) +#define DIB3000MB_DEVICE_ID (0x3000) +#define DIB3000MC_DEVICE_ID (0x3001) +#define DIB3000P_DEVICE_ID (0x3002) + +/* frontend state */ +struct dib3000_state { + struct i2c_adapter* i2c; + +/* configuration settings */ + struct dib3000_config config; + + struct dvb_frontend frontend; + int timing_offset; + int timing_offset_comp_done; + + fe_bandwidth_t last_tuned_bw; + u32 last_tuned_freq; +}; + /* register addresses and some of their default values */ /* restart subsystems */ diff --git a/linux/drivers/media/dvb/frontends/dib3000mc.c b/linux/drivers/media/dvb/frontends/dib3000mc.c index 6c3be2529..3e68fd8e3 100644 --- a/linux/drivers/media/dvb/frontends/dib3000mc.c +++ b/linux/drivers/media/dvb/frontends/dib3000mc.c @@ -1,914 +1,954 @@ /* - * Frontend driver for mobile DVB-T demodulator DiBcom 3000P/M-C - * DiBcom (http://www.dibcom.fr/) + * Driver for DiBcom DiB3000MC/P-demodulator. * + * Copyright (C) 2004-6 DiBcom (http://www.dibcom.fr/) * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) * - * based on GPL code from DiBCom, which has + * This code is partially based on the previous dib3000mc.c . * - * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr) - * - * This program is free software; you can redistribute it and/or + * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2. - * - * Acknowledgements - * - * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver - * sources, on which this driver (and the dvb-dibusb) are based. - * - * see Documentation/dvb/README.dibusb for more information - * */ -#include <linux/config.h> + #include <linux/kernel.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/string.h> -#include <linux/slab.h> - -#include "dib3000-common.h" -#include "dib3000mc_priv.h" -#include "dib3000.h" - -/* Version information */ -#define DRIVER_VERSION "0.1" -#define DRIVER_DESC "DiBcom 3000M-C DVB-T demodulator" -#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de" - -#ifdef CONFIG_DVB_DIBCOM_DEBUG +#include <linux/i2c.h> +//#include <linux/init.h> +//#include <linux/delay.h> +//#include <linux/string.h> +//#include <linux/slab.h> + +#include "dvb_frontend.h" + +#include "dib3000mc.h" + static int debug; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=stat (|-able))."); -#endif -#define deb_info(args...) dprintk(0x01,args) -#define deb_xfer(args...) dprintk(0x02,args) -#define deb_setf(args...) dprintk(0x04,args) -#define deb_getf(args...) dprintk(0x08,args) -#define deb_stat(args...) dprintk(0x10,args) - -static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode, - fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth) -{ - switch (transmission_mode) { - case TRANSMISSION_MODE_2K: - wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[0]); - break; - case TRANSMISSION_MODE_8K: - wr_foreach(dib3000mc_reg_fft,dib3000mc_fft_modes[1]); - break; - default: - break; - } +MODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); - switch (bandwidth) { -/* case BANDWIDTH_5_MHZ: - wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[0]); - break; */ - case BANDWIDTH_6_MHZ: - wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[1]); - break; - case BANDWIDTH_7_MHZ: - wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[2]); - break; - case BANDWIDTH_8_MHZ: - wr_foreach(dib3000mc_reg_impulse_noise,dib3000mc_impluse_noise[3]); - break; - default: - break; +#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB3000MC/P:"); printk(args); } } while (0) + +struct dib3000mc_state { + struct dvb_frontend demod; + struct dib3000mc_config *cfg; + + u8 i2c_addr; + struct i2c_adapter *i2c_adap; + + struct dibx000_i2c_master i2c_master; + + fe_bandwidth_t current_bandwidth; + + u16 dev_id; +}; + +static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg) +{ + u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; + u8 rb[2]; + struct i2c_msg msg[2] = { + { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, + { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, + }; + + if (i2c_transfer(state->i2c_adap, msg, 2) != 2) + dprintk("i2c read error on %d\n",reg); + + return (rb[0] << 8) | rb[1]; +} + +static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val) +{ + u8 b[4] = { + (reg >> 8) & 0xff, reg & 0xff, + (val >> 8) & 0xff, val & 0xff, + }; + struct i2c_msg msg = { + .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 + }; + return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; +} + +static void dump_fep(struct dibx000_ofdm_channel *cd) +{ + printk(KERN_DEBUG "DiB3000MC: "); + switch (cd->nfft) { + case 1: printk("8K "); break; + case 2: printk("4K "); break; + case 0: printk("2K "); break; + default: printk("FFT_UNK "); break; } - switch (mode) { - case 0: /* no impulse */ /* fall through */ - wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[0]); - break; - case 1: /* new algo */ - wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[1]); - set_or(DIB3000MC_REG_IMP_NOISE_55,DIB3000MC_IMP_NEW_ALGO(0)); /* gives 1<<10 */ - break; - default: /* old algo */ - wr_foreach(dib3000mc_reg_imp_noise_ctl,dib3000mc_imp_noise_ctl[3]); - break; + printk("1/%i ", 32 / (1 << cd->guard)); + switch (cd->nqam) { + case 0: printk("QPSK "); break; + case 1: printk("16QAM "); break; + case 2: printk("64QAM "); break; + default: printk("QAM_UNK "); break; } - return 0; + printk("ALPHA %i ", cd->vit_alpha); + printk("Code Rate HP %i/%i ", cd->vit_code_rate_hp, cd->vit_code_rate_hp + 1); + printk("Code Rate LP %i/%i ", cd->vit_code_rate_lp, cd->vit_code_rate_lp + 1); + printk("HRCH %i\n", cd->vit_hrch); } -static int dib3000mc_set_timing(struct dib3000_state *state, int upd_offset, - fe_transmit_mode_t fft, fe_bandwidth_t bw) + +static int dib3000mc_identify(struct dib3000mc_state *state) { - u16 timf_msb,timf_lsb; - s32 tim_offset,tim_sgn; - u64 comp1,comp2,comp=0; + u16 value; + if ((value = dib3000mc_read_word(state, 1025)) != 0x01b3) { + dprintk("-E- DiB3000MC/P: wrong Vendor ID (read=0x%x)\n",value); + return -EREMOTEIO; + } - switch (bw) { - case BANDWIDTH_8_MHZ: comp = DIB3000MC_CLOCK_REF*8; break; - case BANDWIDTH_7_MHZ: comp = DIB3000MC_CLOCK_REF*7; break; - case BANDWIDTH_6_MHZ: comp = DIB3000MC_CLOCK_REF*6; break; - default: err("unknown bandwidth (%d)",bw); break; + value = dib3000mc_read_word(state, 1026); + if (value != 0x3001 && value != 0x3002) { + dprintk("-E- DiB3000MC/P: wrong Device ID (%x)\n",value); + return -EREMOTEIO; } - timf_msb = (comp >> 16) & 0xff; - timf_lsb = (comp & 0xffff); + state->dev_id = value; + + dprintk("-I- found DiB3000MC/P: %x\n",state->dev_id); + + return 0; +} + +static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset) +{ +/* + u32 timf_msb, timf_lsb, i; + int tim_sgn ; + LUInt comp1, comp2, comp ; +// u32 tim_offset ; + comp = 27700 * BW_INDEX_TO_KHZ(bw) / 1000; + timf_msb = (comp >> 16) & 0x00FF; + timf_lsb = comp & 0xFFFF; // Update the timing offset ; - if (upd_offset > 0) { - if (!state->timing_offset_comp_done) { - msleep(200); + if (update_offset) { + if (state->timing_offset_comp_done == 0) { + usleep(200000); state->timing_offset_comp_done = 1; } - tim_offset = rd(DIB3000MC_REG_TIMING_OFFS_MSB); + tim_offset = dib3000mc_read_word(state, 416); if ((tim_offset & 0x2000) == 0x2000) - tim_offset |= 0xC000; - if (fft == TRANSMISSION_MODE_2K) - tim_offset <<= 2; + tim_offset |= 0xC000; // PB: This only works if tim_offset is s16 - weird + + if (nfft == 0) + tim_offset = tim_offset << 2; // PB: Do not store the offset for different things in one variable state->timing_offset += tim_offset; } - tim_offset = state->timing_offset; + if (tim_offset < 0) { tim_sgn = 1; tim_offset = -tim_offset; } else tim_sgn = 0; - comp1 = (u32)tim_offset * (u32)timf_lsb ; - comp2 = (u32)tim_offset * (u32)timf_msb ; + comp1 = tim_offset * timf_lsb; + comp2 = tim_offset * timf_msb; comp = ((comp1 >> 16) + comp2) >> 7; if (tim_sgn == 0) - comp = (u32)(timf_msb << 16) + (u32) timf_lsb + comp; + comp = timf_msb * (1<<16) + timf_lsb + comp; else - comp = (u32)(timf_msb << 16) + (u32) timf_lsb - comp ; + comp = timf_msb * (1<<16) + timf_lsb - comp; - timf_msb = (comp >> 16) & 0xff; - timf_lsb = comp & 0xffff; + timf_msb = (comp>>16)&0xFF ; + timf_lsb = comp&0xFFFF; +*/ + u32 timf = 1384402 * (BW_INDEX_TO_KHZ(bw) / 1000); + + dib3000mc_write_word(state, 23, timf >> 16); + dib3000mc_write_word(state, 24, timf & 0xffff); - wr(DIB3000MC_REG_TIMING_FREQ_MSB,timf_msb); - wr(DIB3000MC_REG_TIMING_FREQ_LSB,timf_lsb); return 0; } -static int dib3000mc_init_auto_scan(struct dib3000_state *state, fe_bandwidth_t bw, int boost) +static int dib3000mc_setup_pwm3_state(struct dib3000mc_state *state) { - if (boost) { - wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_ON); + if (state->cfg->pwm3_inversion) { + dib3000mc_write_word(state, 51, (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0)); + dib3000mc_write_word(state, 52, (0 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (2 << 0)); } else { - wr(DIB3000MC_REG_SCAN_BOOST,DIB3000MC_SCAN_BOOST_OFF); - } - switch (bw) { - case BANDWIDTH_8_MHZ: - wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz); - break; - case BANDWIDTH_7_MHZ: - wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_7mhz); - break; - case BANDWIDTH_6_MHZ: - wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_6mhz); - break; -/* case BANDWIDTH_5_MHZ: - wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_5mhz); - break;*/ - case BANDWIDTH_AUTO: - return -EOPNOTSUPP; - default: - err("unknown bandwidth value (%d).",bw); - return -EINVAL; - } - if (boost) { - u32 timeout = (rd(DIB3000MC_REG_BW_TIMOUT_MSB) << 16) + - rd(DIB3000MC_REG_BW_TIMOUT_LSB); - timeout *= 85; timeout >>= 7; - wr(DIB3000MC_REG_BW_TIMOUT_MSB,(timeout >> 16) & 0xffff); - wr(DIB3000MC_REG_BW_TIMOUT_LSB,timeout & 0xffff); + dib3000mc_write_word(state, 51, (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0)); + dib3000mc_write_word(state, 52, (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0)); } + + if (state->cfg->use_pwm3) + dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0)); + else + dib3000mc_write_word(state, 245, 0); + + dib3000mc_write_word(state, 1040, 0x3); return 0; } -static int dib3000mc_set_adp_cfg(struct dib3000_state *state, fe_modulation_t con) +static int dib3000mc_set_output_mode(struct dib3000mc_state *state, int mode) { - switch (con) { - case QAM_64: - wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[2]); - break; - case QAM_16: - wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[1]); - break; - case QPSK: - wr_foreach(dib3000mc_reg_adp_cfg,dib3000mc_adp_cfg[0]); - break; - case QAM_AUTO: + int ret = 0; + u16 fifo_threshold = 1792; + u16 outreg = 0; + u16 outmode = 0; + u16 elecout = 1; + u16 smo_reg = (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (1 << 1) | 0 ; //smo_mode = 1 + + dprintk("-I- Setting output mode for demod %p to %d\n", + &state->demod, mode); + + switch (mode) { + case OUTMODE_HIGH_Z: // disable + elecout = 0; + break; + case OUTMODE_MPEG2_PAR_GATED_CLK: // STBs with parallel gated clock + outmode = 0; + break; + case OUTMODE_MPEG2_PAR_CONT_CLK: // STBs with parallel continues clock + outmode = 1; + break; + case OUTMODE_MPEG2_SERIAL: // STBs with serial input + outmode = 2; + break; + case OUTMODE_MPEG2_FIFO: // e.g. USB feeding + elecout = 3; + /*ADDR @ 206 : + P_smo_error_discard [1;6:6] = 0 + P_smo_rs_discard [1;5:5] = 0 + P_smo_pid_parse [1;4:4] = 0 + P_smo_fifo_flush [1;3:3] = 0 + P_smo_mode [2;2:1] = 11 + P_smo_ovf_prot [1;0:0] = 0 + */ + smo_reg = (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) |(3 << 1) | 0; + fifo_threshold = 512; + outmode = 5; + break; + case OUTMODE_DIVERSITY: + outmode = 4; + elecout = 1; break; default: - warn("unkown constellation."); + dprintk("Unhandled output_mode passed to be set for demod %p\n",&state->demod); + outmode = 0; break; } - return 0; + + if ((state->cfg->output_mpeg2_in_188_bytes)) + smo_reg |= (1 << 5) ; //P_smo_rs_discard [1;5:5] = 1 + + outreg = dib3000mc_read_word(state, 244) & 0x07FF; + outreg |= (outmode << 11); + ret |= dib3000mc_write_word(state, 244, outreg); + ret |= dib3000mc_write_word(state, 206, smo_reg); /*smo_ mode*/ + ret |= dib3000mc_write_word(state, 207, fifo_threshold); /* synchronous fread */ + ret |= dib3000mc_write_word(state, 1040, elecout); /* P_out_cfg */ + return ret; } -static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_frontend_parameters *fep, int *auto_val) +static int dib3000mc_set_bandwidth(struct dvb_frontend *demod, u8 bw) { - struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm; - fe_code_rate_t fe_cr = FEC_NONE; - u8 fft=0, guard=0, qam=0, alpha=0, sel_hp=0, cr=0, hrch=0; - int seq; + struct dib3000mc_state *state = demod->demodulator_priv; + u16 bw_cfg[6] = { 0 }; + u16 imp_bw_cfg[3] = { 0 }; + u16 reg; - switch (ofdm->transmission_mode) { - case TRANSMISSION_MODE_2K: fft = DIB3000_TRANSMISSION_MODE_2K; break; - case TRANSMISSION_MODE_8K: fft = DIB3000_TRANSMISSION_MODE_8K; break; - case TRANSMISSION_MODE_AUTO: break; - default: return -EINVAL; - } - switch (ofdm->guard_interval) { - case GUARD_INTERVAL_1_32: guard = DIB3000_GUARD_TIME_1_32; break; - case GUARD_INTERVAL_1_16: guard = DIB3000_GUARD_TIME_1_16; break; - case GUARD_INTERVAL_1_8: guard = DIB3000_GUARD_TIME_1_8; break; - case GUARD_INTERVAL_1_4: guard = DIB3000_GUARD_TIME_1_4; break; - case GUARD_INTERVAL_AUTO: break; - default: return -EINVAL; - } - switch (ofdm->constellation) { - case QPSK: qam = DIB3000_CONSTELLATION_QPSK; break; - case QAM_16: qam = DIB3000_CONSTELLATION_16QAM; break; - case QAM_64: qam = DIB3000_CONSTELLATION_64QAM; break; - case QAM_AUTO: break; - default: return -EINVAL; - } - switch (ofdm->hierarchy_information) { - case HIERARCHY_NONE: /* fall through */ - case HIERARCHY_1: alpha = DIB3000_ALPHA_1; break; - case HIERARCHY_2: alpha = DIB3000_ALPHA_2; break; - case HIERARCHY_4: alpha = DIB3000_ALPHA_4; break; - case HIERARCHY_AUTO: break; - default: return -EINVAL; - } - if (ofdm->hierarchy_information == HIERARCHY_NONE) { - hrch = DIB3000_HRCH_OFF; - sel_hp = DIB3000_SELECT_HP; - fe_cr = ofdm->code_rate_HP; - } else if (ofdm->hierarchy_information != HIERARCHY_AUTO) { - hrch = DIB3000_HRCH_ON; - sel_hp = DIB3000_SELECT_LP; - fe_cr = ofdm->code_rate_LP; - } - switch (fe_cr) { - case FEC_1_2: cr = DIB3000_FEC_1_2; break; - case FEC_2_3: cr = DIB3000_FEC_2_3; break; - case FEC_3_4: cr = DIB3000_FEC_3_4; break; - case FEC_5_6: cr = DIB3000_FEC_5_6; break; - case FEC_7_8: cr = DIB3000_FEC_7_8; break; - case FEC_NONE: break; - case FEC_AUTO: break; - default: return -EINVAL; - } +/* settings here are for 27.7MHz */ + switch (bw) { + case BANDWIDTH_8_MHZ: + bw_cfg[0] = 0x0019; bw_cfg[1] = 0x5c30; bw_cfg[2] = 0x0054; bw_cfg[3] = 0x88a0; bw_cfg[4] = 0x01a6; bw_cfg[5] = 0xab20; + imp_bw_cfg[0] = 0x04db; imp_bw_cfg[1] = 0x00db; imp_bw_cfg[2] = 0x00b7; + break; - wr(DIB3000MC_REG_DEMOD_PARM,DIB3000MC_DEMOD_PARM(alpha,qam,guard,fft)); - wr(DIB3000MC_REG_HRCH_PARM,DIB3000MC_HRCH_PARM(sel_hp,cr,hrch)); + case BANDWIDTH_7_MHZ: + bw_cfg[0] = 0x001c; bw_cfg[1] = 0xfba5; bw_cfg[2] = 0x0060; bw_cfg[3] = 0x9c25; bw_cfg[4] = 0x01e3; bw_cfg[5] = 0x0cb7; + imp_bw_cfg[0] = 0x04c0; imp_bw_cfg[1] = 0x00c0; imp_bw_cfg[2] = 0x00a0; + break; - switch (fep->inversion) { - case INVERSION_OFF: - wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF); + case BANDWIDTH_6_MHZ: + bw_cfg[0] = 0x0021; bw_cfg[1] = 0xd040; bw_cfg[2] = 0x0070; bw_cfg[3] = 0xb62b; bw_cfg[4] = 0x0233; bw_cfg[5] = 0x8ed5; + imp_bw_cfg[0] = 0x04a5; imp_bw_cfg[1] = 0x00a5; imp_bw_cfg[2] = 0x0089; break; - case INVERSION_AUTO: /* fall through */ - case INVERSION_ON: - wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_ON); + + case 255 /* BANDWIDTH_5_MHZ */: + bw_cfg[0] = 0x0028; bw_cfg[1] = 0x9380; bw_cfg[2] = 0x0087; bw_cfg[3] = 0x4100; bw_cfg[4] = 0x02a4; bw_cfg[5] = 0x4500; + imp_bw_cfg[0] = 0x0489; imp_bw_cfg[1] = 0x0089; imp_bw_cfg[2] = 0x0072; break; - default: - return -EINVAL; + + default: return -EINVAL; } - seq = dib3000_seq - [ofdm->transmission_mode == TRANSMISSION_MODE_AUTO] - [ofdm->guard_interval == GUARD_INTERVAL_AUTO] - [fep->inversion == INVERSION_AUTO]; - - deb_setf("seq? %d\n", seq); - wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS(seq,1)); - *auto_val = ofdm->constellation == QAM_AUTO || - ofdm->hierarchy_information == HIERARCHY_AUTO || - ofdm->guard_interval == GUARD_INTERVAL_AUTO || - ofdm->transmission_mode == TRANSMISSION_MODE_AUTO || - fe_cr == FEC_AUTO || - fep->inversion == INVERSION_AUTO; - return 0; -} + for (reg = 6; reg < 12; reg++) + dib3000mc_write_word(state, reg, bw_cfg[reg - 6]); + dib3000mc_write_word(state, 12, 0x0000); + dib3000mc_write_word(state, 13, 0x03e8); + dib3000mc_write_word(state, 14, 0x0000); + dib3000mc_write_word(state, 15, 0x03f2); + dib3000mc_write_word(state, 16, 0x0001); + dib3000mc_write_word(state, 17, 0xb0d0); + // P_sec_len + dib3000mc_write_word(state, 18, 0x0393); + dib3000mc_write_word(state, 19, 0x8700); -static int dib3000mc_get_frontend(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep) -{ - struct dib3000_state* state = fe->demodulator_priv; - struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm; - fe_code_rate_t *cr; - u16 tps_val,cr_val; - int inv_test1,inv_test2; - u32 dds_val, threshold = 0x1000000; - - if (!(rd(DIB3000MC_REG_LOCK_507) & DIB3000MC_LOCK_507)) - return 0; - - dds_val = (rd(DIB3000MC_REG_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_DDS_FREQ_LSB); - deb_getf("DDS_FREQ: %6x\n",dds_val); - if (dds_val < threshold) - inv_test1 = 0; - else if (dds_val == threshold) - inv_test1 = 1; - else - inv_test1 = 2; - - dds_val = (rd(DIB3000MC_REG_SET_DDS_FREQ_MSB) << 16) + rd(DIB3000MC_REG_SET_DDS_FREQ_LSB); - deb_getf("DDS_SET_FREQ: %6x\n",dds_val); - if (dds_val < threshold) - inv_test2 = 0; - else if (dds_val == threshold) - inv_test2 = 1; - else - inv_test2 = 2; + for (reg = 55; reg < 58; reg++) + dib3000mc_write_word(state, reg, imp_bw_cfg[reg - 55]); - fep->inversion = - ((inv_test2 == 2) && (inv_test1==1 || inv_test1==0)) || - ((inv_test2 == 0) && (inv_test1==1 || inv_test1==2)) ? - INVERSION_ON : INVERSION_OFF; + // Timing configuration + dib3000mc_set_timing(state, 0, bw, 0); - deb_getf("inversion %d %d, %d\n", inv_test2, inv_test1, fep->inversion); + return 0; +} - fep->frequency = state->last_tuned_freq; - fep->u.ofdm.bandwidth= state->last_tuned_bw; +static u16 impulse_noise_val[29] = - tps_val = rd(DIB3000MC_REG_TUNING_PARM); +{ + 0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, 0x3ffe, 0x7f3, + 0x2d94, 0x76, 0x53d, 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, 0x3feb, 0x7d2, + 0x365e, 0x76, 0x48c, 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0000, 0xd +}; - switch (DIB3000MC_TP_QAM(tps_val)) { - case DIB3000_CONSTELLATION_QPSK: - deb_getf("QPSK "); - ofdm->constellation = QPSK; - break; - case DIB3000_CONSTELLATION_16QAM: - deb_getf("QAM16 "); - ofdm->constellation = QAM_16; - break; - case DIB3000_CONSTELLATION_64QAM: - deb_getf("QAM64 "); - ofdm->constellation = QAM_64; - break; - default: - err("Unexpected constellation returned by TPS (%d)", tps_val); - break; +static void dib3000mc_set_impulse_noise(struct dib3000mc_state *state, u8 mode, s16 nfft) +{ + u16 i; + for (i = 58; i < 87; i++) + dib3000mc_write_word(state, i, impulse_noise_val[i-58]); + + if (nfft == 1) { + dib3000mc_write_word(state, 58, 0x3b); + dib3000mc_write_word(state, 84, 0x00); + dib3000mc_write_word(state, 85, 0x8200); } - if (DIB3000MC_TP_HRCH(tps_val)) { - deb_getf("HRCH ON "); - cr = &ofdm->code_rate_LP; - ofdm->code_rate_HP = FEC_NONE; - switch (DIB3000MC_TP_ALPHA(tps_val)) { - case DIB3000_ALPHA_0: - deb_getf("HIERARCHY_NONE "); - ofdm->hierarchy_information = HIERARCHY_NONE; - break; - case DIB3000_ALPHA_1: - deb_getf("HIERARCHY_1 "); - ofdm->hierarchy_information = HIERARCHY_1; - break; - case DIB3000_ALPHA_2: - deb_getf("HIERARCHY_2 "); - ofdm->hierarchy_information = HIERARCHY_2; - break; - case DIB3000_ALPHA_4: - deb_getf("HIERARCHY_4 "); - ofdm->hierarchy_information = HIERARCHY_4; - break; - default: - err("Unexpected ALPHA value returned by TPS (%d)", tps_val); - break; - } - cr_val = DIB3000MC_TP_FEC_CR_LP(tps_val); + dib3000mc_write_word(state, 34, 0x1294); + dib3000mc_write_word(state, 35, 0x1ff8); + if (mode == 1) + dib3000mc_write_word(state, 55, dib3000mc_read_word(state, 55) | (1 << 10)); +} + +static int dib3000mc_init(struct dvb_frontend *demod) +{ + struct dib3000mc_state *state = demod->demodulator_priv; + struct dibx000_agc_config *agc = state->cfg->agc; + + // Restart Configuration + dib3000mc_write_word(state, 1027, 0x8000); + dib3000mc_write_word(state, 1027, 0x0000); + + // power up the demod + mobility configuration + dib3000mc_write_word(state, 140, 0x0000); + dib3000mc_write_word(state, 1031, 0); + + if (state->cfg->mobile_mode) { + dib3000mc_write_word(state, 139, 0x0000); + dib3000mc_write_word(state, 141, 0x0000); + dib3000mc_write_word(state, 175, 0x0002); + dib3000mc_write_word(state, 1032, 0x0000); } else { - deb_getf("HRCH OFF "); - cr = &ofdm->code_rate_HP; - ofdm->code_rate_LP = FEC_NONE; - ofdm->hierarchy_information = HIERARCHY_NONE; - cr_val = DIB3000MC_TP_FEC_CR_HP(tps_val); + dib3000mc_write_word(state, 139, 0x0001); + dib3000mc_write_word(state, 141, 0x0000); + dib3000mc_write_word(state, 175, 0x0000); + dib3000mc_write_word(state, 1032, 0x012C); } + dib3000mc_write_word(state, 1033, 0); - switch (cr_val) { - case DIB3000_FEC_1_2: - deb_getf("FEC_1_2 "); - *cr = FEC_1_2; - break; - case DIB3000_FEC_2_3: - deb_getf("FEC_2_3 "); - *cr = FEC_2_3; - break; - case DIB3000_FEC_3_4: - deb_getf("FEC_3_4 "); - *cr = FEC_3_4; - break; - case DIB3000_FEC_5_6: - deb_getf("FEC_5_6 "); - *cr = FEC_4_5; - break; - case DIB3000_FEC_7_8: - deb_getf("FEC_7_8 "); - *cr = FEC_7_8; - break; - default: - err("Unexpected FEC returned by TPS (%d)", tps_val); - break; - } + // P_clk_cfg + dib3000mc_write_word(state, 1037, 12592); - switch (DIB3000MC_TP_GUARD(tps_val)) { - case DIB3000_GUARD_TIME_1_32: - deb_getf("GUARD_INTERVAL_1_32 "); - ofdm->guard_interval = GUARD_INTERVAL_1_32; - break; - case DIB3000_GUARD_TIME_1_16: - deb_getf("GUARD_INTERVAL_1_16 "); - ofdm->guard_interval = GUARD_INTERVAL_1_16; - break; - case DIB3000_GUARD_TIME_1_8: - deb_getf("GUARD_INTERVAL_1_8 "); - ofdm->guard_interval = GUARD_INTERVAL_1_8; - break; - case DIB3000_GUARD_TIME_1_4: - deb_getf("GUARD_INTERVAL_1_4 "); - ofdm->guard_interval = GUARD_INTERVAL_1_4; - break; - default: - err("Unexpected Guard Time returned by TPS (%d)", tps_val); - break; - } + // other configurations - switch (DIB3000MC_TP_FFT(tps_val)) { - case DIB3000_TRANSMISSION_MODE_2K: - deb_getf("TRANSMISSION_MODE_2K "); - ofdm->transmission_mode = TRANSMISSION_MODE_2K; - break; - case DIB3000_TRANSMISSION_MODE_8K: - deb_getf("TRANSMISSION_MODE_8K "); - ofdm->transmission_mode = TRANSMISSION_MODE_8K; - break; - default: - err("unexpected transmission mode return by TPS (%d)", tps_val); - break; - } - deb_getf("\n"); + // P_ctrl_sfreq + dib3000mc_write_word(state, 33, (5 << 0)); + dib3000mc_write_word(state, 88, (1 << 10) | (0x10 << 0)); + + // Phase noise control + // P_fft_phacor_inh, P_fft_phacor_cpe, P_fft_powrange + dib3000mc_write_word(state, 99, (1 << 9) | (0x20 << 0)); + + if (state->cfg->phase_noise_mode == 0) + dib3000mc_write_word(state, 111, 0x00); + else + dib3000mc_write_word(state, 111, 0x02); + + // P_agc_global + dib3000mc_write_word(state, 50, 0x8000); + + // agc setup misc + dib3000mc_setup_pwm3_state(state); + + // P_agc_counter_lock + dib3000mc_write_word(state, 53, 0x87); + // P_agc_counter_unlock + dib3000mc_write_word(state, 54, 0x87); + + /* agc */ + dib3000mc_write_word(state, 36, state->cfg->max_time); + dib3000mc_write_word(state, 37, agc->setup); + dib3000mc_write_word(state, 38, state->cfg->pwm3_value); + dib3000mc_write_word(state, 39, state->cfg->ln_adc_level); + + // set_agc_loop_Bw + dib3000mc_write_word(state, 40, 0x0179); + dib3000mc_write_word(state, 41, 0x03f0); + + dib3000mc_write_word(state, 42, agc->agc1_max); + dib3000mc_write_word(state, 43, agc->agc1_min); + dib3000mc_write_word(state, 44, agc->agc2_max); + dib3000mc_write_word(state, 45, agc->agc2_min); + dib3000mc_write_word(state, 46, (agc->agc1_pt1 << 8) | agc->agc1_pt2); + dib3000mc_write_word(state, 47, (agc->agc1_slope1 << 8) | agc->agc1_slope2); + dib3000mc_write_word(state, 48, (agc->agc2_pt1 << 8) | agc->agc2_pt2); + dib3000mc_write_word(state, 49, (agc->agc2_slope1 << 8) | agc->agc2_slope2); + +// Begin: TimeOut registers + // P_pha3_thres + dib3000mc_write_word(state, 110, 3277); + // P_timf_alpha = 6, P_corm_alpha = 6, P_corm_thres = 0x80 + dib3000mc_write_word(state, 26, 0x6680); + // lock_mask0 + dib3000mc_write_word(state, 1, 4); + // lock_mask1 + dib3000mc_write_word(state, 2, 4); + // lock_mask2 + dib3000mc_write_word(state, 3, 0x1000); + // P_search_maxtrial=1 + dib3000mc_write_word(state, 5, 1); + + dib3000mc_set_bandwidth(&state->demod, BANDWIDTH_8_MHZ); + + // div_lock_mask + dib3000mc_write_word(state, 4, 0x814); + + dib3000mc_write_word(state, 21, (1 << 9) | 0x164); + dib3000mc_write_word(state, 22, 0x463d); + + // Spurious rm cfg + // P_cspu_regul, P_cspu_win_cut + dib3000mc_write_word(state, 120, 0x200f); + // P_adp_selec_monit + dib3000mc_write_word(state, 134, 0); + + // Fec cfg + dib3000mc_write_word(state, 195, 0x10); + + // diversity register: P_dvsy_sync_wait.. + dib3000mc_write_word(state, 180, 0x2FF0); + + // Impulse noise configuration + dib3000mc_set_impulse_noise(state, 0, 1); + + // output mode set-up + dib3000mc_set_output_mode(state, OUTMODE_HIGH_Z); + + /* close the i2c-gate */ + dib3000mc_write_word(state, 769, (1 << 7) ); return 0; } -static int dib3000mc_set_frontend(struct dvb_frontend* fe, - struct dvb_frontend_parameters *fep, int tuner) +static int dib3000mc_sleep(struct dvb_frontend *demod) { - struct dib3000_state* state = fe->demodulator_priv; - struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm; - int search_state,auto_val; - u16 val; - - if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */ - fe->ops.tuner_ops.set_params(fe, fep); - if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); - - state->last_tuned_freq = fep->frequency; - // if (!scanboost) { - dib3000mc_set_timing(state,0,ofdm->transmission_mode,ofdm->bandwidth); - dib3000mc_init_auto_scan(state, ofdm->bandwidth, 0); - state->last_tuned_bw = ofdm->bandwidth; - - wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth); - wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_AGC); - wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF); - - /* Default cfg isi offset adp */ - wr_foreach(dib3000mc_reg_offset,dib3000mc_offset[0]); - - wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT | DIB3000MC_ISI_INHIBIT); - dib3000mc_set_adp_cfg(state,ofdm->constellation); - wr(DIB3000MC_REG_UNK_133,DIB3000MC_UNK_133); - - wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general); - /* power smoothing */ - if (ofdm->bandwidth != BANDWIDTH_8_MHZ) { - wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[0]); - } else { - wr_foreach(dib3000mc_reg_bw,dib3000mc_bw[3]); - } - auto_val = 0; - dib3000mc_set_general_cfg(state,fep,&auto_val); - dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth); - - val = rd(DIB3000MC_REG_DEMOD_PARM); - wr(DIB3000MC_REG_DEMOD_PARM,val|DIB3000MC_DEMOD_RST_DEMOD_ON); - wr(DIB3000MC_REG_DEMOD_PARM,val); - // } - msleep(70); - - /* something has to be auto searched */ - if (auto_val) { - int as_count=0; - - deb_setf("autosearch enabled.\n"); - - val = rd(DIB3000MC_REG_DEMOD_PARM); - wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON); - wr(DIB3000MC_REG_DEMOD_PARM,val); - - while ((search_state = dib3000_search_status( - rd(DIB3000MC_REG_AS_IRQ),1)) < 0 && as_count++ < 100) - msleep(10); - - deb_info("search_state after autosearch %d after %d checks\n",search_state,as_count); - - if (search_state == 1) { - struct dvb_frontend_parameters feps; - if (dib3000mc_get_frontend(fe, &feps) == 0) { - deb_setf("reading tuning data from frontend succeeded.\n"); - return dib3000mc_set_frontend(fe, &feps, 0); - } - } - } else { - dib3000mc_set_impulse_noise(state,0,ofdm->transmission_mode,ofdm->bandwidth); - wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE); - dib3000mc_set_adp_cfg(state,ofdm->constellation); - - /* set_offset_cfg */ - wr_foreach(dib3000mc_reg_offset, - dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]); - } - } else { /* second call, after autosearch (fka: set_WithKnownParams) */ -// dib3000mc_set_timing(state,1,ofdm->transmission_mode,ofdm->bandwidth); - - auto_val = 0; - dib3000mc_set_general_cfg(state,fep,&auto_val); - if (auto_val) - deb_info("auto_val is true, even though an auto search was already performed.\n"); + struct dib3000mc_state *state = demod->demodulator_priv; - dib3000mc_set_impulse_noise(state,0,ofdm->constellation,ofdm->bandwidth); + dib3000mc_write_word(state, 1037, dib3000mc_read_word(state, 1037) | 0x0003); + dib3000mc_write_word(state, 1031, 0xFFFF); + dib3000mc_write_word(state, 1032, 0xFFFF); + dib3000mc_write_word(state, 1033, 0xFFF4); // **** Bin2 - val = rd(DIB3000MC_REG_DEMOD_PARM); - wr(DIB3000MC_REG_DEMOD_PARM,val | DIB3000MC_DEMOD_RST_AUTO_SRCH_ON); - wr(DIB3000MC_REG_DEMOD_PARM,val); - - msleep(30); + return 0; +} - wr(DIB3000MC_REG_ISI,DIB3000MC_ISI_DEFAULT|DIB3000MC_ISI_ACTIVATE); - dib3000mc_set_adp_cfg(state,ofdm->constellation); - wr_foreach(dib3000mc_reg_offset, - dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]); +static void dib3000mc_set_adp_cfg(struct dib3000mc_state *state, s16 qam) +{ + u16 cfg[4] = { 0 },reg; + switch (qam) { + case 0: + cfg[0] = 0x099a; cfg[1] = 0x7fae; cfg[2] = 0x0333; cfg[3] = 0x7ff0; + break; + case 1: + cfg[0] = 0x023d; cfg[1] = 0x7fdf; cfg[2] = 0x00a4; cfg[3] = 0x7ff0; + break; + case 2: + cfg[0] = 0x0148; cfg[1] = 0x7ff0; cfg[2] = 0x00a4; cfg[3] = 0x7ff8; + break; } - return 0; + for (reg = 129; reg < 133; reg++) + dib3000mc_write_word(state, reg, cfg[reg - 129]); } -static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode) +static void dib3000mc_set_channel_cfg(struct dib3000mc_state *state, struct dibx000_ofdm_channel *chan, u16 seq) { - struct dib3000_state *state = fe->demodulator_priv; - deb_info("init start\n"); + u16 tmp; - state->timing_offset = 0; - state->timing_offset_comp_done = 0; + dib3000mc_set_timing(state, chan->nfft, chan->Bw, 0); - wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_CONFIG); - wr(DIB3000MC_REG_RESTART,DIB3000MC_RESTART_OFF); - wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_UP); - wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_PUP_MOBILE); - wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_UP); - wr(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_INIT); +// if (boost) +// dib3000mc_write_word(state, 100, (11 << 6) + 6); +// else + dib3000mc_write_word(state, 100, (16 << 6) + 9); - wr(DIB3000MC_REG_RST_UNC,DIB3000MC_RST_UNC_OFF); - wr(DIB3000MC_REG_UNK_19,DIB3000MC_UNK_19); + dib3000mc_write_word(state, 1027, 0x0800); + dib3000mc_write_word(state, 1027, 0x0000); - wr(33,5); - wr(36,81); - wr(DIB3000MC_REG_UNK_88,DIB3000MC_UNK_88); + //Default cfg isi offset adp + dib3000mc_write_word(state, 26, 0x6680); + dib3000mc_write_word(state, 29, 0x1273); + dib3000mc_write_word(state, 33, 5); + dib3000mc_set_adp_cfg(state, 1); + dib3000mc_write_word(state, 133, 15564); - wr(DIB3000MC_REG_UNK_99,DIB3000MC_UNK_99); - wr(DIB3000MC_REG_UNK_111,DIB3000MC_UNK_111_PH_N_MODE_0); /* phase noise algo off */ + dib3000mc_write_word(state, 12 , 0x0); + dib3000mc_write_word(state, 13 , 0x3e8); + dib3000mc_write_word(state, 14 , 0x0); + dib3000mc_write_word(state, 15 , 0x3f2); - /* mobile mode - portable reception */ - wr_foreach(dib3000mc_reg_mobile_mode,dib3000mc_mobile_mode[1]); + dib3000mc_write_word(state, 93,0); + dib3000mc_write_word(state, 94,0); + dib3000mc_write_word(state, 95,0); + dib3000mc_write_word(state, 96,0); + dib3000mc_write_word(state, 97,0); + dib3000mc_write_word(state, 98,0); -/* TUNER_PANASONIC_ENV57H12D5: */ - wr_foreach(dib3000mc_reg_agc_bandwidth,dib3000mc_agc_bandwidth); - wr_foreach(dib3000mc_reg_agc_bandwidth_general,dib3000mc_agc_bandwidth_general); - wr_foreach(dib3000mc_reg_agc,dib3000mc_agc_tuner[1]); + dib3000mc_set_impulse_noise(state, 0, chan->nfft); - wr(DIB3000MC_REG_UNK_110,DIB3000MC_UNK_110); - wr(26,0x6680); - wr(DIB3000MC_REG_UNK_1,DIB3000MC_UNK_1); - wr(DIB3000MC_REG_UNK_2,DIB3000MC_UNK_2); - wr(DIB3000MC_REG_UNK_3,DIB3000MC_UNK_3); - wr(DIB3000MC_REG_SEQ_TPS,DIB3000MC_SEQ_TPS_DEFAULT); + tmp = ((chan->nfft & 0x1) << 7) | (chan->guard << 5) | (chan->nqam << 3) | chan->vit_alpha; + dib3000mc_write_word(state, 0, tmp); - wr_foreach(dib3000mc_reg_bandwidth,dib3000mc_bandwidth_8mhz); - wr_foreach(dib3000mc_reg_bandwidth_general,dib3000mc_bandwidth_general); + dib3000mc_write_word(state, 5, seq); - wr(DIB3000MC_REG_UNK_4,DIB3000MC_UNK_4); - - wr(DIB3000MC_REG_SET_DDS_FREQ_MSB,DIB3000MC_DDS_FREQ_MSB_INV_OFF); - wr(DIB3000MC_REG_SET_DDS_FREQ_LSB,DIB3000MC_DDS_FREQ_LSB); + tmp = (chan->vit_hrch << 4) | (chan->vit_select_hp); + if (!chan->vit_hrch || (chan->vit_hrch && chan->vit_select_hp)) + tmp |= chan->vit_code_rate_hp << 1; + else + tmp |= chan->vit_code_rate_lp << 1; + dib3000mc_write_word(state, 181, tmp); - dib3000mc_set_timing(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ); -// wr_foreach(dib3000mc_reg_timing_freq,dib3000mc_timing_freq[3]); + // diversity synchro delay + tmp = dib3000mc_read_word(state, 180) & 0x000f; + tmp |= ((chan->nfft == 0) ? 64 : 256) * ((1 << (chan->guard)) * 3 / 2) << 4; // add 50% SFN margin + dib3000mc_write_word(state, 180, tmp); - wr(DIB3000MC_REG_UNK_120,DIB3000MC_UNK_120); - wr(DIB3000MC_REG_UNK_134,DIB3000MC_UNK_134); - wr(DIB3000MC_REG_FEC_CFG,DIB3000MC_FEC_CFG); + // restart demod + tmp = dib3000mc_read_word(state, 0); + dib3000mc_write_word(state, 0, tmp | (1 << 9)); + dib3000mc_write_word(state, 0, tmp); - wr(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF); + msleep(30); - dib3000mc_set_impulse_noise(state,0,TRANSMISSION_MODE_8K,BANDWIDTH_8_MHZ); + dib3000mc_set_impulse_noise(state, state->cfg->impulse_noise_mode, chan->nfft); +} -/* output mode control, just the MPEG2_SLAVE */ -// set_or(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE); - wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_SLAVE); - wr(DIB3000MC_REG_SMO_MODE,DIB3000MC_SMO_MODE_SLAVE); - wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_SLAVE); - wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_SLAVE); +static int dib3000mc_autosearch_start(struct dvb_frontend *demod, struct dibx000_ofdm_channel *chan) +{ + struct dib3000mc_state *state = demod->demodulator_priv; + u16 reg; +// u32 val; + struct dibx000_ofdm_channel fchan; -/* MPEG2_PARALLEL_CONTINUOUS_CLOCK - wr(DIB3000MC_REG_OUTMODE, - DIB3000MC_SET_OUTMODE(DIB3000MC_OM_PAR_CONT_CLK, - rd(DIB3000MC_REG_OUTMODE))); + INIT_OFDM_CHANNEL(&fchan); + fchan = *chan; - wr(DIB3000MC_REG_SMO_MODE, - DIB3000MC_SMO_MODE_DEFAULT | - DIB3000MC_SMO_MODE_188); +#if 0 + if (boost) { + val = (dib3000mc_read_word(state, 6) << 16) | dib3000mc_read_word(state, 7); + val *= 85; + val >>= 7; + dib3000mc_write_word(state, 6, (val >> 16) & 0xffff); + dib3000mc_write_word(state, 7, (val ) & 0xffff); + } +#endif - wr(DIB3000MC_REG_FIFO_THRESHOLD,DIB3000MC_FIFO_THRESHOLD_DEFAULT); - wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON); -*/ + /* a channel for autosearch */ + reg = 0; + if (chan->nfft == -1 && chan->guard == -1) reg = 7; + if (chan->nfft == -1 && chan->guard != -1) reg = 2; + if (chan->nfft != -1 && chan->guard == -1) reg = 3; -/* diversity */ - wr(DIB3000MC_REG_DIVERSITY1,DIB3000MC_DIVERSITY1_DEFAULT); - wr(DIB3000MC_REG_DIVERSITY2,DIB3000MC_DIVERSITY2_DEFAULT); + fchan.nfft = 1; fchan.guard = 0; fchan.nqam = 2; + fchan.vit_alpha = 1; fchan.vit_code_rate_hp = 2; fchan.vit_code_rate_lp = 2; + fchan.vit_hrch = 0; fchan.vit_select_hp = 1; - set_and(DIB3000MC_REG_DIVERSITY3,DIB3000MC_DIVERSITY3_IN_OFF); + dib3000mc_set_channel_cfg(state, &fchan, reg); - set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF); + reg = dib3000mc_read_word(state, 0); + dib3000mc_write_word(state, 0, reg | (1 << 8)); + dib3000mc_write_word(state, 0, reg); - deb_info("init end\n"); return 0; } -static int dib3000mc_read_status(struct dvb_frontend* fe, fe_status_t *stat) + +static int dib3000mc_autosearch_is_irq(struct dvb_frontend *demod) { - struct dib3000_state* state = fe->demodulator_priv; - u16 lock = rd(DIB3000MC_REG_LOCKING); + struct dib3000mc_state *state = demod->demodulator_priv; + u16 irq_pending = dib3000mc_read_word(state, 511); - *stat = 0; - if (DIB3000MC_AGC_LOCK(lock)) - *stat |= FE_HAS_SIGNAL; - if (DIB3000MC_CARRIER_LOCK(lock)) - *stat |= FE_HAS_CARRIER; - if (DIB3000MC_TPS_LOCK(lock)) - *stat |= FE_HAS_VITERBI; - if (DIB3000MC_MPEG_SYNC_LOCK(lock)) - *stat |= (FE_HAS_SYNC | FE_HAS_LOCK); + if (irq_pending & 0x1) // failed + return 1; - deb_stat("actual status is %2x fifo_level: %x,244: %x, 206: %x, 207: %x, 1040: %x\n",*stat,rd(510),rd(244),rd(206),rd(207),rd(1040)); + if (irq_pending & 0x2) // succeeded + return 2; - return 0; + return 0; // still pending } -static int dib3000mc_read_ber(struct dvb_frontend* fe, u32 *ber) +static int dib3000mc_tune(struct dvb_frontend *demod, struct dibx000_ofdm_channel *ch) { - struct dib3000_state* state = fe->demodulator_priv; - *ber = ((rd(DIB3000MC_REG_BER_MSB) << 16) | rd(DIB3000MC_REG_BER_LSB)); + struct dib3000mc_state *state = demod->demodulator_priv; + + // ** configure demod ** + dib3000mc_set_channel_cfg(state, ch, 0); + + // activates isi + dib3000mc_write_word(state, 29, 0x1073); + + dib3000mc_set_adp_cfg(state, (u8)ch->nqam); + + if (ch->nfft == 1) { + dib3000mc_write_word(state, 26, 38528); + dib3000mc_write_word(state, 33, 8); + } else { + dib3000mc_write_word(state, 26, 30336); + dib3000mc_write_word(state, 33, 6); + } + + // if (lock) + // dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1); + return 0; } -static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) +static int dib3000mc_demod_output_mode(struct dvb_frontend *demod, int mode) { - struct dib3000_state* state = fe->demodulator_priv; - - *unc = rd(DIB3000MC_REG_PACKET_ERRORS); - return 0; + struct dib3000mc_state *state = demod->demodulator_priv; + return dib3000mc_set_output_mode(state, mode); } -/* see dib3000mb.c for calculation comments */ -static int dib3000mc_read_signal_strength(struct dvb_frontend* fe, u16 *strength) +static int dib3000mc_i2c_enumeration(struct dvb_frontend *demod[], int no_of_demods, u8 default_addr) { - struct dib3000_state* state = fe->demodulator_priv; - u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB); - *strength = (((val >> 6) & 0xff) << 8) + (val & 0x3f); + struct dib3000mc_state *st; + int k,ret=0; + u8 new_addr; + + static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26}; + + for (k = no_of_demods-1; k >= 0; k--) { + st = demod[k]->demodulator_priv; - deb_stat("signal: mantisse = %d, exponent = %d\n",(*strength >> 8) & 0xff, *strength & 0xff); + /* designated i2c address */ + new_addr = DIB3000MC_I2C_ADDRESS[k]; + + st->i2c_addr = new_addr; + if (dib3000mc_identify(st) != 0) { + st->i2c_addr = default_addr; + if (dib3000mc_identify(st) != 0) { + dprintk("-E- DiB3000P/MC #%d: not identified\n", k); + return -EINVAL; + } + } + + /* turn on div_out */ + dib3000mc_demod_output_mode(demod[k], OUTMODE_MPEG2_PAR_CONT_CLK); + + // set new i2c address and force divstr (Bit 1) to value 0 (Bit 0) + ret |= dib3000mc_write_word(st, 1024, (new_addr << 3) | 0x1); + st->i2c_addr = new_addr; + } + + for (k = 0; k < no_of_demods; k++) { + st = demod[k]->demodulator_priv; + + ret |= dib3000mc_write_word(st, 1024, st->i2c_addr << 3); + + /* turn off data output */ + dib3000mc_demod_output_mode(demod[k],OUTMODE_HIGH_Z); + dib3000mc_write_word(st, 769, (1 << 7) ); + + } return 0; } -/* see dib3000mb.c for calculation comments */ -static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr) +struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating) { - struct dib3000_state* state = fe->demodulator_priv; - u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB), - val2 = rd(DIB3000MC_REG_SIGNAL_NOISE_MSB); - u16 sig,noise; + struct dib3000mc_state *st = demod->demodulator_priv; + return dibx000_get_i2c_adapter(&st->i2c_master, DIBX000_I2C_INTERFACE_TUNER, gating); +} - sig = (((val >> 6) & 0xff) << 8) + (val & 0x3f); - noise = (((val >> 4) & 0xff) << 8) + ((val & 0xf) << 2) + ((val2 >> 14) & 0x3); - if (noise == 0) - *snr = 0xffff; - else - *snr = (u16) sig/noise; +EXPORT_SYMBOL(dib3000mc_get_tuner_i2c_master); + +static int dib3000mc_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct dib3000mc_state *state = fe->demodulator_priv; + u16 tps = dib3000mc_read_word(state,458); + + fep->inversion = INVERSION_AUTO; + + fep->u.ofdm.bandwidth = state->current_bandwidth; + + switch ((tps >> 8) & 0x1) { + case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break; + case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break; + } + + switch (tps & 0x3) { + case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break; + case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break; + case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break; + case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break; + } + + switch ((tps >> 13) & 0x3) { + case 0: fep->u.ofdm.constellation = QPSK; break; + case 1: fep->u.ofdm.constellation = QAM_16; break; + case 2: + default: fep->u.ofdm.constellation = QAM_64; break; + } + + /* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */ + /* (tps >> 12) & 0x1 == hrch is used, (tps >> 9) & 0x7 == alpha */ + + fep->u.ofdm.hierarchy_information = HIERARCHY_NONE; + switch ((tps >> 5) & 0x7) { + case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break; + case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break; + case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break; + case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break; + case 7: + default: fep->u.ofdm.code_rate_HP = FEC_7_8; break; + + } + + switch ((tps >> 2) & 0x7) { + case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break; + case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break; + case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break; + case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break; + case 7: + default: fep->u.ofdm.code_rate_LP = FEC_7_8; break; + } - deb_stat("signal: mantisse = %d, exponent = %d\n",(sig >> 8) & 0xff, sig & 0xff); - deb_stat("noise: mantisse = %d, exponent = %d\n",(noise >> 8) & 0xff, noise & 0xff); - deb_stat("snr: %d\n",*snr); return 0; } -static int dib3000mc_sleep(struct dvb_frontend* fe) +static int dib3000mc_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) { - struct dib3000_state* state = fe->demodulator_priv; + struct dib3000mc_state *state = fe->demodulator_priv; + struct dibx000_ofdm_channel ch; - set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_PWR_DOWN); - wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_DOWN); - wr(DIB3000MC_REG_CLK_CFG_2,DIB3000MC_CLK_CFG_2_POWER_DOWN); - wr(DIB3000MC_REG_CLK_CFG_3,DIB3000MC_CLK_CFG_3_POWER_DOWN); - return 0; + INIT_OFDM_CHANNEL(&ch); + FEP2DIB(fep,&ch); + + dump_fep(&ch); + + state->current_bandwidth = fep->u.ofdm.bandwidth; + dib3000mc_set_bandwidth(fe, fep->u.ofdm.bandwidth); + + if (fe->ops.tuner_ops.set_params) { + fe->ops.tuner_ops.set_params(fe, fep); + msleep(100); + } + + if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO || + fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || + fep->u.ofdm.constellation == QAM_AUTO || + fep->u.ofdm.code_rate_HP == FEC_AUTO) { + int i = 100, found; + + dib3000mc_autosearch_start(fe, &ch); + do { + msleep(1); + found = dib3000mc_autosearch_is_irq(fe); + } while (found == 0 && i--); + + dprintk("autosearch returns: %d\n",found); + if (found == 0 || found == 1) + return 0; // no channel found + + dib3000mc_get_frontend(fe, fep); + FEP2DIB(fep,&ch); + } + + /* make this a config parameter */ + dib3000mc_set_output_mode(state, OUTMODE_MPEG2_FIFO); + + return dib3000mc_tune(fe, &ch); } -static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) +static int dib3000mc_read_status(struct dvb_frontend *fe, fe_status_t *stat) { - tune->min_delay_ms = 1000; + struct dib3000mc_state *state = fe->demodulator_priv; + u16 lock = dib3000mc_read_word(state, 509); + + *stat = 0; + + if (lock & 0x8000) + *stat |= FE_HAS_SIGNAL; + if (lock & 0x3000) + *stat |= FE_HAS_CARRIER; + if (lock & 0x0100) + *stat |= FE_HAS_VITERBI; + if (lock & 0x0010) + *stat |= FE_HAS_SYNC; + if (lock & 0x0008) + *stat |= FE_HAS_LOCK; + return 0; } -static int dib3000mc_fe_init_nonmobile(struct dvb_frontend* fe) +static int dib3000mc_read_ber(struct dvb_frontend *fe, u32 *ber) { - return dib3000mc_fe_init(fe, 0); + struct dib3000mc_state *state = fe->demodulator_priv; + *ber = (dib3000mc_read_word(state, 500) << 16) | dib3000mc_read_word(state, 501); + return 0; } -static int dib3000mc_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_frontend_parameters *fep) +static int dib3000mc_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) { - return dib3000mc_set_frontend(fe, fep, 1); + struct dib3000mc_state *state = fe->demodulator_priv; + *unc = dib3000mc_read_word(state, 508); + return 0; } -static void dib3000mc_release(struct dvb_frontend* fe) +static int dib3000mc_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { - struct dib3000_state *state = fe->demodulator_priv; - kfree(state); + struct dib3000mc_state *state = fe->demodulator_priv; + u16 val = dib3000mc_read_word(state, 392); + *strength = 65535 - val; + return 0; } -/* pid filter and transfer stuff */ -static int dib3000mc_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff) +static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr) { - struct dib3000_state *state = fe->demodulator_priv; - pid = (onoff ? pid | DIB3000_ACTIVATE_PID_FILTERING : 0); - wr(index+DIB3000MC_REG_FIRST_PID,pid); + *snr = 0x0000; return 0; } -static int dib3000mc_fifo_control(struct dvb_frontend *fe, int onoff) +static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) { - struct dib3000_state *state = fe->demodulator_priv; - u16 tmp = rd(DIB3000MC_REG_SMO_MODE); - - deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling"); - - if (onoff) { - deb_xfer("%d %x\n",tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH); - wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_FIFO_UNFLUSH); - } else { - deb_xfer("%d %x\n",tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH); - wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_FIFO_FLUSH); - } + tune->min_delay_ms = 1000; return 0; } -static int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff) +static void dib3000mc_release(struct dvb_frontend *fe) { - struct dib3000_state *state = fe->demodulator_priv; - u16 tmp = rd(DIB3000MC_REG_SMO_MODE); - - deb_xfer("%s pid parsing\n",onoff ? "enabling" : "disabling"); - - if (onoff) { - wr(DIB3000MC_REG_SMO_MODE,tmp | DIB3000MC_SMO_MODE_PID_PARSE); - } else { - wr(DIB3000MC_REG_SMO_MODE,tmp & DIB3000MC_SMO_MODE_NO_PID_PARSE); - } - return 0; + struct dib3000mc_state *state = fe->demodulator_priv; + dibx000_exit_i2c_master(&state->i2c_master); + kfree(state); } -static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr) +int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff) { - struct dib3000_state *state = fe->demodulator_priv; - if (onoff) { - wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr)); - } else { - wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_DISABLE(pll_addr)); - } + struct dib3000mc_state *state = fe->demodulator_priv; + dib3000mc_write_word(state, 212 + index, onoff ? (1 << 13) | pid : 0); return 0; } +EXPORT_SYMBOL(dib3000mc_pid_control); -static int dib3000mc_demod_init(struct dib3000_state *state) +int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff) { - u16 default_addr = 0x0a; - /* first init */ - if (state->config.demod_address != default_addr) { - deb_info("initializing the demod the first time. Setting demod addr to 0x%x\n",default_addr); - wr(DIB3000MC_REG_ELEC_OUT,DIB3000MC_ELEC_OUT_DIV_OUT_ON); - wr(DIB3000MC_REG_OUTMODE,DIB3000MC_OM_PAR_CONT_CLK); - - wr(DIB3000MC_REG_RST_I2C_ADDR, - DIB3000MC_DEMOD_ADDR(default_addr) | - DIB3000MC_DEMOD_ADDR_ON); - - state->config.demod_address = default_addr; - - wr(DIB3000MC_REG_RST_I2C_ADDR, - DIB3000MC_DEMOD_ADDR(default_addr)); - } else - deb_info("demod is already initialized. Demod addr: 0x%x\n",state->config.demod_address); - return 0; + struct dib3000mc_state *state = fe->demodulator_priv; + u16 tmp = dib3000mc_read_word(state, 206) & ~(1 << 4); + tmp |= (onoff << 4); + return dib3000mc_write_word(state, 206, tmp); } +EXPORT_SYMBOL(dib3000mc_pid_parse); +void dib3000mc_set_config(struct dvb_frontend *fe, struct dib3000mc_config *cfg) +{ + struct dib3000mc_state *state = fe->demodulator_priv; + state->cfg = cfg; +} +EXPORT_SYMBOL(dib3000mc_set_config); static struct dvb_frontend_ops dib3000mc_ops; -struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config, - struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops) +int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr, u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[]) { - struct dib3000_state* state = NULL; - u16 devid; + struct dib3000mc_state *st; + int k, num=0; - /* allocate memory for the internal state */ - state = kzalloc(sizeof(struct dib3000_state), GFP_KERNEL); - if (state == NULL) - goto error; + if (no_of_demods < 1) + return -EINVAL; - /* setup the state */ - state->i2c = i2c; - memcpy(&state->config,config,sizeof(struct dib3000_config)); + for (k = 0; k < no_of_demods; k++) { + st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL); + if (st == NULL) + goto error; - /* check for the correct demod */ - if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM) - goto error; + num++; - devid = rd(DIB3000_REG_DEVICE_ID); - if (devid != DIB3000MC_DEVICE_ID && devid != DIB3000P_DEVICE_ID) - goto error; + st->cfg = &cfg[k]; + // st->gpio_val = cfg[k].gpio_val; + // st->gpio_dir = cfg[k].gpio_dir; + st->i2c_adap = i2c_adap; - switch (devid) { - case DIB3000MC_DEVICE_ID: - info("Found a DiBcom 3000M-C, interesting..."); - break; - case DIB3000P_DEVICE_ID: - info("Found a DiBcom 3000P."); - break; - } + demod[k] = &st->demod; + demod[k]->demodulator_priv = st; + memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops)); - /* create dvb_frontend */ - memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops)); - state->frontend.demodulator_priv = state; +// INIT_COMPONENT_REGISTER_ACCESS(&st->register_access, 12, 16, dib7000p_register_read, dib7000p_register_write, st); +// demod[k]->register_access = &st->register_access; + } - /* set the xfer operations */ - xfer_ops->pid_parse = dib3000mc_pid_parse; - xfer_ops->fifo_ctrl = dib3000mc_fifo_control; - xfer_ops->pid_ctrl = dib3000mc_pid_control; - xfer_ops->tuner_pass_ctrl = dib3000mc_tuner_pass_ctrl; + if (do_i2c_enum) { + if (dib3000mc_i2c_enumeration(demod,no_of_demods,default_addr) != 0) + goto error; + } else { + st = demod[0]->demodulator_priv; + st->i2c_addr = default_addr; + if (dib3000mc_identify(st) != 0) + goto error; + } - dib3000mc_demod_init(state); + for (k = 0; k < num; k++) { + st = demod[k]->demodulator_priv; + dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr); + } - return &state->frontend; + return 0; error: - kfree(state); - return NULL; + for (k = 0; k < num; k++) + kfree(demod[k]->demodulator_priv); + + return -EINVAL; } + EXPORT_SYMBOL(dib3000mc_attach); static struct dvb_frontend_ops dib3000mc_ops = { - .info = { - .name = "DiBcom 3000P/M-C DVB-T", - .type = FE_OFDM, - .frequency_min = 44250000, - .frequency_max = 867250000, - .frequency_stepsize = 62500, + .name = "DiBcom 3000MC/P", + .type = FE_OFDM, + .frequency_min = 44250000, + .frequency_max = 867250000, + .frequency_stepsize = 62500, .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_RECOVER | - FE_CAN_HIERARCHY_AUTO, + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_RECOVER | + FE_CAN_HIERARCHY_AUTO, }, - .release = dib3000mc_release, + .release = dib3000mc_release, - .init = dib3000mc_fe_init_nonmobile, - .sleep = dib3000mc_sleep, + .init = dib3000mc_init, + .sleep = dib3000mc_sleep, - .set_frontend = dib3000mc_set_frontend_and_tuner, - .get_frontend = dib3000mc_get_frontend, - .get_tune_settings = dib3000mc_fe_get_tune_settings, + .set_frontend = dib3000mc_set_frontend, + .get_tune_settings = dib3000mc_fe_get_tune_settings, + .get_frontend = dib3000mc_get_frontend, - .read_status = dib3000mc_read_status, - .read_ber = dib3000mc_read_ber, + .read_status = dib3000mc_read_status, + .read_ber = dib3000mc_read_ber, .read_signal_strength = dib3000mc_read_signal_strength, - .read_snr = dib3000mc_read_snr, - .read_ucblocks = dib3000mc_read_unc_blocks, + .read_snr = dib3000mc_read_snr, + .read_ucblocks = dib3000mc_read_unc_blocks, }; -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); +MODULE_DESCRIPTION("Driver for the DiBcom 3000MC/P COFDM demodulator"); MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/dib3000mc_priv.h b/linux/drivers/media/dvb/frontends/dib3000mc_priv.h deleted file mode 100644 index 2930aac75..000000000 --- a/linux/drivers/media/dvb/frontends/dib3000mc_priv.h +++ /dev/null @@ -1,428 +0,0 @@ -/* - * dib3000mc_priv.h - * - * Copyright (C) 2004 Patrick Boettcher (patrick.boettcher@desy.de) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - * for more information see dib3000mc.c . - */ - -#ifndef __DIB3000MC_PRIV_H__ -#define __DIB3000MC_PRIV_H__ - -/* - * Demodulator parameters - * reg: 0 1 1 1 11 11 111 - * | | | | | | - * | | | | | +-- alpha (000=0, 001=1, 010=2, 100=4) - * | | | | +----- constellation (00=QPSK, 01=16QAM, 10=64QAM) - * | | | +-------- guard (00=1/32, 01=1/16, 10=1/8, 11=1/4) - * | | +----------- transmission mode (0=2k, 1=8k) - * | | - * | +-------------- restart autosearch for parameters - * +---------------- restart the demodulator - * reg: 181 1 111 1 - * | | | - * | | +- FEC applies for HP or LP (0=LP, 1=HP) - * | +---- FEC rate (001=1/2, 010=2/3, 011=3/4, 101=5/6, 111=7/8) - * +------- hierarchy on (0=no, 1=yes) - */ - -/* demodulator tuning parameter and restart options */ -#define DIB3000MC_REG_DEMOD_PARM ( 0) -#define DIB3000MC_DEMOD_PARM(a,c,g,t) ( \ - (0x7 & a) | \ - ((0x3 & c) << 3) | \ - ((0x3 & g) << 5) | \ - ((0x1 & t) << 7) ) -#define DIB3000MC_DEMOD_RST_AUTO_SRCH_ON (1 << 8) -#define DIB3000MC_DEMOD_RST_AUTO_SRCH_OFF (0 << 8) -#define DIB3000MC_DEMOD_RST_DEMOD_ON (1 << 9) -#define DIB3000MC_DEMOD_RST_DEMOD_OFF (0 << 9) - -/* register for hierarchy parameters */ -#define DIB3000MC_REG_HRCH_PARM ( 181) -#define DIB3000MC_HRCH_PARM(s,f,h) ( \ - (0x1 & s) | \ - ((0x7 & f) << 1) | \ - ((0x1 & h) << 4) ) - -/* timeout ??? */ -#define DIB3000MC_REG_UNK_1 ( 1) -#define DIB3000MC_UNK_1 ( 0x04) - -/* timeout ??? */ -#define DIB3000MC_REG_UNK_2 ( 2) -#define DIB3000MC_UNK_2 ( 0x04) - -/* timeout ??? */ -#define DIB3000MC_REG_UNK_3 ( 3) -#define DIB3000MC_UNK_3 (0x1000) - -#define DIB3000MC_REG_UNK_4 ( 4) -#define DIB3000MC_UNK_4 (0x0814) - -/* timeout ??? */ -#define DIB3000MC_REG_SEQ_TPS ( 5) -#define DIB3000MC_SEQ_TPS_DEFAULT ( 1) -#define DIB3000MC_SEQ_TPS(s,t) ( \ - ((s & 0x0f) << 4) | \ - ((t & 0x01) << 8) ) -#define DIB3000MC_IS_TPS(v) ((v << 8) & 0x1) -#define DIB3000MC_IS_AS(v) ((v >> 4) & 0xf) - -/* parameters for the bandwidth */ -#define DIB3000MC_REG_BW_TIMOUT_MSB ( 6) -#define DIB3000MC_REG_BW_TIMOUT_LSB ( 7) - -static u16 dib3000mc_reg_bandwidth[] = { 6,7,8,9,10,11,16,17 }; - -/*static u16 dib3000mc_bandwidth_5mhz[] = - { 0x28, 0x9380, 0x87, 0x4100, 0x2a4, 0x4500, 0x1, 0xb0d0 };*/ - -static u16 dib3000mc_bandwidth_6mhz[] = - { 0x21, 0xd040, 0x70, 0xb62b, 0x233, 0x8ed5, 0x1, 0xb0d0 }; - -static u16 dib3000mc_bandwidth_7mhz[] = - { 0x1c, 0xfba5, 0x60, 0x9c25, 0x1e3, 0x0cb7, 0x1, 0xb0d0 }; - -static u16 dib3000mc_bandwidth_8mhz[] = - { 0x19, 0x5c30, 0x54, 0x88a0, 0x1a6, 0xab20, 0x1, 0xb0d0 }; - -static u16 dib3000mc_reg_bandwidth_general[] = { 12,13,14,15 }; -static u16 dib3000mc_bandwidth_general[] = { 0x0000, 0x03e8, 0x0000, 0x03f2 }; - -/* lock mask */ -#define DIB3000MC_REG_LOCK_MASK ( 15) -#define DIB3000MC_ACTIVATE_LOCK_MASK (0x0800) - -/* reset the uncorrected packet count (??? do it 5 times) */ -#define DIB3000MC_REG_RST_UNC ( 18) -#define DIB3000MC_RST_UNC_ON ( 1) -#define DIB3000MC_RST_UNC_OFF ( 0) - -#define DIB3000MC_REG_UNK_19 ( 19) -#define DIB3000MC_UNK_19 ( 0) - -/* DDS frequency value (IF position) and inversion bit */ -#define DIB3000MC_REG_INVERSION ( 21) -#define DIB3000MC_REG_SET_DDS_FREQ_MSB ( 21) -#define DIB3000MC_DDS_FREQ_MSB_INV_OFF (0x0164) -#define DIB3000MC_DDS_FREQ_MSB_INV_ON (0x0364) - -#define DIB3000MC_REG_SET_DDS_FREQ_LSB ( 22) -#define DIB3000MC_DDS_FREQ_LSB (0x463d) - -/* timing frequencies setting */ -#define DIB3000MC_REG_TIMING_FREQ_MSB ( 23) -#define DIB3000MC_REG_TIMING_FREQ_LSB ( 24) -#define DIB3000MC_CLOCK_REF (0x151fd1) - -//static u16 dib3000mc_reg_timing_freq[] = { 23,24 }; - -//static u16 dib3000mc_timing_freq[][2] = { -// { 0x69, 0x9f18 }, /* 5 MHz */ -// { 0x7e ,0xbee9 }, /* 6 MHz */ -// { 0x93 ,0xdebb }, /* 7 MHz */ -// { 0xa8 ,0xfe8c }, /* 8 MHz */ -//}; - -/* timeout ??? */ -static u16 dib3000mc_reg_offset[] = { 26,33 }; - -static u16 dib3000mc_offset[][2] = { - { 26240, 5 }, /* default */ - { 30336, 6 }, /* 8K */ - { 38528, 8 }, /* 2K */ -}; - -#define DIB3000MC_REG_ISI ( 29) -#define DIB3000MC_ISI_DEFAULT (0x1073) -#define DIB3000MC_ISI_ACTIVATE (0x0000) -#define DIB3000MC_ISI_INHIBIT (0x0200) - -/* impulse noise control */ -static u16 dib3000mc_reg_imp_noise_ctl[] = { 34,35 }; - -static u16 dib3000mc_imp_noise_ctl[][2] = { - { 0x1294, 0x1ff8 }, /* mode 0 */ - { 0x1294, 0x1ff8 }, /* mode 1 */ - { 0x1294, 0x1ff8 }, /* mode 2 */ - { 0x1294, 0x1ff8 }, /* mode 3 */ - { 0x1294, 0x1ff8 }, /* mode 4 */ -}; - -/* AGC registers */ -static u16 dib3000mc_reg_agc[] = { - 36,37,38,39,42,43,44,45,46,47,48,49 -}; - -static u16 dib3000mc_agc_tuner[][12] = { - { 0x0051, 0x301d, 0x0000, 0x1cc7, 0xcf5c, 0x6666, - 0xbae1, 0xa148, 0x3b5e, 0x3c1c, 0x001a, 0x2019 - }, /* TUNER_PANASONIC_ENV77H04D5, */ - - { 0x0051, 0x301d, 0x0000, 0x1cc7, 0xdc29, 0x570a, - 0xbae1, 0x8ccd, 0x3b6d, 0x551d, 0x000a, 0x951e - }, /* TUNER_PANASONIC_ENV57H13D5, TUNER_PANASONIC_ENV57H12D5 */ - - { 0x0051, 0x301d, 0x0000, 0x1cc7, 0xffff, 0xffff, - 0xffff, 0x0000, 0xfdfd, 0x4040, 0x00fd, 0x4040 - }, /* TUNER_SAMSUNG_DTOS333IH102, TUNER_RFAGCIN_UNKNOWN */ - - { 0x0196, 0x301d, 0x0000, 0x1cc7, 0xbd71, 0x5c29, - 0xb5c3, 0x6148, 0x6569, 0x5127, 0x0033, 0x3537 - }, /* TUNER_PROVIDER_X */ - /* TODO TUNER_PANASONIC_ENV57H10D8, TUNER_PANASONIC_ENV57H11D8 */ -}; - -/* AGC loop bandwidth */ -static u16 dib3000mc_reg_agc_bandwidth[] = { 40,41 }; -static u16 dib3000mc_agc_bandwidth[] = { 0x119,0x330 }; - -static u16 dib3000mc_reg_agc_bandwidth_general[] = { 50,51,52,53,54 }; -static u16 dib3000mc_agc_bandwidth_general[] = - { 0x8000, 0x91ca, 0x01ba, 0x0087, 0x0087 }; - -#define DIB3000MC_REG_IMP_NOISE_55 ( 55) -#define DIB3000MC_IMP_NEW_ALGO(w) (w | (1<<10)) - -/* Impulse noise params */ -static u16 dib3000mc_reg_impulse_noise[] = { 55,56,57 }; -static u16 dib3000mc_impluse_noise[][3] = { - { 0x489, 0x89, 0x72 }, /* 5 MHz */ - { 0x4a5, 0xa5, 0x89 }, /* 6 MHz */ - { 0x4c0, 0xc0, 0xa0 }, /* 7 MHz */ - { 0x4db, 0xdb, 0xb7 }, /* 8 Mhz */ -}; - -static u16 dib3000mc_reg_fft[] = { - 58,59,60,61,62,63,64,65,66,67,68,69, - 70,71,72,73,74,75,76,77,78,79,80,81, - 82,83,84,85,86 -}; - -static u16 dib3000mc_fft_modes[][29] = { - { 0x38, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, - 0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d, - 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, - 0x3feb, 0x7d2, 0x365e, 0x76, 0x48c, - 0x3ffe, 0x5b3, 0x3feb, 0x76, 0x0, 0xd - }, /* fft mode 0 */ - { 0x3b, 0x6d9, 0x3f28, 0x7a7, 0x3a74, 0x196, 0x32a, 0x48c, - 0x3ffe, 0x7f3, 0x2d94, 0x76, 0x53d, - 0x3ff8, 0x7e3, 0x3320, 0x76, 0x5b3, - 0x3feb, 0x7d2, 0x365e, 0x76, 0x48c, - 0x3ffe, 0x5b3, 0x3feb, 0x0, 0x8200, 0xd - }, /* fft mode 1 */ -}; - -#define DIB3000MC_REG_UNK_88 ( 88) -#define DIB3000MC_UNK_88 (0x0410) - -static u16 dib3000mc_reg_bw[] = { 93,94,95,96,97,98 }; -static u16 dib3000mc_bw[][6] = { - { 0,0,0,0,0,0 }, /* 5 MHz */ - { 0,0,0,0,0,0 }, /* 6 MHz */ - { 0,0,0,0,0,0 }, /* 7 MHz */ - { 0x20, 0x21, 0x20, 0x23, 0x20, 0x27 }, /* 8 MHz */ -}; - - -/* phase noise control */ -#define DIB3000MC_REG_UNK_99 ( 99) -#define DIB3000MC_UNK_99 (0x0220) - -#define DIB3000MC_REG_SCAN_BOOST ( 100) -#define DIB3000MC_SCAN_BOOST_ON ((11 << 6) + 6) -#define DIB3000MC_SCAN_BOOST_OFF ((16 << 6) + 9) - -/* timeout ??? */ -#define DIB3000MC_REG_UNK_110 ( 110) -#define DIB3000MC_UNK_110 ( 3277) - -#define DIB3000MC_REG_UNK_111 ( 111) -#define DIB3000MC_UNK_111_PH_N_MODE_0 ( 0) -#define DIB3000MC_UNK_111_PH_N_MODE_1 (1 << 1) - -/* superious rm config */ -#define DIB3000MC_REG_UNK_120 ( 120) -#define DIB3000MC_UNK_120 ( 8207) - -#define DIB3000MC_REG_UNK_133 ( 133) -#define DIB3000MC_UNK_133 ( 15564) - -#define DIB3000MC_REG_UNK_134 ( 134) -#define DIB3000MC_UNK_134 ( 0) - -/* adapter config for constellation */ -static u16 dib3000mc_reg_adp_cfg[] = { 129, 130, 131, 132 }; - -static u16 dib3000mc_adp_cfg[][4] = { - { 0x99a, 0x7fae, 0x333, 0x7ff0 }, /* QPSK */ - { 0x23d, 0x7fdf, 0x0a4, 0x7ff0 }, /* 16-QAM */ - { 0x148, 0x7ff0, 0x0a4, 0x7ff8 }, /* 64-QAM */ -}; - -static u16 dib3000mc_reg_mobile_mode[] = { 139, 140, 141, 175, 1032 }; - -static u16 dib3000mc_mobile_mode[][5] = { - { 0x01, 0x0, 0x0, 0x00, 0x12c }, /* fixed */ - { 0x01, 0x0, 0x0, 0x00, 0x12c }, /* portable */ - { 0x00, 0x0, 0x0, 0x02, 0x000 }, /* mobile */ - { 0x00, 0x0, 0x0, 0x02, 0x000 }, /* auto */ -}; - -#define DIB3000MC_REG_DIVERSITY1 ( 177) -#define DIB3000MC_DIVERSITY1_DEFAULT ( 1) - -#define DIB3000MC_REG_DIVERSITY2 ( 178) -#define DIB3000MC_DIVERSITY2_DEFAULT ( 1) - -#define DIB3000MC_REG_DIVERSITY3 ( 180) -#define DIB3000MC_DIVERSITY3_IN_OFF (0xfff0) -#define DIB3000MC_DIVERSITY3_IN_ON (0xfff6) - -#define DIB3000MC_REG_FEC_CFG ( 195) -#define DIB3000MC_FEC_CFG ( 0x10) - -/* - * reg 206, output mode - * 1111 1111 - * |||| |||| - * |||| |||+- unk - * |||| ||+-- unk - * |||| |+--- unk (on by default) - * |||| +---- fifo_ctrl (1 = inhibit (flushed), 0 = active (unflushed)) - * |||+------ pid_parse (1 = enabled, 0 = disabled) - * ||+------- outp_188 (1 = TS packet size 188, 0 = packet size 204) - * |+-------- unk - * +--------- unk - */ - -#define DIB3000MC_REG_SMO_MODE ( 206) -#define DIB3000MC_SMO_MODE_DEFAULT (1 << 2) -#define DIB3000MC_SMO_MODE_FIFO_FLUSH (1 << 3) -#define DIB3000MC_SMO_MODE_FIFO_UNFLUSH (0xfff7) -#define DIB3000MC_SMO_MODE_PID_PARSE (1 << 4) -#define DIB3000MC_SMO_MODE_NO_PID_PARSE (0xffef) -#define DIB3000MC_SMO_MODE_188 (1 << 5) -#define DIB3000MC_SMO_MODE_SLAVE (DIB3000MC_SMO_MODE_DEFAULT | \ - DIB3000MC_SMO_MODE_188 | DIB3000MC_SMO_MODE_PID_PARSE | (1<<1)) - -#define DIB3000MC_REG_FIFO_THRESHOLD ( 207) -#define DIB3000MC_FIFO_THRESHOLD_DEFAULT ( 1792) -#define DIB3000MC_FIFO_THRESHOLD_SLAVE ( 512) -/* - * pidfilter - * it is not a hardware pidfilter but a filter which drops all pids - * except the ones set. When connected to USB1.1 bandwidth this is important. - * DiB3000P/M-C can filter up to 32 PIDs - */ -#define DIB3000MC_REG_FIRST_PID ( 212) -#define DIB3000MC_NUM_PIDS ( 32) - -#define DIB3000MC_REG_OUTMODE ( 244) -#define DIB3000MC_OM_PARALLEL_GATED_CLK ( 0) -#define DIB3000MC_OM_PAR_CONT_CLK (1 << 11) -#define DIB3000MC_OM_SERIAL (2 << 11) -#define DIB3000MC_OM_DIVOUT_ON (4 << 11) -#define DIB3000MC_OM_SLAVE (DIB3000MC_OM_DIVOUT_ON | DIB3000MC_OM_PAR_CONT_CLK) - -#define DIB3000MC_REG_RF_POWER ( 392) - -#define DIB3000MC_REG_FFT_POSITION ( 407) - -#define DIB3000MC_REG_DDS_FREQ_MSB ( 414) -#define DIB3000MC_REG_DDS_FREQ_LSB ( 415) - -#define DIB3000MC_REG_TIMING_OFFS_MSB ( 416) -#define DIB3000MC_REG_TIMING_OFFS_LSB ( 417) - -#define DIB3000MC_REG_TUNING_PARM ( 458) -#define DIB3000MC_TP_QAM(v) ((v >> 13) & 0x03) -#define DIB3000MC_TP_HRCH(v) ((v >> 12) & 0x01) -#define DIB3000MC_TP_ALPHA(v) ((v >> 9) & 0x07) -#define DIB3000MC_TP_FFT(v) ((v >> 8) & 0x01) -#define DIB3000MC_TP_FEC_CR_HP(v) ((v >> 5) & 0x07) -#define DIB3000MC_TP_FEC_CR_LP(v) ((v >> 2) & 0x07) -#define DIB3000MC_TP_GUARD(v) (v & 0x03) - -#define DIB3000MC_REG_SIGNAL_NOISE_MSB ( 483) -#define DIB3000MC_REG_SIGNAL_NOISE_LSB ( 484) - -#define DIB3000MC_REG_MER ( 485) - -#define DIB3000MC_REG_BER_MSB ( 500) -#define DIB3000MC_REG_BER_LSB ( 501) - -#define DIB3000MC_REG_PACKET_ERRORS ( 503) - -#define DIB3000MC_REG_PACKET_ERROR_COUNT ( 506) - -#define DIB3000MC_REG_LOCK_507 ( 507) -#define DIB3000MC_LOCK_507 (0x0002) // ? name correct ? - -#define DIB3000MC_REG_LOCKING ( 509) -#define DIB3000MC_AGC_LOCK(v) (v & 0x8000) -#define DIB3000MC_CARRIER_LOCK(v) (v & 0x2000) -#define DIB3000MC_MPEG_SYNC_LOCK(v) (v & 0x0080) -#define DIB3000MC_MPEG_DATA_LOCK(v) (v & 0x0040) -#define DIB3000MC_TPS_LOCK(v) (v & 0x0004) - -#define DIB3000MC_REG_AS_IRQ ( 511) -#define DIB3000MC_AS_IRQ_SUCCESS (1 << 1) -#define DIB3000MC_AS_IRQ_FAIL ( 1) - -#define DIB3000MC_REG_TUNER ( 769) - -#define DIB3000MC_REG_RST_I2C_ADDR ( 1024) -#define DIB3000MC_DEMOD_ADDR_ON ( 1) -#define DIB3000MC_DEMOD_ADDR(a) ((a << 4) & 0x03F0) - -#define DIB3000MC_REG_RESTART ( 1027) -#define DIB3000MC_RESTART_OFF (0x0000) -#define DIB3000MC_RESTART_AGC (0x0800) -#define DIB3000MC_RESTART_CONFIG (0x8000) - -#define DIB3000MC_REG_RESTART_VIT ( 1028) -#define DIB3000MC_RESTART_VIT_OFF ( 0) -#define DIB3000MC_RESTART_VIT_ON ( 1) - -#define DIB3000MC_REG_CLK_CFG_1 ( 1031) -#define DIB3000MC_CLK_CFG_1_POWER_UP ( 0) -#define DIB3000MC_CLK_CFG_1_POWER_DOWN (0xffff) - -#define DIB3000MC_REG_CLK_CFG_2 ( 1032) -#define DIB3000MC_CLK_CFG_2_PUP_FIXED (0x012c) -#define DIB3000MC_CLK_CFG_2_PUP_PORT (0x0104) -#define DIB3000MC_CLK_CFG_2_PUP_MOBILE (0x0000) -#define DIB3000MC_CLK_CFG_2_POWER_DOWN (0xffff) - -#define DIB3000MC_REG_CLK_CFG_3 ( 1033) -#define DIB3000MC_CLK_CFG_3_POWER_UP ( 0) -#define DIB3000MC_CLK_CFG_3_POWER_DOWN (0xfff5) - -#define DIB3000MC_REG_CLK_CFG_7 ( 1037) -#define DIB3000MC_CLK_CFG_7_INIT ( 12592) -#define DIB3000MC_CLK_CFG_7_POWER_UP (~0x0003) -#define DIB3000MC_CLK_CFG_7_PWR_DOWN (0x0003) -#define DIB3000MC_CLK_CFG_7_DIV_IN_OFF (1 << 8) - -/* was commented out ??? */ -#define DIB3000MC_REG_CLK_CFG_8 ( 1038) -#define DIB3000MC_CLK_CFG_8_POWER_UP (0x160c) - -#define DIB3000MC_REG_CLK_CFG_9 ( 1039) -#define DIB3000MC_CLK_CFG_9_POWER_UP ( 0) - -/* also clock ??? */ -#define DIB3000MC_REG_ELEC_OUT ( 1040) -#define DIB3000MC_ELEC_OUT_HIGH_Z ( 0) -#define DIB3000MC_ELEC_OUT_DIV_OUT_ON ( 1) -#define DIB3000MC_ELEC_OUT_SLAVE ( 3) - -#endif diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.c b/linux/drivers/media/dvb/frontends/dvb-pll.c index fce5c4252..c92877baa 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.c +++ b/linux/drivers/media/dvb/frontends/dvb-pll.c @@ -611,26 +611,27 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = { .get_bandwidth = dvb_pll_get_bandwidth, }; -int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) +struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) { u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { .addr = pll_addr, .flags = 0, .buf = NULL, .len = 0 }, - { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; + struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }; struct dvb_pll_priv *priv = NULL; int ret; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c != NULL) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); - ret = i2c_transfer (i2c, msg, 2); - if (ret != 2) - return -1; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + ret = i2c_transfer (i2c, &msg, 1); + if (ret != 1) + return NULL; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + } priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); if (priv == NULL) - return -ENOMEM; + return NULL; priv->pll_i2c_address = pll_addr; priv->i2c = i2c; @@ -642,7 +643,7 @@ int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2 fe->ops.tuner_ops.info.frequency_min = desc->max; fe->tuner_priv = priv; - return 0; + return fe; } EXPORT_SYMBOL(dvb_pll_attach); diff --git a/linux/drivers/media/dvb/frontends/dvb-pll.h b/linux/drivers/media/dvb/frontends/dvb-pll.h index 66361cd18..ed5ac5a36 100644 --- a/linux/drivers/media/dvb/frontends/dvb-pll.h +++ b/linux/drivers/media/dvb/frontends/dvb-pll.h @@ -57,8 +57,8 @@ extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf, * @param pll_addr i2c address of the PLL (if used). * @param i2c i2c adapter to use (set to NULL if not used). * @param desc dvb_pll_desc to use. - * @return 0 on success, nonzero on failure. + * @return Frontend pointer on success, NULL on failure */ -extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc); +extern struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc); #endif diff --git a/linux/drivers/media/dvb/frontends/isl6421.c b/linux/drivers/media/dvb/frontends/isl6421.c index 58c34db31..0fc18f5a7 100644 --- a/linux/drivers/media/dvb/frontends/isl6421.c +++ b/linux/drivers/media/dvb/frontends/isl6421.c @@ -42,12 +42,11 @@ struct isl6421 { u8 override_and; struct i2c_adapter *i2c; u8 i2c_addr; - void (*release_chain)(struct dvb_frontend* fe); }; static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { - struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; + struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv; struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0, .buf = &isl6421->config, .len = sizeof(isl6421->config) }; @@ -75,7 +74,7 @@ static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) { - struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; + struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv; struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0, .buf = &isl6421->config, .len = sizeof(isl6421->config) }; @@ -93,31 +92,26 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) static void isl6421_release(struct dvb_frontend *fe) { - struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; - /* power off */ isl6421_set_voltage(fe, SEC_VOLTAGE_OFF); - /* free data & call next release routine */ - fe->ops.release = isl6421->release_chain; - kfree(fe->misc_priv); - fe->misc_priv = NULL; - if (fe->ops.release) - fe->ops.release(fe); + /* free */ + kfree(fe->sec_priv); + fe->sec_priv = NULL; } -int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, +struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, u8 override_set, u8 override_clear) { struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL); if (!isl6421) - return -ENOMEM; + return NULL; /* default configuration */ isl6421->config = ISL6421_ISEL1; isl6421->i2c = i2c; isl6421->i2c_addr = i2c_addr; - fe->misc_priv = isl6421; + fe->sec_priv = isl6421; /* bits which should be forced to '1' */ isl6421->override_or = override_set; @@ -128,19 +122,17 @@ int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr /* detect if it is present or not */ if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) { kfree(isl6421); - fe->misc_priv = NULL; - return -EIO; + return NULL; } /* install release callback */ - isl6421->release_chain = fe->ops.release; fe->ops.release = isl6421_release; /* override frontend ops */ fe->ops.set_voltage = isl6421_set_voltage; fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage; - return 0; + return fe; } EXPORT_SYMBOL(isl6421_attach); diff --git a/linux/drivers/media/dvb/frontends/isl6421.h b/linux/drivers/media/dvb/frontends/isl6421.h index 675f80a19..1916e3eb2 100644 --- a/linux/drivers/media/dvb/frontends/isl6421.h +++ b/linux/drivers/media/dvb/frontends/isl6421.h @@ -39,8 +39,17 @@ #define ISL6421_ISEL1 0x20 #define ISL6421_DCL 0x40 +#if defined(CONFIG_DVB_ISL6421) || defined(CONFIG_DVB_ISL6421_MODULE) /* override_set and override_clear control which system register bits (above) to always set & clear */ -extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, +extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, u8 override_set, u8 override_clear); +#else +static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, + u8 override_set, u8 override_clear) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_ISL6421 #endif diff --git a/linux/drivers/media/dvb/frontends/l64781.h b/linux/drivers/media/dvb/frontends/l64781.h index 83b8bc210..21ba4a230 100644 --- a/linux/drivers/media/dvb/frontends/l64781.h +++ b/linux/drivers/media/dvb/frontends/l64781.h @@ -31,8 +31,16 @@ struct l64781_config u8 demod_address; }; - +#if defined(CONFIG_DVB_L64781) || defined(CONFIG_DVB_L64781_MODULE) extern struct dvb_frontend* l64781_attach(const struct l64781_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* l64781_attach(const struct l64781_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_L64781 #endif // L64781_H diff --git a/linux/drivers/media/dvb/frontends/lgdt330x.c b/linux/drivers/media/dvb/frontends/lgdt330x.c index b48b82b11..a1152c69c 100644 --- a/linux/drivers/media/dvb/frontends/lgdt330x.c +++ b/linux/drivers/media/dvb/frontends/lgdt330x.c @@ -216,7 +216,7 @@ static int lgdt330x_init(struct dvb_frontend* fe) AGC_DELAY0, 0x07, AGC_DELAY2, 0xfe, /* Change the value of IAGCBW[15:8] - of inner AGC loop filter bandwith */ + of inner AGC loop filter bandwidth */ AGC_LOOP_BANDWIDTH0, 0x08, AGC_LOOP_BANDWIDTH1, 0x9a }; diff --git a/linux/drivers/media/dvb/frontends/lgdt330x.h b/linux/drivers/media/dvb/frontends/lgdt330x.h index bad903c6f..3f96b4855 100644 --- a/linux/drivers/media/dvb/frontends/lgdt330x.h +++ b/linux/drivers/media/dvb/frontends/lgdt330x.h @@ -52,8 +52,17 @@ struct lgdt330x_config int clock_polarity_flip; }; +#if defined(CONFIG_DVB_LGDT330X) || defined(CONFIG_DVB_LGDT330X_MODULE) extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_LGDT330X #endif /* LGDT330X_H */ diff --git a/linux/drivers/media/dvb/frontends/lnbp21.c b/linux/drivers/media/dvb/frontends/lnbp21.c index e933edc8d..37bba32f2 100644 --- a/linux/drivers/media/dvb/frontends/lnbp21.c +++ b/linux/drivers/media/dvb/frontends/lnbp21.c @@ -40,12 +40,11 @@ struct lnbp21 { u8 override_or; u8 override_and; struct i2c_adapter *i2c; - void (*release_chain)(struct dvb_frontend* fe); }; static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv; struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &lnbp21->config, .len = sizeof(lnbp21->config) }; @@ -73,7 +72,7 @@ static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) { - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->sec_priv; struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = &lnbp21->config, .len = sizeof(lnbp21->config) }; @@ -91,29 +90,24 @@ static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) static void lnbp21_release(struct dvb_frontend *fe) { - struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; - /* LNBP power off */ lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); - /* free data & call next release routine */ - fe->ops.release = lnbp21->release_chain; - kfree(fe->misc_priv); - fe->misc_priv = NULL; - if (fe->ops.release) - fe->ops.release(fe); + /* free data */ + kfree(fe->sec_priv); + fe->sec_priv = NULL; } -int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) +struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) { struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL); if (!lnbp21) - return -ENOMEM; + return NULL; /* default configuration */ lnbp21->config = LNBP21_ISEL; lnbp21->i2c = i2c; - fe->misc_priv = lnbp21; + fe->sec_priv = lnbp21; /* bits which should be forced to '1' */ lnbp21->override_or = override_set; @@ -124,19 +118,17 @@ int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_ /* detect if it is present or not */ if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) { kfree(lnbp21); - fe->misc_priv = NULL; - return -EIO; + return NULL; } /* install release callback */ - lnbp21->release_chain = fe->ops.release; fe->ops.release = lnbp21_release; /* override frontend ops */ fe->ops.set_voltage = lnbp21_set_voltage; fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; - return 0; + return fe; } EXPORT_SYMBOL(lnbp21_attach); diff --git a/linux/drivers/media/dvb/frontends/lnbp21.h b/linux/drivers/media/dvb/frontends/lnbp21.h index 047a4ab68..1fe1dd179 100644 --- a/linux/drivers/media/dvb/frontends/lnbp21.h +++ b/linux/drivers/media/dvb/frontends/lnbp21.h @@ -39,7 +39,15 @@ #include <linux/dvb/frontend.h> +#if defined(CONFIG_DVB_LNBP21) || defined(CONFIG_DVB_LNBP21_MODULE) /* override_set and override_clear control which system register bits (above) to always set & clear */ -extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear); +extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear); +#else +static inline struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_LNBP21 -#endif +#endif // _LNBP21_H diff --git a/linux/drivers/media/dvb/frontends/mt2060.c b/linux/drivers/media/dvb/frontends/mt2060.c new file mode 100644 index 000000000..39b32de2c --- /dev/null +++ b/linux/drivers/media/dvb/frontends/mt2060.c @@ -0,0 +1,372 @@ +/* + * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner" + * + * Copyright (c) 2006 Olivier DANET <odanet@caramail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + */ + +/* In that file, frequencies are expressed in kiloHertz to avoid 32 bits overflows */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/delay.h> +#include <linux/dvb/frontend.h> +#include <linux/i2c.h> + +#include "dvb_frontend.h" + +#include "mt2060.h" +#include "mt2060_priv.h" + +static int debug; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); + +#define dprintk(args...) do { if (debug) {printk(KERN_DEBUG "MT2060: " args); printk("\n"); }} while (0) + +// Reads a single register +static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val) +{ + struct i2c_msg msg[2] = { + { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, + { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 }, + }; + + if (i2c_transfer(priv->i2c, msg, 2) != 2) { + printk(KERN_WARNING "mt2060 I2C read failed\n"); + return -EREMOTEIO; + } + return 0; +} + +// Writes a single register +static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val) +{ + u8 buf[2] = { reg, val }; + struct i2c_msg msg = { + .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2 + }; + + if (i2c_transfer(priv->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mt2060 I2C write failed\n"); + return -EREMOTEIO; + } + return 0; +} + +// Writes a set of consecutive registers +static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) +{ + struct i2c_msg msg = { + .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = len + }; + if (i2c_transfer(priv->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n",(int)len); + return -EREMOTEIO; + } + return 0; +} + +// Initialisation sequences +// LNABAND=3, NUM1=0x3C, DIV1=0x74, NUM2=0x1080, DIV2=0x49 +static u8 mt2060_config1[] = { + REG_LO1C1, + 0x3F, 0x74, 0x00, 0x08, 0x93 +}; + +// FMCG=2, GP2=0, GP1=0 +static u8 mt2060_config2[] = { + REG_MISC_CTRL, + 0x20, 0x1E, 0x30, 0xff, 0x80, 0xff, 0x00, 0x2c, 0x42 +}; + +// VGAG=3, V1CSE=1 +#if 0 +static u8 mt2060_config3[] = { + REG_VGAG, + 0x33 +}; +#endif + +#ifdef MT2060_SPURCHECK +/* The function below calculates the frequency offset between the output frequency if2 + and the closer cross modulation subcarrier between lo1 and lo2 up to the tenth harmonic */ +static int mt2060_spurcalc(u32 lo1,u32 lo2,u32 if2) +{ + int I,J; + int dia,diamin,diff; + diamin=1000000; + for (I = 1; I < 10; I++) { + J = ((2*I*lo1)/lo2+1)/2; + diff = I*(int)lo1-J*(int)lo2; + if (diff < 0) diff=-diff; + dia = (diff-(int)if2); + if (dia < 0) dia=-dia; + if (diamin > dia) diamin=dia; + } + return diamin; +} + +#define BANDWIDTH 4000 // kHz + +/* Calculates the frequency offset to add to avoid spurs. Returns 0 if no offset is needed */ +static int mt2060_spurcheck(u32 lo1,u32 lo2,u32 if2) +{ + u32 Spur,Sp1,Sp2; + int I,J; + I=0; + J=1000; + + Spur=mt2060_spurcalc(lo1,lo2,if2); + if (Spur < BANDWIDTH) { + /* Potential spurs detected */ + dprintk("Spurs before : f_lo1: %d f_lo2: %d (kHz)", + (int)lo1,(int)lo2); + I=1000; + Sp1 = mt2060_spurcalc(lo1+I,lo2+I,if2); + Sp2 = mt2060_spurcalc(lo1-I,lo2-I,if2); + + if (Sp1 < Sp2) { + J=-J; I=-I; Spur=Sp2; + } else + Spur=Sp1; + + while (Spur < BANDWIDTH) { + I += J; + Spur = mt2060_spurcalc(lo1+I,lo2+I,if2); + } + dprintk("Spurs after : f_lo1: %d f_lo2: %d (kHz)", + (int)(lo1+I),(int)(lo2+I)); + } + return I; +} +#endif + +#define IF2 36150 // IF2 frequency = 36.150 MHz +#define FREF 16000 // Quartz oscillator 16 MHz + +static int mt2060_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) +{ + struct mt2060_priv *priv; + int ret=0; + int i=0; + u32 freq; + u8 lnaband; + u32 f_lo1,f_lo2; + u32 div1,num1,div2,num2; + u8 b[8]; + u32 if1; + + priv = fe->tuner_priv; + + if1 = priv->if1_freq; + b[0] = REG_LO1B1; + b[1] = 0xFF; + + mt2060_writeregs(priv,b,2); + + freq = params->frequency / 1000; // Hz -> kHz + priv->bandwidth = (fe->ops.info.type == FE_OFDM) ? params->u.ofdm.bandwidth : 0; + + f_lo1 = freq + if1 * 1000; + f_lo1 = (f_lo1 / 250) * 250; + f_lo2 = f_lo1 - freq - IF2; + // From the Comtech datasheet, the step used is 50kHz. The tuner chip could be more precise + f_lo2 = ((f_lo2 + 25) / 50) * 50; + priv->frequency = (f_lo1 - f_lo2 - IF2) * 1000, + +#ifdef MT2060_SPURCHECK + // LO-related spurs detection and correction + num1 = mt2060_spurcheck(f_lo1,f_lo2,IF2); + f_lo1 += num1; + f_lo2 += num1; +#endif + //Frequency LO1 = 16MHz * (DIV1 + NUM1/64 ) + num1 = f_lo1 / (FREF / 64); + div1 = num1 / 64; + num1 &= 0x3f; + + // Frequency LO2 = 16MHz * (DIV2 + NUM2/8192 ) + num2 = f_lo2 * 64 / (FREF / 128); + div2 = num2 / 8192; + num2 &= 0x1fff; + + if (freq <= 95000) lnaband = 0xB0; else + if (freq <= 180000) lnaband = 0xA0; else + if (freq <= 260000) lnaband = 0x90; else + if (freq <= 335000) lnaband = 0x80; else + if (freq <= 425000) lnaband = 0x70; else + if (freq <= 480000) lnaband = 0x60; else + if (freq <= 570000) lnaband = 0x50; else + if (freq <= 645000) lnaband = 0x40; else + if (freq <= 730000) lnaband = 0x30; else + if (freq <= 810000) lnaband = 0x20; else lnaband = 0x10; + + b[0] = REG_LO1C1; + b[1] = lnaband | ((num1 >>2) & 0x0F); + b[2] = div1; + b[3] = (num2 & 0x0F) | ((num1 & 3) << 4); + b[4] = num2 >> 4; + b[5] = ((num2 >>12) & 1) | (div2 << 1); + + dprintk("IF1: %dMHz",(int)if1); + dprintk("PLL freq=%dkHz f_lo1=%dkHz f_lo2=%dkHz",(int)freq,(int)f_lo1,(int)f_lo2); + dprintk("PLL div1=%d num1=%d div2=%d num2=%d",(int)div1,(int)num1,(int)div2,(int)num2); + dprintk("PLL [1..5]: %2x %2x %2x %2x %2x",(int)b[1],(int)b[2],(int)b[3],(int)b[4],(int)b[5]); + + mt2060_writeregs(priv,b,6); + + //Waits for pll lock or timeout + i = 0; + do { + mt2060_readreg(priv,REG_LO_STATUS,b); + if ((b[0] & 0x88)==0x88) + break; + msleep(4); + i++; + } while (i<10); + + return ret; +} + +static void mt2060_calibrate(struct mt2060_priv *priv) +{ + u8 b = 0; + int i = 0; + + if (mt2060_writeregs(priv,mt2060_config1,sizeof(mt2060_config1))) + return; + if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2))) + return; + + do { + b |= (1 << 6); // FM1SS; + mt2060_writereg(priv, REG_LO2C1,b); + msleep(20); + + if (i == 0) { + b |= (1 << 7); // FM1CA; + mt2060_writereg(priv, REG_LO2C1,b); + b &= ~(1 << 7); // FM1CA; + msleep(20); + } + + b &= ~(1 << 6); // FM1SS + mt2060_writereg(priv, REG_LO2C1,b); + + msleep(20); + i++; + } while (i < 9); + + i = 0; + while (i++ < 10 && mt2060_readreg(priv, REG_MISC_STAT, &b) == 0 && (b & (1 << 6)) == 0) + msleep(20); + + if (i < 10) { + mt2060_readreg(priv, REG_FM_FREQ, &priv->fmfreq); // now find out, what is fmreq used for :) + dprintk("calibration was successful: %d", (int)priv->fmfreq); + } else + dprintk("FMCAL timed out"); +} + +static int mt2060_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len) +{ + return -ENODEV; +} + +static int mt2060_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct mt2060_priv *priv = fe->tuner_priv; + *frequency = priv->frequency; + return 0; +} + +static int mt2060_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct mt2060_priv *priv = fe->tuner_priv; + *bandwidth = priv->bandwidth; + return 0; +} + +static int mt2060_sleep(struct dvb_frontend *fe) +{ + struct mt2060_priv *priv = fe->tuner_priv; + return mt2060_writereg(priv, REG_VGAG,0x30); +} + +static int mt2060_release(struct dvb_frontend *fe) +{ + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static const struct dvb_tuner_ops mt2060_tuner_ops = { + .info = { + .name = "Microtune MT2060", + .frequency_min = 48000000, + .frequency_max = 860000000, + .frequency_step = 50000, + }, + + .release = mt2060_release, + + .sleep = mt2060_sleep, + + .set_params = mt2060_set_params, + .calc_regs = mt2060_calc_regs, + .get_frequency = mt2060_get_frequency, + .get_bandwidth = mt2060_get_bandwidth +}; + +/* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */ +int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1) +{ + struct mt2060_priv *priv = NULL; + u8 id = 0; + + priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + priv->cfg = cfg; + priv->i2c = i2c; + priv->if1_freq = if1; + + if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) { + kfree(priv); + return -ENODEV; + } + + if (id != PART_REV) { + kfree(priv); + return -ENODEV; + } + printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1); + memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = priv; + + mt2060_calibrate(priv); + + return 0; +} +EXPORT_SYMBOL(mt2060_attach); + +MODULE_AUTHOR("Olivier DANET"); +MODULE_DESCRIPTION("Microtune MT2060 silicon tuner driver"); +MODULE_LICENSE("GPL"); diff --git a/linux/drivers/media/dvb/frontends/mt2060.h b/linux/drivers/media/dvb/frontends/mt2060.h new file mode 100644 index 000000000..c58b03e82 --- /dev/null +++ b/linux/drivers/media/dvb/frontends/mt2060.h @@ -0,0 +1,35 @@ +/* + * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner" + * + * Copyright (c) 2006 Olivier DANET <odanet@caramail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + */ + +#ifndef MT2060_H +#define MT2060_H + +struct dvb_frontend; +struct i2c_adapter; + +struct mt2060_config { + u8 i2c_address; + /* Shall we add settings for the discrete outputs ? */ +}; + +extern int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1); + +#endif diff --git a/linux/drivers/media/dvb/frontends/mt2060_priv.h b/linux/drivers/media/dvb/frontends/mt2060_priv.h new file mode 100644 index 000000000..5eaccdefd --- /dev/null +++ b/linux/drivers/media/dvb/frontends/mt2060_priv.h @@ -0,0 +1,105 @@ +/* + * Driver for Microtune MT2060 "Single chip dual conversion broadband tuner" + * + * Copyright (c) 2006 Olivier DANET <odanet@caramail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= + */ + +#ifndef MT2060_PRIV_H +#define MT2060_PRIV_H + +// Uncomment the #define below to enable spurs checking. The results where quite unconvincing. +// #define MT2060_SPURCHECK + +/* This driver is based on the information available in the datasheet of the + "Comtech SDVBT-3K6M" tuner ( K1000737843.pdf ) which features the MT2060 register map : + + I2C Address : 0x60 + + Reg.No | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | ( defaults ) + -------------------------------------------------------------------------------- + 00 | [ PART ] | [ REV ] | R = 0x63 + 01 | [ LNABAND ] | [ NUM1(5:2) ] | RW = 0x3F + 02 | [ DIV1 ] | RW = 0x74 + 03 | FM1CA | FM1SS | [ NUM1(1:0) ] | [ NUM2(3:0) ] | RW = 0x00 + 04 | NUM2(11:4) ] | RW = 0x08 + 05 | [ DIV2 ] |NUM2(12)| RW = 0x93 + 06 | L1LK | [ TAD1 ] | L2LK | [ TAD2 ] | R + 07 | [ FMF ] | R + 08 | ? | FMCAL | ? | ? | ? | ? | ? | TEMP | R + 09 | 0 | 0 | [ FMGC ] | 0 | GP02 | GP01 | 0 | RW = 0x20 + 0A | ?? + 0B | 0 | 0 | 1 | 1 | 0 | 0 | [ VGAG ] | RW = 0x30 + 0C | V1CSE | 1 | 1 | 1 | 1 | 1 | 1 | 1 | RW = 0xFF + 0D | 1 | 0 | [ V1CS ] | RW = 0xB0 + 0E | ?? + 0F | ?? + 10 | ?? + 11 | [ LOTO ] | 0 | 0 | 1 | 0 | RW = 0x42 + + PART : Part code : 6 for MT2060 + REV : Revision code : 3 for current revision + LNABAND : Input frequency range : ( See code for details ) + NUM1 / DIV1 / NUM2 / DIV2 : Frequencies programming ( See code for details ) + FM1CA : Calibration Start Bit + FM1SS : Calibration Single Step bit + L1LK : LO1 Lock Detect + TAD1 : Tune Line ADC ( ? ) + L2LK : LO2 Lock Detect + TAD2 : Tune Line ADC ( ? ) + FMF : Estimated first IF Center frequency Offset ( ? ) + FM1CAL : Calibration done bit + TEMP : On chip temperature sensor + FMCG : Mixer 1 Cap Gain ( ? ) + GP01 / GP02 : Programmable digital outputs. Unconnected pins ? + V1CSE : LO1 VCO Automatic Capacitor Select Enable ( ? ) + V1CS : LO1 Capacitor Selection Value ( ? ) + LOTO : LO Timeout ( ? ) + VGAG : Tuner Output gain +*/ + +#define I2C_ADDRESS 0x60 + +#define REG_PART_REV 0 +#define REG_LO1C1 1 +#define REG_LO1C2 2 +#define REG_LO2C1 3 +#define REG_LO2C2 4 +#define REG_LO2C3 5 +#define REG_LO_STATUS 6 +#define REG_FM_FREQ 7 +#define REG_MISC_STAT 8 +#define REG_MISC_CTRL 9 +#define REG_RESERVED_A 0x0A +#define REG_VGAG 0x0B +#define REG_LO1B1 0x0C +#define REG_LO1B2 0x0D +#define REG_LOTO 0x11 + +#define PART_REV 0x63 // The current driver works only with PART=6 and REV=3 chips + +struct mt2060_priv { + struct mt2060_config *cfg; + struct i2c_adapter *i2c; + + u32 frequency; + u32 bandwidth; + u16 if1_freq; + u8 fmfreq; +}; + +#endif diff --git a/linux/drivers/media/dvb/frontends/mt312.h b/linux/drivers/media/dvb/frontends/mt312.h index 666a1bd1c..7112fb4d5 100644 --- a/linux/drivers/media/dvb/frontends/mt312.h +++ b/linux/drivers/media/dvb/frontends/mt312.h @@ -34,8 +34,16 @@ struct mt312_config u8 demod_address; }; +#if defined(CONFIG_DVB_MT312) || defined(CONFIG_DVB_MT312_MODULE) struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, struct i2c_adapter* i2c); - +#else +static inline struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_MT312 #endif // MT312_H diff --git a/linux/drivers/media/dvb/frontends/mt352.c b/linux/drivers/media/dvb/frontends/mt352.c index 5de7376c9..87e31ca7e 100644 --- a/linux/drivers/media/dvb/frontends/mt352.c +++ b/linux/drivers/media/dvb/frontends/mt352.c @@ -70,7 +70,7 @@ static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val) return 0; } -int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen) +static int _mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen) { int err,i; for (i=0; i < ilen-1; i++) @@ -107,7 +107,7 @@ static int mt352_sleep(struct dvb_frontend* fe) { static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 }; - mt352_write(fe, mt352_softdown, sizeof(mt352_softdown)); + _mt352_write(fe, mt352_softdown, sizeof(mt352_softdown)); return 0; } @@ -293,14 +293,14 @@ static int mt352_set_parameters(struct dvb_frontend* fe, fe->ops.i2c_gate_ctrl(fe, 0); } - mt352_write(fe, buf, 8); - mt352_write(fe, fsm_go, 2); + _mt352_write(fe, buf, 8); + _mt352_write(fe, fsm_go, 2); } else { if (fe->ops.tuner_ops.calc_regs) { fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5); buf[8] <<= 1; - mt352_write(fe, buf, sizeof(buf)); - mt352_write(fe, tuner_go, 2); + _mt352_write(fe, buf, sizeof(buf)); + _mt352_write(fe, tuner_go, 2); } } @@ -522,7 +522,7 @@ static int mt352_init(struct dvb_frontend* fe) (mt352_read_register(state, CONFIG) & 0x20) == 0) { /* Do a "hard" reset */ - mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach)); + _mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach)); return state->config.demod_init(fe); } @@ -585,6 +585,7 @@ static struct dvb_frontend_ops mt352_ops = { .init = mt352_init, .sleep = mt352_sleep, + .write = _mt352_write, .set_frontend = mt352_set_parameters, .get_frontend = mt352_get_parameters, @@ -605,4 +606,3 @@ MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(mt352_attach); -EXPORT_SYMBOL(mt352_write); diff --git a/linux/drivers/media/dvb/frontends/mt352.h b/linux/drivers/media/dvb/frontends/mt352.h index 9e7ff4b8f..0035c2e2d 100644 --- a/linux/drivers/media/dvb/frontends/mt352.h +++ b/linux/drivers/media/dvb/frontends/mt352.h @@ -51,9 +51,23 @@ struct mt352_config int (*demod_init)(struct dvb_frontend* fe); }; +#if defined(CONFIG_DVB_MT352) || defined(CONFIG_DVB_MT352_MODULE) extern struct dvb_frontend* mt352_attach(const struct mt352_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* mt352_attach(const struct mt352_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_MT352 -extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen); +static inline int mt352_write(struct dvb_frontend *fe, u8 *buf, int len) { + int r = 0; + if (fe->ops.write) + r = fe->ops.write(fe, buf, len); + return r; +} #endif // MT352_H diff --git a/linux/drivers/media/dvb/frontends/nxt200x.c b/linux/drivers/media/dvb/frontends/nxt200x.c index 55671cb52..87c286ee6 100644 --- a/linux/drivers/media/dvb/frontends/nxt200x.c +++ b/linux/drivers/media/dvb/frontends/nxt200x.c @@ -896,9 +896,9 @@ static int nxt2002_init(struct dvb_frontend* fe) } ret = nxt2002_load_firmware(fe, fw); + release_firmware(fw); if (ret) { printk("nxt2002: Writing firmware to device failed\n"); - release_firmware(fw); return ret; } printk("nxt2002: Firmware upload complete\n"); @@ -960,9 +960,9 @@ static int nxt2004_init(struct dvb_frontend* fe) } ret = nxt2004_load_firmware(fe, fw); + release_firmware(fw); if (ret) { printk("nxt2004: Writing firmware to device failed\n"); - release_firmware(fw); return ret; } printk("nxt2004: Firmware upload complete\n"); diff --git a/linux/drivers/media/dvb/frontends/nxt200x.h b/linux/drivers/media/dvb/frontends/nxt200x.h index 34d617358..2eb220e98 100644 --- a/linux/drivers/media/dvb/frontends/nxt200x.h +++ b/linux/drivers/media/dvb/frontends/nxt200x.h @@ -45,8 +45,17 @@ struct nxt200x_config int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); }; +#if defined(CONFIG_DVB_NXT200X) || defined(CONFIG_DVB_NXT200X_MODULE) extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_NXT200X #endif /* NXT200X_H */ diff --git a/linux/drivers/media/dvb/frontends/nxt6000.h b/linux/drivers/media/dvb/frontends/nxt6000.h index 117031d11..9397393a6 100644 --- a/linux/drivers/media/dvb/frontends/nxt6000.h +++ b/linux/drivers/media/dvb/frontends/nxt6000.h @@ -33,7 +33,16 @@ struct nxt6000_config u8 clock_inversion:1; }; +#if defined(CONFIG_DVB_NXT6000) || defined(CONFIG_DVB_NXT6000_MODULE) extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_NXT6000 #endif // NXT6000_H diff --git a/linux/drivers/media/dvb/frontends/or51132.h b/linux/drivers/media/dvb/frontends/or51132.h index 89658883a..9718be4fb 100644 --- a/linux/drivers/media/dvb/frontends/or51132.h +++ b/linux/drivers/media/dvb/frontends/or51132.h @@ -34,8 +34,17 @@ struct or51132_config int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); }; +#if defined(CONFIG_DVB_OR51132) || defined(CONFIG_DVB_OR51132_MODULE) extern struct dvb_frontend* or51132_attach(const struct or51132_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* or51132_attach(const struct or51132_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_OR51132 #endif // OR51132_H diff --git a/linux/drivers/media/dvb/frontends/or51211.c b/linux/drivers/media/dvb/frontends/or51211.c index 26bed616f..2bf124b53 100644 --- a/linux/drivers/media/dvb/frontends/or51211.c +++ b/linux/drivers/media/dvb/frontends/or51211.c @@ -437,10 +437,10 @@ static int or51211_init(struct dvb_frontend* fe) } ret = or51211_load_firmware(fe, fw); + release_firmware(fw); if (ret) { printk(KERN_WARNING "or51211: Writing firmware to " "device failed!\n"); - release_firmware(fw); return ret; } printk(KERN_INFO "or51211: Firmware upload complete.\n"); diff --git a/linux/drivers/media/dvb/frontends/or51211.h b/linux/drivers/media/dvb/frontends/or51211.h index 13a5a3afb..10a5419f9 100644 --- a/linux/drivers/media/dvb/frontends/or51211.h +++ b/linux/drivers/media/dvb/frontends/or51211.h @@ -37,8 +37,17 @@ struct or51211_config void (*sleep)(struct dvb_frontend * fe); }; +#if defined(CONFIG_DVB_OR51211) || defined(CONFIG_DVB_OR51211_MODULE) extern struct dvb_frontend* or51211_attach(const struct or51211_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* or51211_attach(const struct or51211_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_OR51211 #endif // OR51211_H diff --git a/linux/drivers/media/dvb/frontends/s5h1420.h b/linux/drivers/media/dvb/frontends/s5h1420.h index 4e39015fa..efc54d7f3 100644 --- a/linux/drivers/media/dvb/frontends/s5h1420.h +++ b/linux/drivers/media/dvb/frontends/s5h1420.h @@ -34,7 +34,16 @@ struct s5h1420_config u8 invert:1; }; +#if defined(CONFIG_DVB_S5H1420) || defined(CONFIG_DVB_S5H1420_MODULE) extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_S5H1420 #endif // S5H1420_H diff --git a/linux/drivers/media/dvb/frontends/sp8870.c b/linux/drivers/media/dvb/frontends/sp8870.c index 44ec5b9a4..d98fd5c2e 100644 --- a/linux/drivers/media/dvb/frontends/sp8870.c +++ b/linux/drivers/media/dvb/frontends/sp8870.c @@ -318,7 +318,6 @@ static int sp8870_init (struct dvb_frontend* fe) printk("sp8870: waiting for firmware upload (%s)...\n", SP8870_DEFAULT_FIRMWARE); if (state->config->request_firmware(fe, &fw, SP8870_DEFAULT_FIRMWARE)) { printk("sp8870: no firmware upload (timeout or file not found?)\n"); - release_firmware(fw); return -EIO; } @@ -327,6 +326,7 @@ static int sp8870_init (struct dvb_frontend* fe) release_firmware(fw); return -EIO; } + release_firmware(fw); printk("sp8870: firmware upload complete\n"); /* enable TS output and interface pins */ diff --git a/linux/drivers/media/dvb/frontends/sp8870.h b/linux/drivers/media/dvb/frontends/sp8870.h index 93afbb969..4cf27d3b1 100644 --- a/linux/drivers/media/dvb/frontends/sp8870.h +++ b/linux/drivers/media/dvb/frontends/sp8870.h @@ -35,7 +35,16 @@ struct sp8870_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; +#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE) extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* sp8870_attach(const struct sp8870_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_SP8870 #endif // SP8870_H diff --git a/linux/drivers/media/dvb/frontends/sp887x.c b/linux/drivers/media/dvb/frontends/sp887x.c index b0a2b02f6..5c2f8f4e0 100644 --- a/linux/drivers/media/dvb/frontends/sp887x.c +++ b/linux/drivers/media/dvb/frontends/sp887x.c @@ -520,9 +520,9 @@ static int sp887x_init(struct dvb_frontend* fe) } ret = sp887x_initial_setup(fe, fw); + release_firmware(fw); if (ret) { printk("sp887x: writing firmware to device failed\n"); - release_firmware(fw); return ret; } printk("sp887x: firmware upload complete\n"); diff --git a/linux/drivers/media/dvb/frontends/sp887x.h b/linux/drivers/media/dvb/frontends/sp887x.h index c44b0ebdf..cab7ea644 100644 --- a/linux/drivers/media/dvb/frontends/sp887x.h +++ b/linux/drivers/media/dvb/frontends/sp887x.h @@ -17,7 +17,16 @@ struct sp887x_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; +#if defined(CONFIG_DVB_SP887X) || defined(CONFIG_DVB_SP887X_MODULE) extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_SP887X #endif // SP887X_H diff --git a/linux/drivers/media/dvb/frontends/stv0297.h b/linux/drivers/media/dvb/frontends/stv0297.h index 1da5384fb..760b80db4 100644 --- a/linux/drivers/media/dvb/frontends/stv0297.h +++ b/linux/drivers/media/dvb/frontends/stv0297.h @@ -42,7 +42,16 @@ struct stv0297_config u8 stop_during_read:1; }; +#if defined(CONFIG_DVB_STV0297) || defined(CONFIG_DVB_STV0297_MODULE) extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_STV0297 #endif // STV0297_H diff --git a/linux/drivers/media/dvb/frontends/stv0299.c b/linux/drivers/media/dvb/frontends/stv0299.c index 96648a754..93483769e 100644 --- a/linux/drivers/media/dvb/frontends/stv0299.c +++ b/linux/drivers/media/dvb/frontends/stv0299.c @@ -92,11 +92,14 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data) return (ret != 1) ? -EREMOTEIO : 0; } -int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data) +int stv0299_write(struct dvb_frontend* fe, u8 *buf, int len) { struct stv0299_state* state = fe->demodulator_priv; - return stv0299_writeregI(state, reg, data); + if (len != 2) + return -EINVAL; + + return stv0299_writeregI(state, buf[0], buf[1]); } static u8 stv0299_readreg (struct stv0299_state* state, u8 reg) @@ -694,6 +697,7 @@ static struct dvb_frontend_ops stv0299_ops = { .init = stv0299_init, .sleep = stv0299_sleep, + .write = stv0299_write, .i2c_gate_ctrl = stv0299_i2c_gate_ctrl, .set_frontend = stv0299_set_frontend, @@ -724,5 +728,4 @@ MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, " "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly"); MODULE_LICENSE("GPL"); -EXPORT_SYMBOL(stv0299_writereg); EXPORT_SYMBOL(stv0299_attach); diff --git a/linux/drivers/media/dvb/frontends/stv0299.h b/linux/drivers/media/dvb/frontends/stv0299.h index 1504828e4..7ef252070 100644 --- a/linux/drivers/media/dvb/frontends/stv0299.h +++ b/linux/drivers/media/dvb/frontends/stv0299.h @@ -89,9 +89,24 @@ struct stv0299_config int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio); }; -extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data); - +#if defined(CONFIG_DVB_STV0299) || defined(CONFIG_DVB_STV0299_MODULE) extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_STV0299 + +static inline int stv0299_writereg(struct dvb_frontend *fe, u8 reg, u8 val) { + int r = 0; + u8 buf[] = {reg, val}; + if (fe->ops.write) + r = fe->ops.write(fe, buf, 2); + return r; +} #endif // STV0299_H diff --git a/linux/drivers/media/dvb/frontends/tda10021.c b/linux/drivers/media/dvb/frontends/tda10021.c index 48b02abd0..8b7bbdf2e 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.c +++ b/linux/drivers/media/dvb/frontends/tda10021.c @@ -21,7 +21,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/config.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/init.h> @@ -73,7 +72,7 @@ static u8 tda10021_inittab[0x40]= 0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00, }; -static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data) +static int _tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data) { u8 buf[] = { reg, data }; struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; @@ -89,14 +88,6 @@ static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data) return (ret != 1) ? -EREMOTEIO : 0; } -int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data) -{ - struct tda10021_state* state = fe->demodulator_priv; - - return tda10021_writereg(state, reg, data); -} -EXPORT_SYMBOL(tda10021_write_byte); - static u8 tda10021_readreg (struct tda10021_state* state, u8 reg) { u8 b0 [] = { reg }; @@ -150,8 +141,8 @@ static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0, else if (INVERSION_OFF == inversion) DISABLE_INVERSION(reg0); - tda10021_writereg (state, 0x00, reg0 & 0xfe); - tda10021_writereg (state, 0x00, reg0 | 0x01); + _tda10021_writereg (state, 0x00, reg0 & 0xfe); + _tda10021_writereg (state, 0x00, reg0 | 0x01); state->reg0 = reg0; return 0; @@ -199,17 +190,27 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate NDEC = (NDEC << 6) | tda10021_inittab[0x03]; - tda10021_writereg (state, 0x03, NDEC); - tda10021_writereg (state, 0x0a, BDR&0xff); - tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff); - tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f); + _tda10021_writereg (state, 0x03, NDEC); + _tda10021_writereg (state, 0x0a, BDR&0xff); + _tda10021_writereg (state, 0x0b, (BDR>> 8)&0xff); + _tda10021_writereg (state, 0x0c, (BDR>>16)&0x3f); - tda10021_writereg (state, 0x0d, BDRI); - tda10021_writereg (state, 0x0e, SFIL); + _tda10021_writereg (state, 0x0d, BDRI); + _tda10021_writereg (state, 0x0e, SFIL); return 0; } +int tda10021_write(struct dvb_frontend* fe, u8 *buf, int len) +{ + struct tda10021_state* state = fe->demodulator_priv; + + if (len != 2) + return -EINVAL; + + return _tda10021_writereg(state, buf[0], buf[1]); +} + static int tda10021_init (struct dvb_frontend *fe) { struct tda10021_state* state = fe->demodulator_priv; @@ -217,12 +218,12 @@ static int tda10021_init (struct dvb_frontend *fe) dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num); - //tda10021_writereg (fe, 0, 0); + //_tda10021_writereg (fe, 0, 0); for (i=0; i<tda10021_inittab_size; i++) - tda10021_writereg (state, i, tda10021_inittab[i]); + _tda10021_writereg (state, i, tda10021_inittab[i]); - tda10021_writereg (state, 0x34, state->pwm); + _tda10021_writereg (state, 0x34, state->pwm); //Comment by markus //0x2A[3-0] == PDIV -> P multiplaying factor (P=PDIV+1)(default 0) @@ -231,7 +232,7 @@ static int tda10021_init (struct dvb_frontend *fe) //0x2A[6] == POLAXIN -> Polarity of the input reference clock (default 0) //Activate PLL - tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef); + _tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef); return 0; } @@ -265,12 +266,12 @@ static int tda10021_set_parameters (struct dvb_frontend *fe, } tda10021_set_symbolrate (state, p->u.qam.symbol_rate); - tda10021_writereg (state, 0x34, state->pwm); + _tda10021_writereg (state, 0x34, state->pwm); - tda10021_writereg (state, 0x01, reg0x01[qam]); - tda10021_writereg (state, 0x05, reg0x05[qam]); - tda10021_writereg (state, 0x08, reg0x08[qam]); - tda10021_writereg (state, 0x09, reg0x09[qam]); + _tda10021_writereg (state, 0x01, reg0x01[qam]); + _tda10021_writereg (state, 0x05, reg0x05[qam]); + _tda10021_writereg (state, 0x08, reg0x08[qam]); + _tda10021_writereg (state, 0x09, reg0x09[qam]); tda10021_setup_reg0 (state, reg0x00[qam], p->inversion); @@ -343,8 +344,8 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) *ucblocks = 0xffffffff; /* reset uncorrected block counter */ - tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf); - tda10021_writereg (state, 0x10, tda10021_inittab[0x10]); + _tda10021_writereg (state, 0x10, tda10021_inittab[0x10] & 0xdf); + _tda10021_writereg (state, 0x10, tda10021_inittab[0x10]); return 0; } @@ -393,8 +394,8 @@ static int tda10021_sleep(struct dvb_frontend* fe) { struct tda10021_state* state = fe->demodulator_priv; - tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */ - tda10021_writereg (state, 0x00, 0x80); /* standby */ + _tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */ + _tda10021_writereg (state, 0x00, 0x80); /* standby */ return 0; } @@ -460,6 +461,7 @@ static struct dvb_frontend_ops tda10021_ops = { .init = tda10021_init, .sleep = tda10021_sleep, + .write = tda10021_write, .i2c_gate_ctrl = tda10021_i2c_gate_ctrl, .set_frontend = tda10021_set_parameters, diff --git a/linux/drivers/media/dvb/frontends/tda10021.h b/linux/drivers/media/dvb/frontends/tda10021.h index b1df4259b..d68ae20c8 100644 --- a/linux/drivers/media/dvb/frontends/tda10021.h +++ b/linux/drivers/media/dvb/frontends/tda10021.h @@ -32,9 +32,24 @@ struct tda10021_config u8 demod_address; }; +#if defined(CONFIG_DVB_TDA10021) || defined(CONFIG_DVB_TDA10021_MODULE) extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config, struct i2c_adapter* i2c, u8 pwm); - -extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data); +#else +static inline struct dvb_frontend* tda10021_attach(const struct tda10021_config* config, + struct i2c_adapter* i2c, u8 pwm) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TDA10021 + +static inline int tda10021_writereg(struct dvb_frontend *fe, u8 reg, u8 val) { + int r = 0; + u8 buf[] = {reg, val}; + if (fe->ops.write) + r = fe->ops.write(fe, buf, 2); + return r; +} #endif // TDA10021_H diff --git a/linux/drivers/media/dvb/frontends/tda1004x.c b/linux/drivers/media/dvb/frontends/tda1004x.c index 59a2ed614..11e0dca9a 100644 --- a/linux/drivers/media/dvb/frontends/tda1004x.c +++ b/linux/drivers/media/dvb/frontends/tda1004x.c @@ -579,11 +579,14 @@ static int tda1004x_decode_fec(int tdafec) return -1; } -int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data) +int tda1004x_write(struct dvb_frontend* fe, u8 *buf, int len) { struct tda1004x_state* state = fe->demodulator_priv; - return tda1004x_write_byteI(state, reg, data); + if (len != 2) + return -EINVAL; + + return tda1004x_write_byteI(state, buf[0], buf[1]); } static int tda10045_init(struct dvb_frontend* fe) @@ -1216,6 +1219,7 @@ static struct dvb_frontend_ops tda10045_ops = { .init = tda10045_init, .sleep = tda1004x_sleep, + .write = tda1004x_write, .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl, .set_frontend = tda1004x_set_fe, @@ -1274,6 +1278,7 @@ static struct dvb_frontend_ops tda10046_ops = { .init = tda10046_init, .sleep = tda1004x_sleep, + .write = tda1004x_write, .i2c_gate_ctrl = tda1004x_i2c_gate_ctrl, .set_frontend = tda1004x_set_fe, @@ -1323,4 +1328,3 @@ MODULE_LICENSE("GPL"); EXPORT_SYMBOL(tda10045_attach); EXPORT_SYMBOL(tda10046_attach); -EXPORT_SYMBOL(tda1004x_write_byte); diff --git a/linux/drivers/media/dvb/frontends/tda1004x.h b/linux/drivers/media/dvb/frontends/tda1004x.h index b877b23ed..e28fca057 100644 --- a/linux/drivers/media/dvb/frontends/tda1004x.h +++ b/linux/drivers/media/dvb/frontends/tda1004x.h @@ -71,12 +71,33 @@ struct tda1004x_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; +#if defined(CONFIG_DVB_TDA1004X) || defined(CONFIG_DVB_TDA1004X_MODULE) extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, struct i2c_adapter* i2c); extern struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, struct i2c_adapter* i2c); - -extern int tda1004x_write_byte(struct dvb_frontend* fe, int reg, int data); +#else +static inline struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +static inline struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TDA1004X + +static inline int tda1004x_writereg(struct dvb_frontend *fe, u8 reg, u8 val) { + int r = 0; + u8 buf[] = {reg, val}; + if (fe->ops.write) + r = fe->ops.write(fe, buf, 2); + return r; +} #endif // TDA1004X_H diff --git a/linux/drivers/media/dvb/frontends/tda8083.h b/linux/drivers/media/dvb/frontends/tda8083.h index e7a48f61e..aae15bdce 100644 --- a/linux/drivers/media/dvb/frontends/tda8083.h +++ b/linux/drivers/media/dvb/frontends/tda8083.h @@ -35,7 +35,16 @@ struct tda8083_config u8 demod_address; }; +#if defined(CONFIG_DVB_TDA8083) || defined(CONFIG_DVB_TDA8083_MODULE) extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TDA8083 #endif // TDA8083_H diff --git a/linux/drivers/media/dvb/frontends/tda80xx.c b/linux/drivers/media/dvb/frontends/tda80xx.c index 996fd4beb..83fc57a22 100644 --- a/linux/drivers/media/dvb/frontends/tda80xx.c +++ b/linux/drivers/media/dvb/frontends/tda80xx.c @@ -21,7 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/config.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/spinlock.h> diff --git a/linux/drivers/media/dvb/frontends/tda80xx.h b/linux/drivers/media/dvb/frontends/tda80xx.h index 435dd9477..ce472b3fb 100644 --- a/linux/drivers/media/dvb/frontends/tda80xx.h +++ b/linux/drivers/media/dvb/frontends/tda80xx.h @@ -41,7 +41,16 @@ struct tda80xx_config u8 volt18setting; }; +#if defined(CONFIG_DVB_TDA80XX) || defined(CONFIG_DVB_TDA80XX_MODULE) extern struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TDA80XX #endif // TDA80XX_H diff --git a/linux/drivers/media/dvb/frontends/ves1820.c b/linux/drivers/media/dvb/frontends/ves1820.c index 6bffe85c1..9b57576bf 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.c +++ b/linux/drivers/media/dvb/frontends/ves1820.c @@ -18,7 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/config.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/init.h> diff --git a/linux/drivers/media/dvb/frontends/ves1820.h b/linux/drivers/media/dvb/frontends/ves1820.h index 520f09522..f0c9dded3 100644 --- a/linux/drivers/media/dvb/frontends/ves1820.h +++ b/linux/drivers/media/dvb/frontends/ves1820.h @@ -41,7 +41,16 @@ struct ves1820_config u8 selagc:1; }; +#if defined(CONFIG_DVB_VES1820) || defined(CONFIG_DVB_VES1820_MODULE) extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, struct i2c_adapter* i2c, u8 pwm); +#else +static inline struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, + struct i2c_adapter* i2c, u8 pwm) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_VES1820 #endif // VES1820_H diff --git a/linux/drivers/media/dvb/frontends/ves1x93.h b/linux/drivers/media/dvb/frontends/ves1x93.h index ba88ae085..395fed39b 100644 --- a/linux/drivers/media/dvb/frontends/ves1x93.h +++ b/linux/drivers/media/dvb/frontends/ves1x93.h @@ -40,7 +40,16 @@ struct ves1x93_config u8 invert_pwm:1; }; +#if defined(CONFIG_DVB_VES1X93) || defined(CONFIG_DVB_VES1X93_MODULE) extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, struct i2c_adapter* i2c); +#else +static inline struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, + struct i2c_adapter* i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_VES1X93 #endif // VES1X93_H diff --git a/linux/drivers/media/dvb/frontends/zl10353.c b/linux/drivers/media/dvb/frontends/zl10353.c index 27001b453..1d22d53dc 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.c +++ b/linux/drivers/media/dvb/frontends/zl10353.c @@ -268,7 +268,6 @@ static int zl10353_init(struct dvb_frontend *fe) static void zl10353_release(struct dvb_frontend *fe) { struct zl10353_state *state = fe->demodulator_priv; - kfree(state); } @@ -324,6 +323,7 @@ static struct dvb_frontend_ops zl10353_ops = { .init = zl10353_init, .sleep = zl10353_sleep, + .write = zl10353_write, .set_frontend = zl10353_set_parameters, .get_tune_settings = zl10353_get_tune_settings, @@ -342,4 +342,3 @@ MODULE_AUTHOR("Chris Pascoe"); MODULE_LICENSE("GPL"); EXPORT_SYMBOL(zl10353_attach); -EXPORT_SYMBOL(zl10353_write); diff --git a/linux/drivers/media/dvb/frontends/zl10353.h b/linux/drivers/media/dvb/frontends/zl10353.h index 9770cb840..6aec655d8 100644 --- a/linux/drivers/media/dvb/frontends/zl10353.h +++ b/linux/drivers/media/dvb/frontends/zl10353.h @@ -33,9 +33,16 @@ struct zl10353_config int no_tuner; }; +#if defined(CONFIG_DVB_ZL10353) || defined(CONFIG_DVB_ZL10353_MODULE) extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, struct i2c_adapter *i2c); - -extern int zl10353_write(struct dvb_frontend *fe, u8 *ibuf, int ilen); +#else +static inline struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, + struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_ZL10353 #endif /* ZL10353_H */ diff --git a/linux/drivers/media/dvb/pluto2/pluto2.c b/linux/drivers/media/dvb/pluto2/pluto2.c index acabea079..2310b2bfe 100644 --- a/linux/drivers/media/dvb/pluto2/pluto2.c +++ b/linux/drivers/media/dvb/pluto2/pluto2.c @@ -616,7 +616,7 @@ static int __devinit pluto2_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, pluto); - ret = request_irq(pdev->irq, pluto_irq, SA_SHIRQ, DRIVER_NAME, pluto); + ret = request_irq(pdev->irq, pluto_irq, IRQF_SHARED, DRIVER_NAME, pluto); if (ret < 0) goto err_pci_iounmap; diff --git a/linux/drivers/media/dvb/ttpci/Kconfig b/linux/drivers/media/dvb/ttpci/Kconfig index 987881fa9..0f01b9ff1 100644 --- a/linux/drivers/media/dvb/ttpci/Kconfig +++ b/linux/drivers/media/dvb/ttpci/Kconfig @@ -3,14 +3,14 @@ config DVB_AV7110 depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select FW_LOADER select VIDEO_SAA7146_VV - select DVB_VES1820 - select DVB_VES1X93 - select DVB_STV0299 - select DVB_TDA8083 - select DVB_SP8870 - select DVB_STV0297 - select DVB_L64781 - select DVB_LNBP21 + select DVB_VES1820 if !DVB_FE_CUSTOMISE + select DVB_VES1X93 if !DVB_FE_CUSTOMISE + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_TDA8083 if !DVB_FE_CUSTOMISE + select DVB_SP8870 if !DVB_FE_CUSTOMISE + select DVB_STV0297 if !DVB_FE_CUSTOMISE + select DVB_L64781 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE help Support for SAA7146 and AV7110 based DVB cards as produced by Fujitsu-Siemens, Technotrend, Hauppauge and others. @@ -61,14 +61,14 @@ config DVB_BUDGET tristate "Budget cards" depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146 - select DVB_STV0299 - select DVB_VES1X93 - select DVB_VES1820 - select DVB_L64781 - select DVB_TDA8083 - select DVB_TDA10021 - select DVB_S5H1420 - select DVB_LNBP21 + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_VES1X93 if !DVB_FE_CUSTOMISE + select DVB_VES1820 if !DVB_FE_CUSTOMISE + select DVB_L64781 if !DVB_FE_CUSTOMISE + select DVB_TDA8083 if !DVB_FE_CUSTOMISE + select DVB_TDA10021 if !DVB_FE_CUSTOMISE + select DVB_S5H1420 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -83,10 +83,10 @@ config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146 - select DVB_STV0297 - select DVB_STV0299 - select DVB_TDA1004X - select DVB_LNBP21 + select DVB_STV0297 if !DVB_FE_CUSTOMISE + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_TDA1004X if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard @@ -104,9 +104,9 @@ config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146_VV - select DVB_STV0299 - select DVB_TDA1004X - select DVB_TDA10021 + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_TDA1004X if !DVB_FE_CUSTOMISE + select DVB_TDA10021 if !DVB_FE_CUSTOMISE select FW_LOADER help Support for simple SAA7146 based DVB cards @@ -122,9 +122,9 @@ config DVB_BUDGET_PATCH tristate "AV7110 cards with Budget Patch" depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1 select DVB_AV7110 - select DVB_STV0299 - select DVB_VES1X93 - select DVB_TDA8083 + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_VES1X93 if !DVB_FE_CUSTOMISE + select DVB_TDA8083 if !DVB_FE_CUSTOMISE help Support for Budget Patch (full TS) modification on SAA7146+AV7110 based cards (DVB-S cards). This diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c index e3eee1bbd..b08c54e79 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.c +++ b/linux/drivers/media/dvb/ttpci/av7110.c @@ -30,7 +30,6 @@ */ -#include <linux/config.h> #include <linux/module.h> #include <linux/kmod.h> #include <linux/delay.h> @@ -1384,8 +1383,10 @@ static void dvb_unregister(struct av7110 *av7110) dvb_dmxdev_release(&av7110->dmxdev); dvb_dmx_release(&av7110->demux); - if (av7110->fe != NULL) + if (av7110->fe != NULL) { dvb_unregister_frontend(av7110->fe); + dvb_frontend_detach(av7110->fe); + } dvb_unregister_device(av7110->osd_dev); av7110_av_unregister(av7110); av7110_ca_unregister(av7110); @@ -2078,7 +2079,7 @@ static int frontend_init(struct av7110 *av7110) if (av7110->dev->pci->subsystem_vendor == 0x110a) { switch(av7110->dev->pci->subsystem_device) { case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??)) - av7110->fe = ves1820_attach(&philips_cd1516_config, + av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap, read_pwm(av7110)); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params; @@ -2093,7 +2094,7 @@ static int frontend_init(struct av7110 *av7110) case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE // try the ALPS BSRV2 first of all - av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; @@ -2104,7 +2105,7 @@ static int frontend_init(struct av7110 *av7110) } // try the ALPS BSRU6 now - av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(stv0299_attach, &alps_bsru6_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; av7110->fe->tuner_priv = &av7110->i2c_adap; @@ -2117,7 +2118,7 @@ static int frontend_init(struct av7110 *av7110) } // Try the grundig 29504-451 - av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; @@ -2131,7 +2132,7 @@ static int frontend_init(struct av7110 *av7110) switch(av7110->dev->pci->subsystem_device) { case 0x0000: /* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */ - av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap, + av7110->fe = dvb_attach(ves1820_attach, &philips_cd1516_config, &av7110->i2c_adap, read_pwm(av7110)); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params; @@ -2139,7 +2140,7 @@ static int frontend_init(struct av7110 *av7110) break; case 0x0003: /* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */ - av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, + av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; @@ -2151,7 +2152,7 @@ static int frontend_init(struct av7110 *av7110) case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X // ALPS TDLB7 - av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(sp8870_attach, &alps_tdlb7_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params; } @@ -2159,7 +2160,7 @@ static int frontend_init(struct av7110 *av7110) case 0x0002: // Hauppauge/TT DVB-C premium rev2.X - av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); + av7110->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110)); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; } @@ -2167,7 +2168,7 @@ static int frontend_init(struct av7110 *av7110) case 0x0004: // Galaxis DVB-S rev1.3 /* ALPS BSRV2 */ - av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; @@ -2179,7 +2180,7 @@ static int frontend_init(struct av7110 *av7110) case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */ /* Grundig 29504-451 */ - av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(tda8083_attach, &grundig_29504_451_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd; @@ -2191,7 +2192,7 @@ static int frontend_init(struct av7110 *av7110) case 0x0008: // Hauppauge/TT DVB-T - av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(l64781_attach, &grundig_29504_401_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; } @@ -2199,7 +2200,7 @@ static int frontend_init(struct av7110 *av7110) case 0x000A: // Hauppauge/TT Nexus-CA rev1.X - av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(stv0297_attach, &nexusca_stv0297_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params; @@ -2215,12 +2216,12 @@ static int frontend_init(struct av7110 *av7110) case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */ /* ALPS BSBE1 */ - av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap); + av7110->fe = dvb_attach(stv0299_attach, &alps_bsbe1_config, &av7110->i2c_adap); if (av7110->fe) { av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params; av7110->fe->tuner_priv = &av7110->i2c_adap; - if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) { + if (dvb_attach(lnbp21_attach, av7110->fe, &av7110->i2c_adap, 0, 0) == NULL) { printk("dvb-ttpci: LNBP21 not found!\n"); if (av7110->fe->ops.release) av7110->fe->ops.release(av7110->fe); @@ -2256,8 +2257,7 @@ static int frontend_init(struct av7110 *av7110) ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe); if (ret < 0) { printk("av7110: Frontend registration failed!\n"); - if (av7110->fe->ops.release) - av7110->fe->ops.release(av7110->fe); + dvb_frontend_detach(av7110->fe); av7110->fe = NULL; } } diff --git a/linux/drivers/media/dvb/ttpci/av7110.h b/linux/drivers/media/dvb/ttpci/av7110.h index 51e8c3eca..c1fe289d3 100644 --- a/linux/drivers/media/dvb/ttpci/av7110.h +++ b/linux/drivers/media/dvb/ttpci/av7110.h @@ -6,10 +6,6 @@ #include <linux/netdevice.h> #include <linux/i2c.h> -#ifdef CONFIG_DEVFS_FS -#include <linux/devfs_fs_kernel.h> -#endif - #include <linux/dvb/video.h> #include <linux/dvb/audio.h> #include <linux/dvb/dmx.h> diff --git a/linux/drivers/media/dvb/ttpci/av7110_av.c b/linux/drivers/media/dvb/ttpci/av7110_av.c index 0f3a044ae..8c577cf30 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_av.c +++ b/linux/drivers/media/dvb/ttpci/av7110_av.c @@ -33,7 +33,6 @@ #include <linux/string.h> #include <linux/sched.h> #include <linux/delay.h> -#include <linux/byteorder/swabb.h> #include <linux/smp_lock.h> #include <linux/fs.h> diff --git a/linux/drivers/media/dvb/ttpci/av7110_ca.c b/linux/drivers/media/dvb/ttpci/av7110_ca.c index 6079e8865..dd9aee314 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_ca.c +++ b/linux/drivers/media/dvb/ttpci/av7110_ca.c @@ -35,7 +35,6 @@ #include <linux/fs.h> #include <linux/timer.h> #include <linux/poll.h> -#include <linux/byteorder/swabb.h> #include <linux/smp_lock.h> #include "av7110.h" diff --git a/linux/drivers/media/dvb/ttpci/av7110_hw.c b/linux/drivers/media/dvb/ttpci/av7110_hw.c index 668f6cc10..bfd9ad371 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_hw.c +++ b/linux/drivers/media/dvb/ttpci/av7110_hw.c @@ -34,7 +34,6 @@ #include <linux/string.h> #include <linux/sched.h> #include <linux/delay.h> -#include <linux/byteorder/swabb.h> #include <linux/smp_lock.h> #include <linux/fs.h> diff --git a/linux/drivers/media/dvb/ttpci/av7110_v4l.c b/linux/drivers/media/dvb/ttpci/av7110_v4l.c index 6ffe53fdc..52b500a38 100644 --- a/linux/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/linux/drivers/media/dvb/ttpci/av7110_v4l.c @@ -32,7 +32,6 @@ #include <linux/fs.h> #include <linux/timer.h> #include <linux/poll.h> -#include <linux/byteorder/swabb.h> #include <linux/smp_lock.h> #include "av7110.h" diff --git a/linux/drivers/media/dvb/ttpci/budget-av.c b/linux/drivers/media/dvb/ttpci/budget-av.c index 5f111d407..6f1c41fb2 100644 --- a/linux/drivers/media/dvb/ttpci/budget-av.c +++ b/linux/drivers/media/dvb/ttpci/budget-av.c @@ -235,7 +235,7 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) /* set tda10021 back to original clock configuration on reset */ if (budget_av->tda10021_poclkp) { - tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0); budget_av->tda10021_ts_enabled = 0; } @@ -257,7 +257,7 @@ static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) /* set tda10021 back to original clock configuration when cam removed */ if (budget_av->tda10021_poclkp) { - tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0); budget_av->tda10021_ts_enabled = 0; } return 0; @@ -277,7 +277,7 @@ static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) /* tda10021 seems to need a different TS clock config when data is routed to the CAM */ if (budget_av->tda10021_poclkp) { - tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1); + tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa1); budget_av->tda10021_ts_enabled = 1; } @@ -1068,9 +1068,9 @@ static int tda10021_set_frontend(struct dvb_frontend *fe, result = budget_av->tda10021_set_frontend(fe, p); if (budget_av->tda10021_ts_enabled) { - tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1); + tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa1); } else { - tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0); + tda10021_writereg(budget_av->budget.dvb_frontend, 0x12, 0xa0); } return result; @@ -1098,13 +1098,13 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBS_KNC1: case SUBID_DVBS_EASYWATCH_1: if (saa->pci->subsystem_vendor == 0x1894) { - fe = stv0299_attach(&cinergy_1200s_1894_0010_config, + fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config, &budget_av->budget.i2c_adap); if (fe) { fe->ops.tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params; } } else { - fe = stv0299_attach(&typhoon_config, + fe = dvb_attach(stv0299_attach, &typhoon_config, &budget_av->budget.i2c_adap); if (fe) { fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; @@ -1116,7 +1116,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBS_TV_STAR_CI: case SUBID_DVBS_CYNERGY1200N: case SUBID_DVBS_EASYWATCH: - fe = stv0299_attach(&philips_sd1878_config, + fe = dvb_attach(stv0299_attach, &philips_sd1878_config, &budget_av->budget.i2c_adap); if (fe) { fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params; @@ -1125,7 +1125,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBS_TYPHOON: - fe = stv0299_attach(&typhoon_config, + fe = dvb_attach(stv0299_attach, &typhoon_config, &budget_av->budget.i2c_adap); if (fe) { fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; @@ -1133,7 +1133,7 @@ static void frontend_init(struct budget_av *budget_av) break; case SUBID_DVBS_CINERGY1200: - fe = stv0299_attach(&cinergy_1200s_config, + fe = dvb_attach(stv0299_attach, &cinergy_1200s_config, &budget_av->budget.i2c_adap); if (fe) { fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params; @@ -1142,7 +1142,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBC_KNC1: budget_av->reinitialise_demod = 1; - fe = tda10021_attach(&philips_cu1216_config, + fe = dvb_attach(tda10021_attach, &philips_cu1216_config, &budget_av->budget.i2c_adap, read_pwm(budget_av)); if (fe) { @@ -1153,7 +1153,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBC_KNC1_PLUS: case SUBID_DVBC_CINERGY1200: budget_av->reinitialise_demod = 1; - fe = tda10021_attach(&philips_cu1216_config, + fe = dvb_attach(tda10021_attach, &philips_cu1216_config, &budget_av->budget.i2c_adap, read_pwm(budget_av)); if (fe) { @@ -1168,7 +1168,7 @@ static void frontend_init(struct budget_av *budget_av) case SUBID_DVBT_KNC1_PLUS: case SUBID_DVBT_CINERGY1200: budget_av->reinitialise_demod = 1; - fe = tda10046_attach(&philips_tu1216_config, + fe = dvb_attach(tda10046_attach, &philips_tu1216_config, &budget_av->budget.i2c_adap); if (fe) { fe->ops.tuner_ops.init = philips_tu1216_tuner_init; @@ -1192,8 +1192,7 @@ static void frontend_init(struct budget_av *budget_av) if (dvb_register_frontend(&budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) { printk(KERN_ERR "budget-av: Frontend registration failed!\n"); - if (budget_av->budget.dvb_frontend->ops.release) - budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend); + dvb_frontend_detach(budget_av->budget.dvb_frontend); budget_av->budget.dvb_frontend = NULL; } } @@ -1227,8 +1226,10 @@ static int budget_av_detach(struct saa7146_dev *dev) if (budget_av->budget.ci_present) ciintf_deinit(budget_av); - if (budget_av->budget.dvb_frontend != NULL) + if (budget_av->budget.dvb_frontend != NULL) { dvb_unregister_frontend(budget_av->budget.dvb_frontend); + dvb_frontend_detach(budget_av->budget.dvb_frontend); + } err = ttpci_budget_deinit(&budget_av->budget); kfree(budget_av); @@ -1303,6 +1304,9 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_av->budget.dvb_adapter.priv = budget_av; frontend_init(budget_av); ciintf_init(budget_av); + + ttpci_budget_init_hooks(&budget_av->budget); + return 0; } diff --git a/linux/drivers/media/dvb/ttpci/budget-ci.c b/linux/drivers/media/dvb/ttpci/budget-ci.c index 4b966eea3..e440fa100 100644 --- a/linux/drivers/media/dvb/ttpci/budget-ci.c +++ b/linux/drivers/media/dvb/ttpci/budget-ci.c @@ -749,17 +749,17 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb // setup PLL filter and TDA9889 switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: - tda1004x_write_byte(fe, 0x0C, 0x14); + tda1004x_writereg(fe, 0x0C, 0x14); filter = 0; break; case BANDWIDTH_7_MHZ: - tda1004x_write_byte(fe, 0x0C, 0x80); + tda1004x_writereg(fe, 0x0C, 0x80); filter = 0; break; case BANDWIDTH_8_MHZ: - tda1004x_write_byte(fe, 0x0C, 0x14); + tda1004x_writereg(fe, 0x0C, 0x14); filter = 1; break; @@ -988,7 +988,7 @@ static void frontend_init(struct budget_ci *budget_ci) switch (budget_ci->budget.dev->pci->subsystem_device) { case 0x100c: // Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059)) budget_ci->budget.dvb_frontend = - stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap); + dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap; @@ -998,7 +998,7 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x100f: // Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059)) budget_ci->budget.dvb_frontend = - stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap); + dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params; break; @@ -1008,7 +1008,7 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x1010: // TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt)) budget_ci->tuner_pll_address = 0x61; budget_ci->budget.dvb_frontend = - stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params; break; @@ -1018,7 +1018,7 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x1011: // Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889) budget_ci->tuner_pll_address = 0x63; budget_ci->budget.dvb_frontend = - tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init; budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; @@ -1029,7 +1029,7 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt)) budget_ci->tuner_pll_address = 0x60; budget_ci->budget.dvb_frontend = - tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap); + dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init; budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; @@ -1038,13 +1038,13 @@ static void frontend_init(struct budget_ci *budget_ci) break; case 0x1017: // TT S-1500 PCI - budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap); + budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params; budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap; budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL; - if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) { + if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) { printk("%s: No LNBP21 found!\n", __FUNCTION__); if (budget_ci->budget.dvb_frontend->ops.release) budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend); @@ -1065,8 +1065,7 @@ static void frontend_init(struct budget_ci *budget_ci) if (dvb_register_frontend (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) { printk("budget-ci: Frontend registration failed!\n"); - if (budget_ci->budget.dvb_frontend->ops.release) - budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend); + dvb_frontend_detach(budget_ci->budget.dvb_frontend); budget_ci->budget.dvb_frontend = NULL; } } @@ -1101,6 +1100,8 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_ci->budget.dvb_adapter.priv = budget_ci; frontend_init(budget_ci); + ttpci_budget_init_hooks(&budget_ci->budget); + return 0; } @@ -1112,8 +1113,10 @@ static int budget_ci_detach(struct saa7146_dev *dev) if (budget_ci->budget.ci_present) ciintf_deinit(budget_ci); - if (budget_ci->budget.dvb_frontend) + if (budget_ci->budget.dvb_frontend) { dvb_unregister_frontend(budget_ci->budget.dvb_frontend); + dvb_frontend_detach(budget_ci->budget.dvb_frontend); + } err = ttpci_budget_deinit(&budget_ci->budget); tasklet_kill(&budget_ci->msp430_irq_tasklet); diff --git a/linux/drivers/media/dvb/ttpci/budget-core.c b/linux/drivers/media/dvb/ttpci/budget-core.c index e4cf7775e..e15562f81 100644 --- a/linux/drivers/media/dvb/ttpci/budget-core.c +++ b/linux/drivers/media/dvb/ttpci/budget-core.c @@ -63,9 +63,6 @@ static int stop_ts_capture(struct budget *budget) { dprintk(2, "budget: %p\n", budget); - if (--budget->feeding) - return budget->feeding; - saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off SAA7146_IER_DISABLE(budget->dev, MASK_10); return 0; @@ -77,8 +74,8 @@ static int start_ts_capture(struct budget *budget) dprintk(2, "budget: %p\n", budget); - if (budget->feeding) - return ++budget->feeding; + if (!budget->feeding || !budget->fe_synced) + return 0; saa7146_write(dev, MC1, MASK_20); // DMA3 off @@ -139,7 +136,33 @@ static int start_ts_capture(struct budget *budget) SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ saa7146_write(dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ - return ++budget->feeding; + return 0; +} + +static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct budget *budget = (struct budget *) fe->dvb->priv; + int synced; + int ret; + + if (budget->read_fe_status) + ret = budget->read_fe_status(fe, status); + else + ret = -EINVAL; + + if (!ret) { + synced = (*status & FE_HAS_LOCK); + if (synced != budget->fe_synced) { + budget->fe_synced = synced; + spin_lock(&budget->feedlock); + if (synced) + start_ts_capture(budget); + else + stop_ts_capture(budget); + spin_unlock(&budget->feedlock); + } + } + return ret; } static void vpeirq(unsigned long data) @@ -267,7 +290,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget *) demux->priv; - int status; + int status = 0; dprintk(2, "budget: %p\n", budget); @@ -276,7 +299,8 @@ static int budget_start_feed(struct dvb_demux_feed *feed) spin_lock(&budget->feedlock); feed->pusi_seen = 0; /* have a clean section start */ - status = start_ts_capture(budget); + if (budget->feeding++ == 0) + status = start_ts_capture(budget); spin_unlock(&budget->feedlock); return status; } @@ -285,12 +309,13 @@ static int budget_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget *) demux->priv; - int status; + int status = 0; dprintk(2, "budget: %p\n", budget); spin_lock(&budget->feedlock); - status = stop_ts_capture(budget); + if (--budget->feeding == 0) + status = stop_ts_capture(budget); spin_unlock(&budget->feedlock); return status; } @@ -470,6 +495,14 @@ err: return ret; } +void ttpci_budget_init_hooks(struct budget *budget) +{ + if (budget->dvb_frontend && !budget->read_fe_status) { + budget->read_fe_status = budget->dvb_frontend->ops.read_status; + budget->dvb_frontend->ops.read_status = budget_read_fe_status; + } +} + int ttpci_budget_deinit(struct budget *budget) { struct saa7146_dev *dev = budget->dev; @@ -508,11 +541,8 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) spin_lock(&budget->feedlock); budget->video_port = video_port; if (budget->feeding) { - int oldfeeding = budget->feeding; - budget->feeding = 1; stop_ts_capture(budget); start_ts_capture(budget); - budget->feeding = oldfeeding; } spin_unlock(&budget->feedlock); } @@ -520,6 +550,7 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) EXPORT_SYMBOL_GPL(ttpci_budget_debiread); EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite); EXPORT_SYMBOL_GPL(ttpci_budget_init); +EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks); EXPORT_SYMBOL_GPL(ttpci_budget_deinit); EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port); diff --git a/linux/drivers/media/dvb/ttpci/budget-patch.c b/linux/drivers/media/dvb/ttpci/budget-patch.c index a3f827faa..175bdab83 100644 --- a/linux/drivers/media/dvb/ttpci/budget-patch.c +++ b/linux/drivers/media/dvb/ttpci/budget-patch.c @@ -325,7 +325,7 @@ static void frontend_init(struct budget_patch* budget) case 0x1013: // SATELCO Multimedia PCI // try the ALPS BSRV2 first of all - budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; @@ -335,7 +335,7 @@ static void frontend_init(struct budget_patch* budget) } // try the ALPS BSRU6 now - budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; budget->dvb_frontend->tuner_priv = &budget->i2c_adap; @@ -347,7 +347,7 @@ static void frontend_init(struct budget_patch* budget) } // Try the grundig 29504-451 - budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; @@ -367,8 +367,7 @@ static void frontend_init(struct budget_patch* budget) } else { if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) { printk("budget-av: Frontend registration failed!\n"); - if (budget->dvb_frontend->ops.release) - budget->dvb_frontend->ops.release(budget->dvb_frontend); + dvb_frontend_detach(budget->dvb_frontend); budget->dvb_frontend = NULL; } } @@ -617,6 +616,8 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte budget->dvb_adapter.priv = budget; frontend_init(budget); + ttpci_budget_init_hooks(budget); + return 0; } @@ -625,8 +626,10 @@ static int budget_patch_detach (struct saa7146_dev* dev) struct budget_patch *budget = (struct budget_patch*) dev->ext_priv; int err; - if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend); - + if (budget->dvb_frontend) { + dvb_unregister_frontend(budget->dvb_frontend); + dvb_frontend_detach(budget->dvb_frontend); + } err = ttpci_budget_deinit (budget); kfree (budget); diff --git a/linux/drivers/media/dvb/ttpci/budget.c b/linux/drivers/media/dvb/ttpci/budget.c index 1b4d884a9..e846b9620 100644 --- a/linux/drivers/media/dvb/ttpci/budget.c +++ b/linux/drivers/media/dvb/ttpci/budget.c @@ -361,7 +361,7 @@ static void frontend_init(struct budget *budget) case 0x1003: // Hauppauge/TT Nova budget (stv0299/ALPS BSRU6(tsa5059) OR ves1893/ALPS BSRV2(sp5659)) case 0x1013: // try the ALPS BSRV2 first of all - budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(ves1x93_attach, &alps_bsrv2_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params; budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; @@ -371,7 +371,7 @@ static void frontend_init(struct budget *budget) } // try the ALPS BSRU6 now - budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; budget->dvb_frontend->tuner_priv = &budget->i2c_adap; @@ -381,7 +381,7 @@ static void frontend_init(struct budget *budget) case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) - budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); + budget->dvb_frontend = dvb_attach(ves1820_attach, &alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget)); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; break; @@ -390,7 +390,7 @@ static void frontend_init(struct budget *budget) case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060)) - budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(l64781_attach, &grundig_29504_401_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params; break; @@ -398,7 +398,7 @@ static void frontend_init(struct budget *budget) break; case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059)) - budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(stv0299_attach, &alps_bsru6_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; budget->dvb_frontend->tuner_priv = &budget->i2c_adap; @@ -408,7 +408,7 @@ static void frontend_init(struct budget *budget) break; case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522)) - budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(tda8083_attach, &grundig_29504_451_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params; budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage; @@ -417,10 +417,10 @@ static void frontend_init(struct budget *budget) break; case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260)) - budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap); + budget->dvb_frontend = dvb_attach(s5h1420_attach, &s5h1420_config, &budget->i2c_adap); if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params; - if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) { + if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0) == NULL) { printk("%s: No LNBP21 found!\n", __FUNCTION__); goto error_out; } @@ -442,8 +442,7 @@ static void frontend_init(struct budget *budget) error_out: printk("budget: Frontend registration failed!\n"); - if (budget->dvb_frontend->ops.release) - budget->dvb_frontend->ops.release(budget->dvb_frontend); + dvb_frontend_detach(budget->dvb_frontend); budget->dvb_frontend = NULL; return; } @@ -471,6 +470,8 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ budget->dvb_adapter.priv = budget; frontend_init(budget); + ttpci_budget_init_hooks(budget); + return 0; } @@ -479,7 +480,10 @@ static int budget_detach (struct saa7146_dev* dev) struct budget *budget = (struct budget*) dev->ext_priv; int err; - if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend); + if (budget->dvb_frontend) { + dvb_unregister_frontend(budget->dvb_frontend); + dvb_frontend_detach(budget->dvb_frontend); + } err = ttpci_budget_deinit (budget); diff --git a/linux/drivers/media/dvb/ttpci/budget.h b/linux/drivers/media/dvb/ttpci/budget.h index c5c226d4f..8a20d59b7 100644 --- a/linux/drivers/media/dvb/ttpci/budget.h +++ b/linux/drivers/media/dvb/ttpci/budget.h @@ -60,13 +60,6 @@ struct budget { struct dmx_frontend hw_frontend; struct dmx_frontend mem_frontend; - int fe_synced; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15) - struct mutex pid_mutex; -#else - struct semaphore pid_mutex; -#endif - int ci_present; int video_port; @@ -86,6 +79,9 @@ struct budget { struct dvb_adapter dvb_adapter; struct dvb_frontend *dvb_frontend; + int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status); + int fe_synced; + void *priv; }; @@ -118,6 +114,7 @@ static struct saa7146_pci_extension_data x_var = { \ extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, struct saa7146_pci_extension_data *info, struct module *owner); +extern void ttpci_budget_init_hooks(struct budget *budget); extern int ttpci_budget_deinit(struct budget *budget); extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr); extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port); diff --git a/linux/drivers/media/dvb/ttusb-budget/Kconfig b/linux/drivers/media/dvb/ttusb-budget/Kconfig index 92c7cdcf8..ce0fb8f54 100644 --- a/linux/drivers/media/dvb/ttusb-budget/Kconfig +++ b/linux/drivers/media/dvb/ttusb-budget/Kconfig @@ -1,13 +1,13 @@ config DVB_TTUSB_BUDGET tristate "Technotrend/Hauppauge Nova-USB devices" depends on DVB_CORE && USB - select DVB_CX22700 - select DVB_TDA1004X - select DVB_VES1820 - select DVB_TDA8083 - select DVB_STV0299 - select DVB_STV0297 - select DVB_LNBP21 + select DVB_CX22700 if !DVB_FE_CUSTOMISE + select DVB_TDA1004X if !DVB_FE_CUSTOMISE + select DVB_VES1820 if !DVB_FE_CUSTOMISE + select DVB_TDA8083 if !DVB_FE_CUSTOMISE + select DVB_STV0299 if !DVB_FE_CUSTOMISE + select DVB_STV0297 if !DVB_FE_CUSTOMISE + select DVB_LNBP21 if !DVB_FE_CUSTOMISE help Support for external USB adapters designed by Technotrend and produced by Hauppauge, shipped under the brand name 'Nova-USB'. diff --git a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index d9eb8ce61..af3391314 100644 --- a/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/linux/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -46,7 +46,7 @@ is a bit braindead (no matching channel masks or no matching filter mask), we won't support this - yet. it doesn't event support negative filters, so the best way is maybe to keep TTUSB_HWSECTIONS undef'd and just - parse TS data. USB bandwith will be a problem when having large + parse TS data. USB bandwidth will be a problem when having large datastreams, especially for dvb-net, but hey, that's not my problem. TTUSB_DISEQC, TTUSB_TONE: @@ -134,10 +134,6 @@ struct ttusb { int revision; -#if 0 /* keep */ - devfs_handle_t stc_devfs_handle; -#endif - struct dvb_frontend* fe; }; @@ -1119,17 +1115,17 @@ static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb // setup PLL filter switch (params->u.ofdm.bandwidth) { case BANDWIDTH_6_MHZ: - tda1004x_write_byte(fe, 0x0C, 0); + tda1004x_writereg(fe, 0x0C, 0); filter = 0; break; case BANDWIDTH_7_MHZ: - tda1004x_write_byte(fe, 0x0C, 0); + tda1004x_writereg(fe, 0x0C, 0); filter = 0; break; case BANDWIDTH_8_MHZ: - tda1004x_write_byte(fe, 0x0C, 0xFF); + tda1004x_writereg(fe, 0x0C, 0xFF); filter = 1; break; @@ -1576,13 +1572,13 @@ static void frontend_init(struct ttusb* ttusb) switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) { case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6|BSBE1(tsa5059)) // try the stv0299 based first - ttusb->fe = stv0299_attach(&alps_stv0299_config, &ttusb->i2c_adap); + ttusb->fe = dvb_attach(stv0299_attach, &alps_stv0299_config, &ttusb->i2c_adap); if (ttusb->fe != NULL) { ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params; if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1 alps_stv0299_config.inittab = alps_bsbe1_inittab; - lnbp21_attach(ttusb->fe, &ttusb->i2c_adap, 0, 0); + dvb_attach(lnbp21_attach, ttusb->fe, &ttusb->i2c_adap, 0, 0); } else { // ALPS BSRU6 ttusb->fe->ops.set_voltage = ttusb_set_voltage; } @@ -1590,7 +1586,7 @@ static void frontend_init(struct ttusb* ttusb) } // Grundig 29504-491 - ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap); + ttusb->fe = dvb_attach(tda8083_attach, &ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap); if (ttusb->fe != NULL) { ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params; ttusb->fe->ops.set_voltage = ttusb_set_voltage; @@ -1599,13 +1595,13 @@ static void frontend_init(struct ttusb* ttusb) break; case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659)) - ttusb->fe = ves1820_attach(&alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb)); + ttusb->fe = dvb_attach(ves1820_attach, &alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb)); if (ttusb->fe != NULL) { ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params; break; } - ttusb->fe = stv0297_attach(&dvbc_philips_tdm1316l_config, &ttusb->i2c_adap); + ttusb->fe = dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &ttusb->i2c_adap); if (ttusb->fe != NULL) { ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params; break; @@ -1614,14 +1610,14 @@ static void frontend_init(struct ttusb* ttusb) case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??)) // try the ALPS TDMB7 first - ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap); + ttusb->fe = dvb_attach(cx22700_attach, &alps_tdmb7_config, &ttusb->i2c_adap); if (ttusb->fe != NULL) { ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params; break; } // Philips td1316 - ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap); + ttusb->fe = dvb_attach(tda10046_attach, &philips_tdm1316l_config, &ttusb->i2c_adap); if (ttusb->fe != NULL) { ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init; ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params; @@ -1637,8 +1633,7 @@ static void frontend_init(struct ttusb* ttusb) } else { if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) { printk("dvb-ttusb-budget: Frontend registration failed!\n"); - if (ttusb->fe->ops.release) - ttusb->fe->ops.release(ttusb->fe); + dvb_frontend_detach(ttusb->fe); ttusb->fe = NULL; } } @@ -1754,13 +1749,6 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i return -ENODEV; } -#if 0 /* keep */ - ttusb->stc_devfs_handle = - devfs_register(ttusb->adapter->devfs_handle, TTUSB_BUDGET_NAME, - DEVFS_FL_DEFAULT, 0, 192, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP - | S_IROTH | S_IWOTH, &stc_fops, ttusb); -#endif usb_set_intfdata(intf, (void *) ttusb); frontend_init(ttusb); @@ -1782,7 +1770,10 @@ static void ttusb_disconnect(struct usb_interface *intf) dvb_net_release(&ttusb->dvbnet); dvb_dmxdev_release(&ttusb->dmxdev); dvb_dmx_release(&ttusb->dvb_demux); - if (ttusb->fe != NULL) dvb_unregister_frontend(ttusb->fe); + if (ttusb->fe != NULL) { + dvb_unregister_frontend(ttusb->fe); + dvb_frontend_detach(ttusb->fe); + } i2c_del_adapter(&ttusb->i2c_adap); dvb_unregister_adapter(&ttusb->adapter); diff --git a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c index 60c9767af..ac91d7350 100644 --- a/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/linux/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1523,7 +1523,11 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend); dvb_dmxdev_release(&dec->dmxdev); dvb_dmx_release(&dec->demux); - if (dec->fe) dvb_unregister_frontend(dec->fe); + if (dec->fe) { + dvb_unregister_frontend(dec->fe); + if (dec->fe->ops.release) + dec->fe->ops.release(dec->fe); + } dvb_unregister_adapter(&dec->adapter); } |