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;
                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_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) */
-       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) {
                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;
        } 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_detach(fc->fe->ops.release_sec, fc->fe);
+                       dvb_detach(fc->fe->ops.tuner_ops.release, fc->fe);
+                       dvb_detach(fc->fe->ops.release, fc->fe);
                        fc->fe = NULL;
                        return -EINVAL;
                }
 
 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_detach(fc->fe->ops.release_sec, fc->fe);
+               dvb_detach(fc->fe->ops.tuner_ops.release, fc->fe);
+               dvb_detach(fc->fe->ops.release, fc->fe);
+       }
 
        fc->init_state &= ~FC_STATE_FE_INIT;
 }
 
 static void dst_release(struct dvb_frontend *fe)
 {
        struct dst_state *state = fe->demodulator_priv;
+
+       if (state->dst_hw_cap & DST_TYPE_HAS_CA)
+               symbol_put(dst_ca_attach);
+
        kfree(state);
 }
 
 
        .fops = &dst_ca_fops
 };
 
-int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
+ssize_t 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;
+       return 1; // must return non-zero for dvb_attach() to work
 }
 
 EXPORT_SYMBOL(dst_ca_attach);
 
 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);
+ssize_t 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);
 
 
 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;
 
 
 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) {
 
        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");
 
                /* 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");
 
                /* 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;
                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;
                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;
                }
                /*      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);
+                       dvb_attach(dst_ca_attach, state, &card->dvb_adapter);
                break;
 
        case BTTV_BOARD_PINNACLESAT:
-               card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
+               card->fe = dvb_attach(cx24110_attach, &pctvsat_config, card->i2c_adapter);
                if (card->fe) {
                        card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
                        card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
                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;
        }
 
        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_detach(card->fe->ops.release_sec, card->fe);
+                       dvb_detach(card->fe->ops.tuner_ops.release, card->fe);
+                       dvb_detach(card->fe->ops.release, card->fe);
                        card->fe = NULL;
                }
 }
        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_detach(card->fe->ops.release_sec, card->fe);
+               dvb_detach(card->fe->ops.tuner_ops.release, card->fe);
+               dvb_detach(card->fe->ops.release, card->fe);
+       }
        dvb_unregister_adapter(&card->dvb_adapter);
 
        kfree(card);
 
 
        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;
 
        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;
 
        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;
 
        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;
 
 
 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;
        }
 
 
                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_detach(d->fe->ops.release_sec, d->fe);
+                       dvb_detach(d->fe->ops.tuner_ops.release, d->fe);
+                       dvb_detach(d->fe->ops.release, d->fe);
                        d->fe = NULL;
                        return -ENODEV;
                }
 
 int dvb_usb_fe_exit(struct dvb_usb_device *d)
 {
-       if (d->fe != NULL)
+       if (d->fe != NULL) {
                dvb_unregister_frontend(d->fe);
+               dvb_detach(d->fe->ops.release_sec, d->fe);
+               dvb_detach(d->fe->ops.tuner_ops.release, d->fe);
+               dvb_detach(d->fe->ops.release, d->fe);
+       }
        return 0;
 }
 
        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;
 }
 
        .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 = I2C_M_RD, .buf = b1, .len = 1 };
 
                ret = i2c_transfer (i2c, &msg, 1);
                if (ret != 1)
-                       return -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;
        fe->ops.tuner_ops.info.frequency_min = desc->max;
 
        fe->tuner_priv = priv;
-       return 0;
+       return fe;
 }
 EXPORT_SYMBOL(dvb_pll_attach);
 
 
  * @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
 
        dvb_dmxdev_release(&av7110->dmxdev);
        dvb_dmx_release(&av7110->demux);
 
-       if (av7110->fe != NULL)
+       if (av7110->fe != NULL) {
                dvb_unregister_frontend(av7110->fe);
+               dvb_detach(av7110->fe->ops.release_sec, av7110->fe);
+               dvb_detach(av7110->fe->ops.tuner_ops.release, av7110->fe);
+               dvb_detach(av7110->fe->ops.release, av7110->fe);
+       }
        dvb_unregister_device(av7110->osd_dev);
        av7110_av_unregister(av7110);
        av7110_ca_unregister(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;
                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;
                        }
 
                        // 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;
                        }
 
                        // 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;
                        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;
                                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;
                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;
                        }
 
                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;
                        }
 
                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;
 
                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;
 
                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;
                        }
 
                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;
 
 
                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) == NULL) {
+                               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);
                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_detach(av7110->fe->ops.release_sec, av7110->fe);
+                       dvb_detach(av7110->fe->ops.tuner_ops.release, av7110->fe);
+                       dvb_detach(av7110->fe->ops.release, av7110->fe);
                        av7110->fe = NULL;
                }
        }
 
 
        /* 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;
        }
 
 
        /* 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;
 
        /* 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;
        }
 
 
        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;
        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;
        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;
 
        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;
                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;
 
        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) {
        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) {
        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;
        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_detach(budget_av->budget.dvb_frontend->ops.release_sec, budget_av->budget.dvb_frontend);
+               dvb_detach(budget_av->budget.dvb_frontend->ops.tuner_ops.release, budget_av->budget.dvb_frontend);
+               dvb_detach(budget_av->budget.dvb_frontend->ops.release, budget_av->budget.dvb_frontend);
                budget_av->budget.dvb_frontend = NULL;
        }
 }
        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_detach(budget_av->budget.dvb_frontend->ops.release_sec, budget_av->budget.dvb_frontend);
+               dvb_detach(budget_av->budget.dvb_frontend->ops.tuner_ops.release, budget_av->budget.dvb_frontend);
+               dvb_detach(budget_av->budget.dvb_frontend->ops.release, budget_av->budget.dvb_frontend);
+       }
        err = ttpci_budget_deinit(&budget_av->budget);
 
        kfree(budget_av);
 
        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;
 
        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;
        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;
        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;
        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;
                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) == NULL) {
+                       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);
                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_detach(budget_ci->budget.dvb_frontend->ops.release_sec, budget_ci->budget.dvb_frontend);
+                       dvb_detach(budget_ci->budget.dvb_frontend->ops.tuner_ops.release, budget_ci->budget.dvb_frontend);
+                       dvb_detach(budget_ci->budget.dvb_frontend->ops.release, budget_ci->budget.dvb_frontend);
                        budget_ci->budget.dvb_frontend = NULL;
                }
        }
 
        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_detach(budget_ci->budget.dvb_frontend->ops.release_sec, budget_ci->budget.dvb_frontend);
+               dvb_detach(budget_ci->budget.dvb_frontend->ops.tuner_ops.release, budget_ci->budget.dvb_frontend);
+               dvb_detach(budget_ci->budget.dvb_frontend->ops.release, budget_ci->budget.dvb_frontend);
+       }
        err = ttpci_budget_deinit(&budget_ci->budget);
 
        tasklet_kill(&budget_ci->msp430_irq_tasklet);
 
        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;
                }
 
                // 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;
                }
 
                // 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;
        } 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_detach(budget->dvb_frontend->ops.release_sec, budget->dvb_frontend);
+                       dvb_detach(budget->dvb_frontend->ops.tuner_ops.release, budget->dvb_frontend);
+                       dvb_detach(budget->dvb_frontend->ops.release, budget->dvb_frontend);
                        budget->dvb_frontend = NULL;
                }
        }
        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_detach(budget->dvb_frontend->ops.release_sec, budget->dvb_frontend);
+               dvb_detach(budget->dvb_frontend->ops.tuner_ops.release, budget->dvb_frontend);
+               dvb_detach(budget->dvb_frontend->ops.release, budget->dvb_frontend);
+       }
        err = ttpci_budget_deinit (budget);
 
        kfree (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;
                }
 
                // 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;
 
        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;
 
        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;
                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;
                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;
                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) == NULL) {
 
 error_out:
        printk("budget: Frontend registration failed!\n");
-       if (budget->dvb_frontend->ops.release)
-               budget->dvb_frontend->ops.release(budget->dvb_frontend);
+       dvb_detach(budget->dvb_frontend->ops.release_sec, budget->dvb_frontend);
+       dvb_detach(budget->dvb_frontend->ops.tuner_ops.release, budget->dvb_frontend);
+       dvb_detach(budget->dvb_frontend->ops.release, budget->dvb_frontend);
        budget->dvb_frontend = NULL;
        return;
 }
        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_detach(budget->dvb_frontend->ops.release_sec, budget->dvb_frontend);
+               dvb_detach(budget->dvb_frontend->ops.tuner_ops.release, budget->dvb_frontend);
+               dvb_detach(budget->dvb_frontend->ops.release, budget->dvb_frontend);
+       }
 
        err = ttpci_budget_deinit (budget);
 
 
        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;
                        }
                }
 
                // 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;
                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;
 
        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;
        } 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_detach(ttusb->fe->ops.release_sec, ttusb->fe);
+                       dvb_detach(ttusb->fe->ops.tuner_ops.release, ttusb->fe);
+                       dvb_detach(ttusb->fe->ops.release, ttusb->fe);
                        ttusb->fe = NULL;
                }
        }
        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_detach(ttusb->fe->ops.release_sec, ttusb->fe);
+               dvb_detach(ttusb->fe->ops.tuner_ops.release, ttusb->fe);
+               dvb_detach(ttusb->fe->ops.release, ttusb->fe);
+       }
        i2c_del_adapter(&ttusb->i2c_adap);
        dvb_unregister_adapter(&ttusb->adapter);
 
 
        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);
 }
 
 
        switch (dev->core->board) {
 #ifdef HAVE_CX22702
        case CX88_BOARD_HAUPPAUGE_DVB_T1:
-               dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
+               dev->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_novat_config,
                                                   &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_thomson_dtt759x);
                }
        case CX88_BOARD_CONEXANT_DVB_T1:
        case CX88_BOARD_KWORLD_DVB_T_CX22702:
        case CX88_BOARD_WINFAST_DTV1000:
-               dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
+               dev->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config,
                                                   &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x60,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_thomson_dtt7579);
                }
        case CX88_BOARD_WINFAST_DTV2000H:
        case CX88_BOARD_HAUPPAUGE_HVR1100:
        case CX88_BOARD_HAUPPAUGE_HVR1100LP:
-               dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config,
+               dev->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr1100_config,
                                                   &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_fmd1216me);
                }
 #if defined(HAVE_MT352) || defined(HAVE_ZL10353)
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
 #ifdef HAVE_MT352
-               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
+               dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv,
                                                 &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x60,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_thomson_dtt7579);
                        break;
 #endif
 #ifdef HAVE_ZL10353
                /* ZL10353 replaces MT352 on later cards */
-               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
+               dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1,
                                                   &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x60,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_thomson_dtt7579);
                }
 #ifdef HAVE_MT352
                /* The tin box says DEE1601, but it seems to be DTT7579
                 * compatible, with a slightly different MT352 AGC gain. */
