V4L/DVB (4386): Convert DVB devices to use dvb_attach()

Only devices using > 1 frontend were ported; ones which did not are left
using static binding.

Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Acked-by: Michael Krufky <mkrufky@linuxtv.org>
Acked-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index fa0bed6..d195cf5 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -1383,8 +1383,12 @@
 	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);
@@ -2077,7 +2081,7 @@
 	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;
@@ -2092,7 +2096,7 @@
 		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;
@@ -2103,7 +2107,7 @@
 			}
 
 			// 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;
@@ -2116,7 +2120,7 @@
 			}
 
 			// 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;
@@ -2130,7 +2134,7 @@
 			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;
@@ -2138,7 +2142,7 @@
 				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;
@@ -2150,7 +2154,7 @@
 		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;
 			}
@@ -2158,7 +2162,7 @@
 
 		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;
 			}
@@ -2166,7 +2170,7 @@
 
 		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;
@@ -2178,7 +2182,7 @@
 
 		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;
@@ -2190,7 +2194,7 @@
 
 		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;
 			}
@@ -2198,7 +2202,7 @@
 
 		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;
 
@@ -2214,12 +2218,12 @@
 
 		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);
@@ -2255,8 +2259,9 @@
 		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;
 		}
 	}
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 2d21fec..c648c01 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -235,7 +235,7 @@
 
 	/* 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 @@
 
 	/* 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 @@
 
 	/* 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 @@
 
 	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 @@
 	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 @@
 	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 @@
 
 	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 @@
 		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 @@
 
 	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 @@
 	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 @@
 	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,9 @@
 	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;
 	}
 }
@@ -1227,8 +1228,12 @@
 	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);
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 8710813..20b5e8d 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -988,7 +988,7 @@
 	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 @@
 
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		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);
@@ -1065,8 +1065,9 @@
 		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;
 		}
 	}
@@ -1114,8 +1115,12 @@
 
 	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);
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 5722744..82dbef8 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -325,7 +325,7 @@
 	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 @@
 		}
 
 		// 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 @@
 		}
 
 		// 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,9 @@
 	} 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;
 		}
 	}
@@ -627,8 +628,12 @@
 	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);
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index c21ee5a..19beb11 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -361,7 +361,7 @@
 	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 @@
 		}
 
 		// 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 @@
 
 	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 @@
 
 	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 @@
 		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 @@
 		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,7 +417,7 @@
 		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) {
@@ -442,8 +442,9 @@
 
 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;
 }
@@ -481,7 +482,12 @@
 	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);