-               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
+               dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_dual,
                                                 &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_thomson_dtt7579);
                        break;
 #endif
 #ifdef HAVE_ZL10353
                /* ZL10353 replaces MT352 on later cards */
-               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
+               dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1,
                                                   &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_thomson_dtt7579);
                }
 #endif /* HAVE_MT352 || HAVE_ZL10353 */
 #ifdef HAVE_MT352
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
-               dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
+               dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv,
                                                 &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_lg_z201);
                }
        case CX88_BOARD_KWORLD_DVB_T:
        case CX88_BOARD_DNTV_LIVE_DVB_T:
        case CX88_BOARD_ADSTECH_DVB_T_PCI:
-               dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
+               dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_config,
                                                 &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_unknown_1);
                }
 #ifdef HAVE_VP3054_I2C
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_fmd1216me;
-               dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
+               dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config,
                        &((struct vp3054_i2c_state *)dev->card_priv)->adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params;
        case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_thomson_fe6600;
-               dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid,
+               dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid,
                                                   &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params;
 #endif
 #ifdef HAVE_OR51132
        case CX88_BOARD_PCHDTV_HD3000:
-               dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
+               dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
                                                 &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_thomson_dtt761x);
                }
                fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_microtune_4042;
-               dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
+               dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold,
                                                    &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
                mdelay(200);
                dev->core->pll_addr = 0x61;
                dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
-               dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
+               dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold,
                                                    &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
                mdelay(100);
                cx_set(MO_GP0_IO, 1);
                mdelay(200);
-               dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
+               dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold,
                                                    &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
                mdelay(100);
                cx_set(MO_GP0_IO, 1);
                mdelay(200);
-               dev->dvb.frontend = lgdt330x_attach(&pchdtv_hd5500,
+               dev->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500,
                                                    &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
 #endif
 #ifdef HAVE_NXT200X
        case CX88_BOARD_ATI_HDTVWONDER:
-               dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder,
+               dev->dvb.frontend = dvb_attach(nxt200x_attach, &ati_hdtvwonder,
                                                 &dev->core->i2c_adap);
                if (dev->dvb.frontend != NULL) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61,
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
                                       &dev->core->i2c_adap,
                                       &dvb_pll_tuv1236d);
                }
 #ifdef HAVE_CX24123
        case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
        case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
-               dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
+               dev->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config,
                        &dev->core->i2c_adap);
                if (dev->dvb.frontend) {
-                       isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap,
+                       dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->core->i2c_adap,
                                       0x08, 0x00, 0x00);
                }
                break;
        case CX88_BOARD_KWORLD_DVBS_100:
-               dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
+               dev->dvb.frontend = dvb_attach(cx24123_attach, &kworld_dvbs_100_config,
                        &dev->core->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
                }
                break;
        case CX88_BOARD_GENIATECH_DVBS:
-               dev->dvb.frontend = cx24123_attach(&geniatech_dvbs_config,
+               dev->dvb.frontend = dvb_attach(cx24123_attach, &geniatech_dvbs_config,
                                                   &dev->core->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
 
 #ifdef HAVE_MT352
        case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL:
                printk("%s: pinnacle 300i dvb setup\n",dev->name);
-               dev->dvb.frontend = mt352_attach(&pinnacle_300i,
+               dev->dvb.frontend = dvb_attach(mt352_attach, &pinnacle_300i,
                                                 &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
 
        case SAA7134_BOARD_AVERMEDIA_777:
                printk("%s: avertv 777 dvb setup\n",dev->name);
-               dev->dvb.frontend = mt352_attach(&avermedia_777,
+               dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
                                                 &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs;
 #endif
 #ifdef HAVE_TDA1004X
        case SAA7134_BOARD_MD7134:
-               dev->dvb.frontend = tda10046_attach(&medion_cardbus,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &medion_cardbus,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init;
                }
                break;
        case SAA7134_BOARD_PHILIPS_TOUGH:
-               dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &philips_tu1216_60_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_60_init;
                }
                break;
        case SAA7134_BOARD_FLYDVBTDUO:
-               dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &tda827x_lifeview_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
                }
                break;
        case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
-               dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &tda827x_lifeview_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
                }
                break;
        case SAA7134_BOARD_PHILIPS_EUROPA:
-               dev->dvb.frontend = tda10046_attach(&philips_europa_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &philips_europa_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
                }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_300:
-               dev->dvb.frontend = tda10046_attach(&philips_europa_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &philips_europa_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
                }
                break;
        case SAA7134_BOARD_VIDEOMATE_DVBT_200:
-               dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &philips_tu1216_61_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_61_init;
                }
                break;
        case SAA7134_BOARD_PHILIPS_TIGER:
-               dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &philips_tiger_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
                }
                break;
        case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
-               dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &philips_tiger_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
                }
                break;
        case SAA7134_BOARD_FLYDVBT_LR301:
-               dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &tda827x_lifeview_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
                }
                break;
        case SAA7134_BOARD_FLYDVB_TRIO:
-               dev->dvb.frontend = tda10046_attach(&lifeview_trio_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &lifeview_trio_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
                }
                break;
        case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
-               dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &ads_tech_duo_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
                }
                break;
        case SAA7134_BOARD_TEVION_DVBT_220RF:
-               dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &tevion_dvbt220rf_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.sleep = tevion_dvb220rf_tuner_sleep;
                }
                break;
        case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
-               dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
+               dev->dvb.frontend = dvb_attach(tda10046_attach, &ads_tech_duo_config,
                                                    &dev->i2c_adap);
                if (dev->dvb.frontend) {
                        dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
 #endif
 #ifdef HAVE_NXT200X
        case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
-               dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tdhu2);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tdhu2);
                }
                break;
        case SAA7134_BOARD_KWORLD_ATSC110:
-               dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap);
+               dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, &dev->i2c_adap);
                if (dev->dvb.frontend) {
-                       dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tuv1236d);
+                       dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tuv1236d);
                }
                break;
 #endif
 
 fail_dmx:
        dvb_unregister_frontend(dvb->frontend);
 fail_frontend:
+       dvb_detach(dvb->frontend->ops.release_sec, dvb->frontend);
+       dvb_detach(dvb->frontend->ops.tuner_ops.release, dvb->frontend);
+       dvb_detach(dvb->frontend->ops.release, dvb->frontend);
        dvb_unregister_adapter(&dvb->adapter);
 fail_adapter:
        return result;
        dvb_dmxdev_release(&dvb->dmxdev);
        dvb_dmx_release(&dvb->demux);
        dvb_unregister_frontend(dvb->frontend);
+       dvb_detach(dvb->frontend->ops.release_sec, dvb->frontend);
+       dvb_detach(dvb->frontend->ops.tuner_ops.release, dvb->frontend);
+       dvb_detach(dvb->frontend->ops.release, dvb->frontend);
        dvb_unregister_adapter(&dvb->adapter);
 }