Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus

* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus:
  [MIPS] Fix wreckage after removal of tickadj; convert to GENERIC_TIME.
  [MIPS] DECstation defconfig update
  [MIPS] Fix size of zones_size and zholes_size array
  [MIPS] BCM1480: Mask pending interrupts against c0_status.im.
  [MIPS] SB1250: Interrupt handler fixes
  [MIPS] Remove IT8172-based platforms, ITE 8172G and Globespan IVR support.
  [MIPS] Remove Atlas and SEAD from feature-removal-schedule.
  [MIPS] Remove Jaguar and Ocelot family from feature list.
  [MIPS] BCM1250: TRDY timeout tweaks for Broadcom SiByte systems
  [MIPS] Remove dead DECstation boot code
  [MIPS] Let gcc align 'struct pt_regs' on 8 bytes boundary
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
index 669a09a..126e59d9 100644
--- a/Documentation/video4linux/CARDLIST.cx88
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -16,7 +16,7 @@
  15 -> DViCO FusionHDTV DVB-T1                             [18ac:db00]
  16 -> KWorld LTV883RF
  17 -> DViCO FusionHDTV 3 Gold-Q                           [18ac:d810,18ac:d800]
- 18 -> Hauppauge Nova-T DVB-T                              [0070:9002,0070:9001]
+ 18 -> Hauppauge Nova-T DVB-T                              [0070:9002,0070:9001,0070:9000]
  19 -> Conexant DVB-T reference design                     [14f1:0187]
  20 -> Provideo PV259                                      [1540:2580]
  21 -> DViCO FusionHDTV DVB-T Plus                         [18ac:db10,18ac:db11]
@@ -41,7 +41,7 @@
  40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid                [0070:9400,0070:9402]
  41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
  42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025,1822:0019]
- 43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1]
+ 43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1,12ab:2300]
  44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
  45 -> KWorld HardwareMpegTV XPert                         [17de:0840]
  46 -> DViCO FusionHDTV DVB-T Hybrid                       [18ac:db40,18ac:db44]
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index 94cf695..6fb82ac 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -97,3 +97,4 @@
  96 -> Medion Md8800 Quadro                     [16be:0007,16be:0008]
  97 -> LifeView FlyDVB-S /Acorp TV134DS         [5168:0300,4e42:0300]
  98 -> Proteus Pro 2309                         [0919:2003]
+ 99 -> AVerMedia TV Hybrid A16AR                [1461:2c00]
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 3dd5dbaf..53304e6 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -1014,6 +1014,13 @@
 	if ((ret = dvb_generic_open (inode, file)) < 0)
 		return ret;
 
+	if (fe->ops.ts_bus_ctrl) {
+		if ((ret = fe->ops.ts_bus_ctrl (fe, 1)) < 0) {
+			dvb_generic_release (inode, file);
+			return ret;
+		}
+	}
+
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
 
 		/* normal tune mode when opened R/W */
@@ -1043,6 +1050,9 @@
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY)
 		fepriv->release_jiffies = jiffies;
 
+	if (fe->ops.ts_bus_ctrl)
+		fe->ops.ts_bus_ctrl (fe, 0);
+
 	return dvb_generic_release (inode, file);
 }
 
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index e5d5028..f233d78 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -129,6 +129,7 @@
 	int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
 	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
+	int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
 
 	struct dvb_tuner_ops tuner_ops;
 };
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index 0a3c353..67cefdd 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -39,20 +39,8 @@
 	  Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
 	  DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
 
-	  Devices supported by this driver:
-	    Artec T1 USB1.1 boxes
-	    Avermedia AverTV DVBT USB1.1
-	    Compro Videomate DVB-U2000 - DVB-T USB
-	    DiBcom USB1.1 reference devices (non-public)
-	    Grandtec DVB-T USB
-	    Hama DVB-T USB1.1-Box
-	    KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
-	    TwinhanDTV Magic Box (VP7041e)
-	    TwinhanDTV USB-Ter (VP7041)
-	    Ultima Electronic/Artec T1 USB TVBOX
-
-	  The VP7041 seems to be identical to "CTS Portable" (Chinese
-	  Television System).
+	  For an up-to-date list of devices supported by this driver, have a look
+	  on the Linux-DVB Wiki at www.linuxtv.org.
 
 	  Say Y if you own such a device and want to use it. You should build it as
 	  a module.
@@ -69,12 +57,29 @@
 	select DVB_DIB3000MC
 	select DVB_TUNER_MT2060
 	help
-	  Support for 2.0 DVB-T receivers based on reference designs made by
+	  Support for USB2.0 DVB-T receivers based on reference designs made by
 	  DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
 
-	  Devices supported by this driver:
-	    Artec T1 USB2.0 boxes
-	    DiBcom USB2.0 reference devices (non-public)
+	  For an up-to-date list of devices supported by this driver, have a look
+	  on the Linux-DVB Wiki at www.linuxtv.org.
+
+	  Say Y if you own such a device and want to use it. You should build it as
+	  a module.
+
+config DVB_USB_DIB0700
+	tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
+	depends on DVB_USB
+	select DVB_DIB7000M
+	select DVB_DIB3000MC
+	select DVB_TUNER_MT2060
+	help
+	  Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
+	  USB bridge is also present in devices having the DiB7700 DVB-T-USB
+	  silicon. This chip can be found in devices offered by Hauppauge,
+	  Avermedia and other big and small companies.
+
+	  For an up-to-date list of devices supported by this driver, have a look
+	  on the Linux-DVB Wiki at www.linuxtv.org.
 
 	  Say Y if you own such a device and want to use it. You should build it as
 	  a module.
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 9643f56..e239107 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -1,4 +1,4 @@
-dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o
+dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o usb-urb.o
 obj-$(CONFIG_DVB_USB) += dvb-usb.o
 
 dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
@@ -36,4 +36,7 @@
 dvb-usb-cxusb-objs = cxusb.o
 obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
 
+dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o
+obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
+
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
index df0c384..2ed3eb6 100644
--- a/drivers/media/dvb/dvb-usb/a800.c
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -27,7 +27,8 @@
 }
 
 /* assure to put cold to 0 for iManufacturer == 1 */
-static int a800_identify_state(struct usb_device *udev, struct dvb_usb_properties *props,struct dvb_usb_device_description **desc, int *cold)
+static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
+	struct dvb_usb_device_description **desc, int *cold)
 {
 	*cold = udev->descriptor.iManufacturer != 1;
 	return 0;
@@ -88,7 +89,7 @@
 }
 
 /* USB Driver stuff */
-static struct dvb_usb_properties a800_properties;
+static struct dvb_usb_device_properties a800_properties;
 
 static int a800_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -104,22 +105,41 @@
 };
 MODULE_DEVICE_TABLE (usb, a800_table);
 
-static struct dvb_usb_properties a800_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
-	.pid_filter_count = 32,
+static struct dvb_usb_device_properties a800_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
-
 	.firmware = "dvb-usb-avertv-a800-02.fw",
 
-	.size_of_priv     = sizeof(struct dibusb_state),
-
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.pid_filter_count = 32,
 	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
 	.pid_filter       = dibusb_pid_filter,
 	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-	.power_ctrl       = a800_power_ctrl,
+
 	.frontend_attach  = dibusb_dib3000mc_frontend_attach,
 	.tuner_attach     = dibusb_dib3000mc_tuner_attach,
+
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+			.size_of_priv     = sizeof(struct dibusb_state),
+		},
+	},
+
+	.power_ctrl       = a800_power_ctrl,
 	.identify_state   = a800_identify_state,
 
 	.rc_interval      = DEFAULT_RC_INTERVAL,
@@ -130,18 +150,6 @@
 	.i2c_algo         = &dibusb_i2c_algo,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
-		.endpoint = 0x06,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
-
 	.num_device_descs = 1,
 	.devices = {
 		{   "AVerMedia AverTV DVB-T USB 2.0 (A800)",
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index c710c01..43f3906 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -161,13 +161,13 @@
 		return 0;
 }
 
-static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+static int cxusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
 	u8 buf[2] = { 0x03, 0x00 };
 	if (onoff)
-		cxusb_ctrl_msg(d,CMD_STREAMING_ON, buf, 2, NULL, 0);
+		cxusb_ctrl_msg(adap->dev, CMD_STREAMING_ON, buf, 2, NULL, 0);
 	else
-		cxusb_ctrl_msg(d,CMD_STREAMING_OFF, NULL, 0, NULL, 0);
+		cxusb_ctrl_msg(adap->dev, CMD_STREAMING_OFF, NULL, 0, NULL, 0);
 
 	return 0;
 }
@@ -327,8 +327,8 @@
 static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
 					  struct dvb_frontend_parameters *fep)
 {
-	struct dvb_usb_device *d = fe->dvb->priv;
-	return lg_h06xf_pll_set(fe, &d->i2c_adap, fep);
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	return lg_h06xf_pll_set(fe, &adap->dev->i2c_adap, fep);
 }
 
 static struct cx22702_config cxusb_cx22702_config = {
@@ -359,98 +359,99 @@
 };
 
 /* Callbacks for DVB USB */
-static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_device *d)
+static int cxusb_fmd1216me_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	u8 bpll[4] = { 0x0b, 0xdc, 0x9c, 0xa0 };
-	d->pll_addr = 0x61;
-	memcpy(d->pll_init, bpll, 4);
-	d->pll_desc = &dvb_pll_fmd1216me;
+	adap->pll_addr = 0x61;
+	memcpy(adap->pll_init, bpll, 4);
+	adap->pll_desc = &dvb_pll_fmd1216me;
 
-	d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
-	d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+	adap->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+	adap->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
 
 	return 0;
 }
 
-static int cxusb_dee1601_tuner_attach(struct dvb_usb_device *d)
+static int cxusb_dee1601_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	d->pll_addr = 0x61;
-	d->pll_desc = &dvb_pll_thomson_dtt7579;
-	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+	adap->pll_addr = 0x61;
+	adap->pll_desc = &dvb_pll_thomson_dtt7579;
+	adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 }
 
-static int cxusb_lgz201_tuner_attach(struct dvb_usb_device *d)
+static int cxusb_lgz201_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	d->pll_addr = 0x61;
-	d->pll_desc = &dvb_pll_lg_z201;
-	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+	adap->pll_addr = 0x61;
+	adap->pll_desc = &dvb_pll_lg_z201;
+	adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 }
 
-static int cxusb_dtt7579_tuner_attach(struct dvb_usb_device *d)
+static int cxusb_dtt7579_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	d->pll_addr = 0x60;
-	d->pll_desc = &dvb_pll_thomson_dtt7579;
-	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+	adap->pll_addr = 0x60;
+	adap->pll_desc = &dvb_pll_thomson_dtt7579;
+	adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 }
 
-static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_device *d)
+static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	d->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
+	adap->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
 	return 0;
 }
 
-static int cxusb_cx22702_frontend_attach(struct dvb_usb_device *d)
+static int cxusb_cx22702_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	u8 b;
-	if (usb_set_interface(d->udev,0,6) < 0)
+	if (usb_set_interface(adap->dev->udev, 0, 6) < 0)
 		err("set interface failed");
 
-	cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, &b, 1);
+	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, &b, 1);
 
-	if ((d->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &d->i2c_adap)) != NULL)
+	if ((adap->fe = dvb_attach(cx22702_attach, &cxusb_cx22702_config, &adap->dev->i2c_adap)) != NULL)
 		return 0;
 
 	return -EIO;
 }
 
-static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_device *d)
+static int cxusb_lgdt3303_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	if (usb_set_interface(d->udev,0,7) < 0)
+	if (usb_set_interface(adap->dev->udev, 0, 7) < 0)
 		err("set interface failed");
 
-	cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	if ((d->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &d->i2c_adap)) != NULL)
+	if ((adap->fe = dvb_attach(lgdt330x_attach, &cxusb_lgdt3303_config, &adap->dev->i2c_adap)) != NULL)
 		return 0;
 
 	return -EIO;
 }
 
-static int cxusb_mt352_frontend_attach(struct dvb_usb_device *d)
-{	/* used in both lgz201 and th7579 */
-	if (usb_set_interface(d->udev,0,0) < 0)
-		err("set interface failed");
-
-	cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
-
-	if ((d->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &d->i2c_adap)) != NULL)
-		return 0;
-
-	return -EIO;
-}
-
-static int cxusb_dee1601_frontend_attach(struct dvb_usb_device *d)
+static int cxusb_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	if (usb_set_interface(d->udev,0,0) < 0)
+	/* used in both lgz201 and th7579 */
+	if (usb_set_interface(adap->dev->udev, 0, 0) < 0)
 		err("set interface failed");
 
-	cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
+	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	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))
+	if ((adap->fe = dvb_attach(mt352_attach, &cxusb_mt352_config, &adap->dev->i2c_adap)) != NULL)
+		return 0;
+
+	return -EIO;
+}
+
+static int cxusb_dee1601_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	if (usb_set_interface(adap->dev->udev, 0, 0) < 0)
+		err("set interface failed");
+
+	cxusb_ctrl_msg(adap->dev, CMD_DIGITAL, NULL, 0, NULL, 0);
+
+	if (((adap->fe = dvb_attach(mt352_attach, &cxusb_dee1601_config, &adap->dev->i2c_adap)) != NULL) ||
+		((adap->fe = dvb_attach(zl10353_attach, &cxusb_zl10353_dee1601_config, &adap->dev->i2c_adap)) != NULL))
 		return 0;
 
 	return -EIO;
@@ -480,11 +481,11 @@
 }
 
 /* DVB USB Driver stuff */
-static struct dvb_usb_properties cxusb_medion_properties;
-static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties;
-static struct dvb_usb_properties cxusb_bluebird_dee1601_properties;
-static struct dvb_usb_properties cxusb_bluebird_lgz201_properties;
-static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties;
+static struct dvb_usb_device_properties cxusb_medion_properties;
+static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties;
+static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties;
+static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties;
+static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties;
 
 static int cxusb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -504,36 +505,36 @@
 		{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
 		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
 		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_WARM) },
-		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_COLD) },
-		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DEE1601_WARM) },
+		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD) },
+		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM) },
 		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_COLD) },
 		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LGZ201_WARM) },
 		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_COLD) },
 		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_TH7579_WARM) },
-		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_COLD) },
-		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_WARM) },
+		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD) },
+		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM) },
+		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD) },
+		{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM) },
 		{}		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE (usb, cxusb_table);
 
-static struct dvb_usb_properties cxusb_medion_properties = {
+static struct dvb_usb_device_properties cxusb_medion_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
 
 	.size_of_priv     = sizeof(struct cxusb_state),
 
+	.num_adapters = 1,
+	.adapter = {
+		{
 	.streaming_ctrl   = cxusb_streaming_ctrl,
-	.power_ctrl       = cxusb_power_ctrl,
 	.frontend_attach  = cxusb_cx22702_frontend_attach,
 	.tuner_attach     = cxusb_fmd1216me_tuner_attach,
-
-	.i2c_algo         = &cxusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
+			.stream = {
+				.type = USB_BULK,
 		.count = 5,
 		.endpoint = 0x02,
 		.u = {
@@ -543,6 +544,14 @@
 		}
 	},
 
+		},
+	},
+	.power_ctrl       = cxusb_power_ctrl,
+
+	.i2c_algo         = &cxusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+
 	.num_device_descs = 1,
 	.devices = {
 		{   "Medion MD95700 (MDUSBTV-HYBRID)",
@@ -552,7 +561,7 @@
 	}
 };
 
-static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = {
+static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl          = DEVICE_SPECIFIC,
@@ -563,11 +572,29 @@
 
 	.size_of_priv     = sizeof(struct cxusb_state),
 
+	.num_adapters = 1,
+	.adapter = {
+		{
 	.streaming_ctrl   = cxusb_streaming_ctrl,
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
 	.frontend_attach  = cxusb_lgdt3303_frontend_attach,
 	.tuner_attach     = cxusb_lgdt3303_tuner_attach,
 
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 5,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 8192,
+			}
+		}
+	},
+		},
+	},
+
+	.power_ctrl       = cxusb_bluebird_power_ctrl,
+
 	.i2c_algo         = &cxusb_i2c_algo,
 
 	.rc_interval      = 100,
@@ -576,17 +603,6 @@
 	.rc_query         = cxusb_rc_query,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 5,
-		.endpoint = 0x02,
-		.u = {
-			.bulk = {
-				.buffersize = 8192,
-			}
-		}
-	},
 
 	.num_device_descs = 1,
 	.devices = {
@@ -597,7 +613,7 @@
 	}
 };
 
-static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = {
+static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl          = DEVICE_SPECIFIC,
@@ -608,10 +624,27 @@
 
 	.size_of_priv     = sizeof(struct cxusb_state),
 
+	.num_adapters = 1,
+	.adapter = {
+		{
 	.streaming_ctrl   = cxusb_streaming_ctrl,
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
 	.frontend_attach  = cxusb_dee1601_frontend_attach,
 	.tuner_attach     = cxusb_dee1601_tuner_attach,
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 5,
+		.endpoint = 0x04,
+		.u = {
+			.bulk = {
+				.buffersize = 8192,
+			}
+		}
+	},
+		},
+	},
+
+	.power_ctrl       = cxusb_bluebird_power_ctrl,
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
@@ -621,19 +654,8 @@
 	.rc_query         = cxusb_rc_query,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 5,
-		.endpoint = 0x04,
-		.u = {
-			.bulk = {
-				.buffersize = 8192,
-			}
-		}
-	},
 
-	.num_device_descs = 2,
+	.num_device_descs = 3,
 	.devices = {
 		{   "DViCO FusionHDTV DVB-T Dual USB",
 			{ &cxusb_table[3], NULL },
@@ -643,10 +665,14 @@
 			{ &cxusb_table[9],  NULL },
 			{ &cxusb_table[10], NULL },
 		},
+		{   "DViCO FusionHDTV DVB-T Dual Digital 2",
+			{ &cxusb_table[11], NULL },
+			{ &cxusb_table[12], NULL },
+		},
 	}
 };
 
-static struct dvb_usb_properties cxusb_bluebird_lgz201_properties = {
+static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl          = DEVICE_SPECIFIC,
@@ -657,11 +683,28 @@
 
 	.size_of_priv     = sizeof(struct cxusb_state),
 
+	.num_adapters = 2,
+	.adapter = {
+		{
 	.streaming_ctrl   = cxusb_streaming_ctrl,
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
 	.frontend_attach  = cxusb_mt352_frontend_attach,
 	.tuner_attach     = cxusb_lgz201_tuner_attach,
 
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 5,
+		.endpoint = 0x04,
+		.u = {
+			.bulk = {
+				.buffersize = 8192,
+			}
+		}
+	},
+		},
+	},
+	.power_ctrl       = cxusb_bluebird_power_ctrl,
+
 	.i2c_algo         = &cxusb_i2c_algo,
 
 	.rc_interval      = 100,
@@ -670,18 +713,6 @@
 	.rc_query         = cxusb_rc_query,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 5,
-		.endpoint = 0x04,
-		.u = {
-			.bulk = {
-				.buffersize = 8192,
-			}
-		}
-	},
-
 	.num_device_descs = 1,
 	.devices = {
 		{   "DViCO FusionHDTV DVB-T USB (LGZ201)",
@@ -691,7 +722,7 @@
 	}
 };
 
-static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties = {
+static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl          = DEVICE_SPECIFIC,
@@ -702,11 +733,28 @@
 
 	.size_of_priv     = sizeof(struct cxusb_state),
 
+	.num_adapters = 1,
+	.adapter = {
+		{
 	.streaming_ctrl   = cxusb_streaming_ctrl,
-	.power_ctrl       = cxusb_bluebird_power_ctrl,
 	.frontend_attach  = cxusb_mt352_frontend_attach,
 	.tuner_attach     = cxusb_dtt7579_tuner_attach,
 
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 5,
+		.endpoint = 0x04,
+		.u = {
+			.bulk = {
+				.buffersize = 8192,
+			}
+		}
+	},
+		},
+	},
+	.power_ctrl       = cxusb_bluebird_power_ctrl,
+
 	.i2c_algo         = &cxusb_i2c_algo,
 
 	.rc_interval      = 100,
@@ -715,17 +763,6 @@
 	.rc_query         = cxusb_rc_query,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 5,
-		.endpoint = 0x04,
-		.u = {
-			.bulk = {
-				.buffersize = 8192,
-			}
-		}
-	},
 
 	.num_device_descs = 1,
 	.devices = {
diff --git a/drivers/media/dvb/dvb-usb/dib0700.h b/drivers/media/dvb/dvb-usb/dib0700.h
new file mode 100644
index 0000000..ac84347
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dib0700.h
@@ -0,0 +1,49 @@
+/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ *  Copyright (C) 2005-6 DiBcom, SA
+ */
+#ifndef _DIB0700_H_
+#define _DIB0700_H_
+
+#define DVB_USB_LOG_PREFIX "dib0700"
+#include "dvb-usb.h"
+
+#include "dib07x0.h"
+
+extern int dvb_usb_dib0700_debug;
+#define deb_info(args...)   dprintk(dvb_usb_dib0700_debug,0x01,args)
+#define deb_fw(args...)     dprintk(dvb_usb_dib0700_debug,0x02,args)
+#define deb_fwdata(args...) dprintk(dvb_usb_dib0700_debug,0x04,args)
+#define deb_data(args...)   dprintk(dvb_usb_dib0700_debug,0x08,args)
+
+#define REQUEST_I2C_READ     0x2
+#define REQUEST_I2C_WRITE    0x3
+#define REQUEST_POLL_RC      0x4
+#define REQUEST_JUMPRAM      0x8
+#define REQUEST_SET_GPIO     0xC
+#define REQUEST_ENABLE_VIDEO 0xF
+	// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
+	// 2 Byte: MPEG2 mode:  4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
+	// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines)    4LSB(     "                "           )
+
+struct dib0700_state {
+	u8 channel_state;
+	u16 mt2060_if1[2];
+};
+
+extern int dib0700_set_gpio(struct dvb_usb_device *, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val);
+extern int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw);
+extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
+extern struct i2c_algorithm dib0700_i2c_algo;
+extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
+			struct dvb_usb_device_description **desc, int *cold);
+
+extern int dib0700_device_count;
+extern struct dvb_usb_device_properties dib0700_devices[];
+extern struct usb_device_id dib0700_usb_id_table[];
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dib0700_core.c b/drivers/media/dvb/dvb-usb/dib0700_core.c
new file mode 100644
index 0000000..dca6c69
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dib0700_core.c
@@ -0,0 +1,279 @@
+/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ *  Copyright (C) 2005-6 DiBcom, SA
+ */
+#include "dib0700.h"
+
+/* debug */
+int dvb_usb_dib0700_debug;
+module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
+
+/* expecting rx buffer: request data[0] data[1] ... data[2] */
+static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
+{
+	int status;
+
+	deb_data(">>> ");
+	debug_dump(tx,txlen,deb_data);
+
+	status = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0),
+		tx[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, tx, txlen,
+		USB_CTRL_GET_TIMEOUT);
+
+	if (status != txlen)
+		deb_data("ep 0 write error (status = %d, len: %d)\n",status,txlen);
+
+	return status < 0 ? status : 0;
+}
+
+/* expecting tx buffer: request data[0] ... data[n] (n <= 4) */
+static int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
+{
+	u16 index, value;
+	int status;
+
+	if (txlen < 2) {
+		err("tx buffer length is smaller than 2. Makes no sense.");
+		return -EINVAL;
+	}
+	if (txlen > 4) {
+		err("tx buffer length is larger than 4. Not supported.");
+		return -EINVAL;
+	}
+
+	deb_data(">>> ");
+	debug_dump(tx,txlen,deb_data);
+
+	value = ((txlen - 2) << 8) | tx[1];
+	index = 0;
+	if (txlen > 2)
+		index |= (tx[2] << 8);
+	if (txlen > 3)
+		index |= tx[3];
+
+	/* think about swapping here */
+	value = le16_to_cpu(value);
+	index = le16_to_cpu(index);
+
+	status = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev,0), tx[0],
+			USB_TYPE_VENDOR | USB_DIR_IN, value, index, rx, rxlen,
+			USB_CTRL_GET_TIMEOUT);
+
+	if (status < 0)
+		deb_info("ep 0 read error (status = %d)\n",status);
+
+	deb_data("<<< ");
+	debug_dump(rx,rxlen,deb_data);
+
+	return status; /* length in case of success */
+}
+
+int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
+{
+	u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
+	return dib0700_ctrl_wr(d,buf,3);
+}
+
+/*
+ * I2C master xfer function
+ */
+static int dib0700_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i,len;
+	u8 buf[255];
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	for (i = 0; i < num; i++) {
+		/* fill in the address */
+		buf[1] = (msg[i].addr << 1);
+		/* fill the buffer */
+		memcpy(&buf[2], msg[i].buf, msg[i].len);
+
+		/* write/read request */
+		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			buf[0] = REQUEST_I2C_READ;
+			buf[1] |= 1;
+
+			/* special thing in the current firmware: when length is zero the read-failed */
+			if ((len = dib0700_ctrl_rd(d, buf, msg[i].len + 2, msg[i+1].buf, msg[i+1].len)) <= 0) {
+				deb_info("I2C read failed on address %x\n", msg[i].addr);
+				break;
+			}
+
+			msg[i+1].len = len;
+
+			i++;
+		} else {
+			buf[0] = REQUEST_I2C_WRITE;
+			if (dib0700_ctrl_wr(d, buf, msg[i].len + 2) < 0)
+				break;
+		}
+	}
+
+	mutex_unlock(&d->i2c_mutex);
+	return i;
+}
+
+static u32 dib0700_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+struct i2c_algorithm dib0700_i2c_algo = {
+	.master_xfer   = dib0700_i2c_xfer,
+	.functionality = dib0700_i2c_func,
+};
+
+int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
+			struct dvb_usb_device_description **desc, int *cold)
+{
+	u8 buf[3] = { REQUEST_SET_GPIO, 4, (GPIO_IN << 7) | (0 << 6) }; // GPIO4 is save - used for I2C
+	*cold = usb_control_msg(udev, usb_sndctrlpipe(udev,0),
+		buf[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, buf, 3, USB_CTRL_GET_TIMEOUT) != 3;
+
+	deb_info("cold: %d\n", *cold);
+	return 0;
+}
+
+static int dib0700_jumpram(struct usb_device *udev, u32 address)
+{
+	int ret, actlen;
+	u8 buf[8] = { REQUEST_JUMPRAM, 0, 0, 0,
+		(address >> 24) & 0xff,
+		(address >> 16) & 0xff,
+		(address >> 8)  & 0xff,
+		 address        & 0xff };
+
+	if ((ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x01),buf,8,&actlen,1000)) < 0) {
+		deb_fw("jumpram to 0x%x failed\n",address);
+		return ret;
+	}
+	if (actlen != 8) {
+		deb_fw("jumpram to 0x%x failed\n",address);
+		return -EIO;
+	}
+	return 0;
+}
+
+int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw)
+{
+	struct hexline hx;
+	int pos = 0, ret, act_len;
+
+	u8 buf[260];
+
+	while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
+		deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",hx.addr, hx.len, hx.chk);
+
+		buf[0] = hx.len;
+		buf[1] = (hx.addr >> 8) & 0xff;
+		buf[2] =  hx.addr       & 0xff;
+		buf[3] = hx.type;
+		memcpy(&buf[4],hx.data,hx.len);
+		buf[4+hx.len] = hx.chk;
+
+		ret = usb_bulk_msg(udev,
+			usb_sndbulkpipe(udev, 0x01),
+			buf,
+			hx.len + 5,
+			&act_len,
+			1000);
+
+		if (ret < 0) {
+			err("firmware download failed at %d with %d",pos,ret);
+			return ret;
+		}
+	}
+
+	if (ret == 0) {
+		/* start the firmware */
+		if ((ret = dib0700_jumpram(udev, 0x70000000)) == 0) {
+			info("firmware started successfully.");
+			msleep(100);
+		}
+	} else
+		ret = -EIO;
+
+	return ret;
+}
+
+int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	struct dib0700_state *st = adap->dev->priv;
+	u8 b[4];
+
+	b[0] = REQUEST_ENABLE_VIDEO;
+	b[1] = 0x00;
+	b[2] = (0x01 << 4); /* Master mode */
+	b[3] = 0x00;
+
+	deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
+
+	if (onoff)
+		st->channel_state |=   1 << adap->id;
+	else
+		st->channel_state &= ~(1 << adap->id);
+
+	b[2] |= st->channel_state;
+
+	if (st->channel_state) /* if at least one channel is active */
+		b[1] = (0x01 << 4) | 0x00;
+
+	deb_info("data for streaming: %x %x\n",b[1],b[2]);
+
+	return dib0700_ctrl_wr(adap->dev, b, 4);
+}
+
+static int dib0700_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	int i;
+
+	for (i = 0; i < dib0700_device_count; i++)
+		if (dvb_usb_device_init(intf, &dib0700_devices[i], THIS_MODULE, NULL) == 0)
+			return 0;
+
+	return -ENODEV;
+}
+
+static struct usb_driver dib0700_driver = {
+	.name       = "dvb_usb_dib0700",
+	.probe      = dib0700_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table   = dib0700_usb_id_table,
+};
+
+/* module stuff */
+static int __init dib0700_module_init(void)
+{
+	int result;
+	info("loaded with support for %d different device-types", dib0700_device_count);
+	if ((result = usb_register(&dib0700_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit dib0700_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&dib0700_driver);
+}
+
+module_init (dib0700_module_init);
+module_exit (dib0700_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for devices based on DiBcom DiB0700 - USB bridge");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c
new file mode 100644
index 0000000..e473bfe
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c
@@ -0,0 +1,212 @@
+/* Linux driver for devices based on the DiBcom DiB0700 USB bridge
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ *  Copyright (C) 2005-6 DiBcom, SA
+ */
+#include "dib0700.h"
+
+#include "dib3000mc.h"
+#include "mt2060.h"
+
+static int force_lna_activation;
+module_param(force_lna_activation, int, 0644);
+MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplifyer(s) (LNA), "
+		"if applicable for the device (default: 0=automatic/off).");
+
+/* Hauppauge Nova-T 500
+ *  has a LNA on GPIO0 which is enabled by setting 1 */
+static struct mt2060_config bristol_mt2060_config[2] = {
+	{
+		.i2c_address = 0x60,
+		.clock_out   = 3,
+	}, {
+		.i2c_address = 0x61,
+	}
+};
+
+static struct dibx000_agc_config bristol_dib3000p_mt2060_agc_config = {
+	.band_caps = BAND_VHF | BAND_UHF,
+	.setup     = (1 << 8) | (5 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (2 << 0),
+
+	.agc1_max = 42598,
+	.agc1_min = 17694,
+	.agc2_max = 45875,
+	.agc2_min = 0,
+
+	.agc1_pt1 = 0,
+	.agc1_pt2 = 59,
+
+	.agc1_slope1 = 0,
+	.agc1_slope2 = 69,
+
+	.agc2_pt1 = 0,
+	.agc2_pt2 = 59,
+
+	.agc2_slope1 = 111,
+	.agc2_slope2 = 28,
+};
+
+static struct dib3000mc_config bristol_dib3000mc_config[2] = {
+	{	.agc          = &bristol_dib3000p_mt2060_agc_config,
+		.max_time     = 0x196,
+		.ln_adc_level = 0x1cc7,
+		.output_mpeg2_in_188_bytes = 1,
+	},
+	{	.agc          = &bristol_dib3000p_mt2060_agc_config,
+		.max_time     = 0x196,
+		.ln_adc_level = 0x1cc7,
+		.output_mpeg2_in_188_bytes = 1,
+	}
+};
+
+static int bristol_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_state *st = adap->dev->priv;
+	if (adap->id == 0) {
+		dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 0); msleep(10);
+		dib0700_set_gpio(adap->dev, GPIO6,  GPIO_OUT, 1); msleep(10);
+		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
+		dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
+
+		if (force_lna_activation)
+			dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+		else
+			dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 0);
+
+		if (dib3000mc_i2c_enumeration(&adap->dev->i2c_adap, 2, DEFAULT_DIB3000P_I2C_ADDRESS, bristol_dib3000mc_config) != 0) {
+			dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
+			return -ENODEV;
+		}
+	}
+	st->mt2060_if1[adap->id] = 1220;
+	return (adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap,
+		(10 + adap->id) << 1, &bristol_dib3000mc_config[adap->id])) == NULL ? -ENODEV : 0;
+}
+
+static int bristol_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_state *st = adap->dev->priv;
+	struct i2c_adapter *tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
+	return dvb_attach(mt2060_attach,adap->fe, tun_i2c, &bristol_mt2060_config[adap->id],
+		st->mt2060_if1[adap->id]) == NULL ? -ENODEV : 0;
+}
+
+/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
+/*
+static struct mt2060_config stk7000p_mt2060_config = {
+	0x60
+};
+*/
+
+static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	/* unless there is no real power management in DVB - we leave the device on GPIO6 */
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0); msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1); msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1); msleep(10);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0); msleep(10);
+
+//	adap->fe = dib7000m_attach(&adap->dev->i2c_adap, &stk7700p_dib7000m_config, 18);
+	return 0;
+}
+
+static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
+{
+//	tun_i2c = dib7000m_get_tuner_i2c_master(adap->fe, 1);
+//	return mt2060_attach(adap->fe, tun_i2c, &stk3000p_mt2060_config, if1);
+	return 0;
+}
+
+struct usb_device_id dib0700_usb_id_table[] = {
+		{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK7700P) },
+		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500) },
+		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_500_2) },
+		{ USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_HAUPPAUGE_NOVA_T_STICK) },
+		{ USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR) },
+		{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
+
+#define DIB0700_DEFAULT_DEVICE_PROPERTIES \
+	.caps              = DVB_USB_IS_AN_I2C_ADAPTER, \
+	.usb_ctrl          = DEVICE_SPECIFIC, \
+	.firmware          = "dvb-usb-dib0700-01.fw", \
+	.download_firmware = dib0700_download_firmware, \
+	.no_reconnect      = 1, \
+	.size_of_priv      = sizeof(struct dib0700_state), \
+	.i2c_algo          = &dib0700_i2c_algo, \
+	.identify_state    = dib0700_identify_state
+
+#define DIB0700_DEFAULT_STREAMING_CONFIG(ep) \
+	.streaming_ctrl   = dib0700_streaming_ctrl, \
+	.stream = { \
+		.type = USB_BULK, \
+		.count = 4, \
+		.endpoint = ep, \
+		.u = { \
+			.bulk = { \
+				.buffersize = 39480, \
+			} \
+		} \
+	}
+
+struct dvb_usb_device_properties dib0700_devices[] = {
+	{
+		DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+		.num_adapters = 1,
+		.adapter = {
+			{
+				.frontend_attach  = stk7700p_frontend_attach,
+				.tuner_attach     = stk7700p_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			},
+		},
+
+		.num_device_descs = 3,
+		.devices = {
+			{   "DiBcom STK7700P reference design",
+				{ &dib0700_usb_id_table[0], NULL },
+				{ NULL },
+			},
+			{   "Hauppauge Nova-T Stick",
+				{ &dib0700_usb_id_table[3], NULL },
+				{ NULL },
+			},
+			{   "AVerMedia AVerTV DVB-T Volar",
+				{ &dib0700_usb_id_table[4], NULL },
+				{ NULL },
+			},
+		}
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+
+		.num_adapters = 2,
+		.adapter = {
+			{
+				.frontend_attach  = bristol_frontend_attach,
+				.tuner_attach     = bristol_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+			}, {
+				.frontend_attach  = bristol_frontend_attach,
+				.tuner_attach     = bristol_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+			}
+		},
+
+		.num_device_descs = 1,
+		.devices = {
+			{   "Hauppauge Nova-T 500 Dual DVB-T",
+				{ &dib0700_usb_id_table[1], &dib0700_usb_id_table[2], NULL },
+				{ NULL },
+			},
+		}
+	}
+};
+
+int dib0700_device_count = ARRAY_SIZE(dib0700_devices);
diff --git a/drivers/media/dvb/dvb-usb/dib07x0.h b/drivers/media/dvb/dvb-usb/dib07x0.h
new file mode 100644
index 0000000..7e62c10
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dib07x0.h
@@ -0,0 +1,21 @@
+#ifndef _DIB07X0_H_
+#define _DIB07X0_H_
+
+enum dib07x0_gpios {
+	GPIO0  =  0,
+	GPIO1  =  2,
+	GPIO2  =  3,
+	GPIO3  =  4,
+	GPIO4  =  5,
+	GPIO5  =  6,
+	GPIO6  =  8,
+	GPIO7  = 10,
+	GPIO8  = 11,
+	GPIO9  = 14,
+	GPIO10 = 15,
+};
+
+#define GPIO_IN  0
+#define GPIO_OUT 1
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 124e25a..fd3a990 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -18,12 +18,12 @@
 #define deb_info(args...) dprintk(debug,0x01,args)
 
 /* common stuff used by the different dibusb modules */
-int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+int dibusb_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-	if (d->priv != NULL) {
-		struct dibusb_state *st = d->priv;
+	if (adap->priv != NULL) {
+		struct dibusb_state *st = adap->priv;
 		if (st->ops.fifo_ctrl != NULL)
-			if (st->ops.fifo_ctrl(d->fe,onoff)) {
+			if (st->ops.fifo_ctrl(adap->fe,onoff)) {
 				err("error while controlling the fifo of the demod.");
 				return -ENODEV;
 			}
@@ -32,23 +32,23 @@
 }
 EXPORT_SYMBOL(dibusb_streaming_ctrl);
 
-int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+int dibusb_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
 {
-	if (d->priv != NULL) {
-		struct dibusb_state *st = d->priv;
+	if (adap->priv != NULL) {
+		struct dibusb_state *st = adap->priv;
 		if (st->ops.pid_ctrl != NULL)
-			st->ops.pid_ctrl(d->fe,index,pid,onoff);
+			st->ops.pid_ctrl(adap->fe,index,pid,onoff);
 	}
 	return 0;
 }
 EXPORT_SYMBOL(dibusb_pid_filter);
 
-int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff)
+int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-	if (d->priv != NULL) {
-		struct dibusb_state *st = d->priv;
+	if (adap->priv != NULL) {
+		struct dibusb_state *st = adap->priv;
 		if (st->ops.pid_parse != NULL)
-			if (st->ops.pid_parse(d->fe,onoff) < 0)
+			if (st->ops.pid_parse(adap->fe,onoff) < 0)
 				err("could not handle pid_parser");
 	}
 	return 0;
@@ -68,24 +68,24 @@
 }
 EXPORT_SYMBOL(dibusb_power_ctrl);
 
-int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
 	u8 b[3] = { 0 };
 	int ret;
 
-	if ((ret = dibusb_streaming_ctrl(d,onoff)) < 0)
+	if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0)
 		return ret;
 
 	if (onoff) {
 		b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
 		b[1] = 0x00;
-		if ((ret = dvb_usb_generic_write(d,b,2)) < 0)
+		if ((ret = dvb_usb_generic_write(adap->dev,b,2)) < 0)
 			return ret;
 	}
 
 	b[0] = DIBUSB_REQ_SET_IOCTL;
 	b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
-	return dvb_usb_generic_write(d,b,3);
+	return dvb_usb_generic_write(adap->dev,b,3);
 }
 EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
 
@@ -228,12 +228,12 @@
 	.output_mpeg2_in_188_bytes = 1,
 };
 
-int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
+int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	if (dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000P_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0 ||
-		dib3000mc_attach(&d->i2c_adap, 1, DEFAULT_DIB3000MC_I2C_ADDRESS, 0, &mod3000p_dib3000p_config, &d->fe) == 0) {
-		if (d->priv != NULL) {
-			struct dibusb_state *st = d->priv;
+	if ((adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000P_I2C_ADDRESS,  &mod3000p_dib3000p_config)) != NULL ||
+		(adap->fe = dvb_attach(dib3000mc_attach, &adap->dev->i2c_adap, DEFAULT_DIB3000MC_I2C_ADDRESS, &mod3000p_dib3000p_config)) != NULL) {
+		if (adap->priv != NULL) {
+			struct dibusb_state *st = adap->priv;
 			st->ops.pid_parse = dib3000mc_pid_parse;
 			st->ops.pid_ctrl  = dib3000mc_pid_control;
 		}
@@ -247,20 +247,19 @@
 	0x60
 };
 
-int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
+int dibusb_dib3000mc_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	struct dibusb_state *st = d->priv;
-	int ret;
+	struct dibusb_state *st = adap->priv;
 	u8 a,b;
 	u16 if1 = 1220;
 	struct i2c_adapter *tun_i2c;
 
 	// First IF calibration for Liteon Sticks
-	if (d->udev->descriptor.idVendor == USB_VID_LITEON &&
-		d->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) {
+	if (adap->dev->udev->descriptor.idVendor  == USB_VID_LITEON &&
+		adap->dev->udev->descriptor.idProduct == USB_PID_LITEON_DVB_T_WARM) {
 
-		dibusb_read_eeprom_byte(d,0x7E,&a);
-		dibusb_read_eeprom_byte(d,0x7F,&b);
+		dibusb_read_eeprom_byte(adap->dev,0x7E,&a);
+		dibusb_read_eeprom_byte(adap->dev,0x7F,&b);
 
 		if (a == 0x00)
 			if1 += b;
@@ -269,14 +268,14 @@
 		else
 			warn("LITE-ON DVB-T: Strange IF1 calibration :%2X %2X\n", a, b);
 
-	} else if (d->udev->descriptor.idVendor  == USB_VID_DIBCOM &&
-		   d->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) {
+	} else if (adap->dev->udev->descriptor.idVendor  == USB_VID_DIBCOM &&
+		   adap->dev->udev->descriptor.idProduct == USB_PID_DIBCOM_MOD3001_WARM) {
 		u8 desc;
-		dibusb_read_eeprom_byte(d, 7, &desc);
+		dibusb_read_eeprom_byte(adap->dev, 7, &desc);
 		if (desc == 2) {
 			a = 127;
 			do {
-				dibusb_read_eeprom_byte(d, a, &desc);
+				dibusb_read_eeprom_byte(adap->dev, a, &desc);
 				a--;
 			} while (a > 7 && (desc == 0xff || desc == 0x00));
 			if (desc & 0x80)
@@ -286,15 +285,15 @@
 		}
 	}
 
-	tun_i2c = dib3000mc_get_tuner_i2c_master(d->fe, 1);
-	if ((ret = mt2060_attach(d->fe, tun_i2c, &stk3000p_mt2060_config, if1)) != 0) {
+	tun_i2c = dib3000mc_get_tuner_i2c_master(adap->fe, 1);
+	if (dvb_attach(mt2060_attach, adap->fe, tun_i2c, &stk3000p_mt2060_config, if1) == NULL) {
 		/* not found - use panasonic pll parameters */
-		if (dvb_pll_attach(d->fe, 0x60, tun_i2c, &dvb_pll_env57h1xd5) == NULL)
+		if (dvb_attach(dvb_pll_attach, adap->fe, 0x60, tun_i2c, &dvb_pll_env57h1xd5) == NULL)
 			return -ENOMEM;
 	} else {
 		st->mt2060_present = 1;
 		/* set the correct parameters for the dib3000p */
-		dib3000mc_set_config(d->fe, &stk3000p_dib3000p_config);
+		dib3000mc_set_config(adap->fe, &stk3000p_dib3000p_config);
 	}
 	return 0;
 }
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index effd34c..4fe363e 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -14,35 +14,35 @@
  */
 #include "dibusb.h"
 
-static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
+static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct dib3000_config demod_cfg;
-	struct dibusb_state *st = d->priv;
+	struct dibusb_state *st = adap->priv;
 
 	demod_cfg.demod_address = 0x8;
 
-	if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
+	if ((adap->fe = dib3000mb_attach(&demod_cfg,&adap->dev->i2c_adap,&st->ops)) == NULL)
 		return -ENODEV;
 
-	d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
-	d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+	adap->fe->ops.tuner_ops.init       = dvb_usb_tuner_init_i2c;
+	adap->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
 
-	d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
+	adap->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 
 	return 0;
 }
 
-static int dibusb_thomson_tuner_attach(struct dvb_usb_device *d)
+static int dibusb_thomson_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	d->pll_addr = 0x61;
-	d->pll_desc = &dvb_pll_tua6010xs;
+	adap->pll_addr = 0x61;
+	adap->pll_desc = &dvb_pll_tua6010xs;
 	return 0;
 }
 
 /* Some of the Artec 1.1 device aren't equipped with the default tuner
  * (Thomson Cable), but with a Panasonic ENV77H11D5.  This function figures
  * this out. */
-static int dibusb_tuner_probe_and_attach(struct dvb_usb_device *d)
+static int dibusb_tuner_probe_and_attach(struct dvb_usb_adapter *adap)
 {
 	u8 b[2] = { 0,0 }, b2[1];
 	int ret = 0;
@@ -54,36 +54,36 @@
 	/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
 	msg[0].addr = msg[1].addr = 0x60;
 
-	if (d->tuner_pass_ctrl)
-		d->tuner_pass_ctrl(d->fe,1,msg[0].addr);
+	if (adap->tuner_pass_ctrl)
+		adap->tuner_pass_ctrl(adap->fe,1,msg[0].addr);
 
-	if (i2c_transfer (&d->i2c_adap, msg, 2) != 2) {
+	if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
 		err("tuner i2c write failed.");
 		ret = -EREMOTEIO;
 	}
 
-	if (d->tuner_pass_ctrl)
-		d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
+	if (adap->tuner_pass_ctrl)
+		adap->tuner_pass_ctrl(adap->fe,0,msg[0].addr);
 
 	if (b2[0] == 0xfe) {
 		info("This device has the Thomson Cable onboard. Which is default.");
-		dibusb_thomson_tuner_attach(d);
+		dibusb_thomson_tuner_attach(adap);
 	} else {
 		u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
 		info("This device has the Panasonic ENV77H11D5 onboard.");
-		d->pll_addr = 0x60;
-		memcpy(d->pll_init,bpll,4);
-		d->pll_desc = &dvb_pll_tda665x;
+		adap->pll_addr = 0x60;
+		memcpy(adap->pll_init,bpll,4);
+		adap->pll_desc = &dvb_pll_tda665x;
 	}
 
 	return ret;
 }
 
 /* USB Driver stuff */
-static struct dvb_usb_properties dibusb1_1_properties;
-static struct dvb_usb_properties dibusb1_1_an2235_properties;
-static struct dvb_usb_properties dibusb2_0b_properties;
-static struct dvb_usb_properties artec_t1_usb2_properties;
+static struct dvb_usb_device_properties dibusb1_1_properties;
+static struct dvb_usb_device_properties dibusb1_1_an2235_properties;
+static struct dvb_usb_device_properties dibusb2_0b_properties;
+static struct dvb_usb_device_properties artec_t1_usb2_properties;
 
 static int dibusb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -150,23 +150,42 @@
 };
 MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
 
-static struct dvb_usb_properties dibusb1_1_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
-	.pid_filter_count = 16,
+static struct dvb_usb_device_properties dibusb1_1_properties = {
+	.caps =  DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_AN2135,
 
 	.firmware = "dvb-usb-dibusb-5.0.0.11.fw",
 
-	.size_of_priv     = sizeof(struct dibusb_state),
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.pid_filter_count = 16,
 
 	.streaming_ctrl   = dibusb_streaming_ctrl,
 	.pid_filter       = dibusb_pid_filter,
 	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-	.power_ctrl       = dibusb_power_ctrl,
 	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
 	.tuner_attach     = dibusb_tuner_probe_and_attach,
 
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+			.size_of_priv     = sizeof(struct dibusb_state),
+		}
+	},
+
+	.power_ctrl       = dibusb_power_ctrl,
+
 	.rc_interval      = DEFAULT_RC_INTERVAL,
 	.rc_key_map       = dibusb_rc_keys,
 	.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
@@ -175,17 +194,6 @@
 	.i2c_algo         = &dibusb_i2c_algo,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
-		.endpoint = 0x02,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
 
 	.num_device_descs = 9,
 	.devices = {
@@ -228,23 +236,40 @@
 	}
 };
 
-static struct dvb_usb_properties dibusb1_1_an2235_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
-	.pid_filter_count = 16,
-
+static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 	.usb_ctrl = CYPRESS_AN2235,
 
 	.firmware = "dvb-usb-dibusb-an2235-01.fw",
 
-	.size_of_priv     = sizeof(struct dibusb_state),
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_ADAP_HAS_PID_FILTER,
+			.pid_filter_count = 16,
 
 	.streaming_ctrl   = dibusb_streaming_ctrl,
 	.pid_filter       = dibusb_pid_filter,
 	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-	.power_ctrl       = dibusb_power_ctrl,
 	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
 	.tuner_attach     = dibusb_tuner_probe_and_attach,
 
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+			.size_of_priv     = sizeof(struct dibusb_state),
+		},
+	},
+	.power_ctrl       = dibusb_power_ctrl,
+
 	.rc_interval      = DEFAULT_RC_INTERVAL,
 	.rc_key_map       = dibusb_rc_keys,
 	.rc_key_map_size  = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
@@ -253,17 +278,6 @@
 	.i2c_algo         = &dibusb_i2c_algo,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
-		.endpoint = 0x02,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
 
 #ifdef CONFIG_DVB_USB_DIBUSB_MB_FAULTY
 	.num_device_descs = 2,
@@ -285,22 +299,39 @@
 	}
 };
 
-static struct dvb_usb_properties dibusb2_0b_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
-	.pid_filter_count = 16,
+static struct dvb_usb_device_properties dibusb2_0b_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
 
 	.firmware = "dvb-usb-adstech-usb2-02.fw",
 
-	.size_of_priv     = sizeof(struct dibusb_state),
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.pid_filter_count = 16,
 
 	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
 	.pid_filter       = dibusb_pid_filter,
 	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-	.power_ctrl       = dibusb2_0_power_ctrl,
 	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
 	.tuner_attach     = dibusb_thomson_tuner_attach,
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+			.size_of_priv     = sizeof(struct dibusb_state),
+		}
+	},
+	.power_ctrl       = dibusb2_0_power_ctrl,
 
 	.rc_interval      = DEFAULT_RC_INTERVAL,
 	.rc_key_map       = dibusb_rc_keys,
@@ -310,17 +341,6 @@
 	.i2c_algo         = &dibusb_i2c_algo,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
-		.endpoint = 0x06,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
 
 	.num_device_descs = 2,
 	.devices = {
@@ -336,22 +356,39 @@
 	}
 };
 
-static struct dvb_usb_properties artec_t1_usb2_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
-	.pid_filter_count = 16,
+static struct dvb_usb_device_properties artec_t1_usb2_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
 
 	.firmware = "dvb-usb-dibusb-6.0.0.8.fw",
 
-	.size_of_priv     = sizeof(struct dibusb_state),
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.pid_filter_count = 16,
 
 	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
 	.pid_filter       = dibusb_pid_filter,
 	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-	.power_ctrl       = dibusb2_0_power_ctrl,
 	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
 	.tuner_attach     = dibusb_tuner_probe_and_attach,
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+			.size_of_priv     = sizeof(struct dibusb_state),
+		}
+	},
+	.power_ctrl       = dibusb2_0_power_ctrl,
 
 	.rc_interval      = DEFAULT_RC_INTERVAL,
 	.rc_key_map       = dibusb_rc_keys,
@@ -361,17 +398,6 @@
 	.i2c_algo         = &dibusb_i2c_algo,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
-		.endpoint = 0x06,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
 
 	.num_device_descs = 1,
 	.devices = {
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
index eca4082a..a0fd37e 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -15,7 +15,7 @@
 #include "dibusb.h"
 
 /* USB Driver stuff */
-static struct dvb_usb_properties dibusb_mc_properties;
+static struct dvb_usb_device_properties dibusb_mc_properties;
 
 static int dibusb_mc_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -43,22 +43,39 @@
 };
 MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
 
-static struct dvb_usb_properties dibusb_mc_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
-	.pid_filter_count = 32,
+static struct dvb_usb_device_properties dibusb_mc_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-dibusb-6.0.0.8.fw",
 
-	.size_of_priv     = sizeof(struct dibusb_state),
-
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.pid_filter_count = 32,
 	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
 	.pid_filter       = dibusb_pid_filter,
 	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-	.power_ctrl       = dibusb2_0_power_ctrl,
 	.frontend_attach  = dibusb_dib3000mc_frontend_attach,
 	.tuner_attach     = dibusb_dib3000mc_tuner_attach,
 
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+			.size_of_priv     = sizeof(struct dibusb_state),
+		}
+	},
+	.power_ctrl       = dibusb2_0_power_ctrl,
+
 	.rc_interval      = DEFAULT_RC_INTERVAL,
 	.rc_key_map       = dibusb_rc_keys,
 	.rc_key_map_size  = 111, /* FIXME */
@@ -67,17 +84,6 @@
 	.i2c_algo         = &dibusb_i2c_algo,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
-		.endpoint = 0x06,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
 
 	.num_device_descs = 7,
 	.devices = {
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
index a43f874..5153fb9 100644
--- a/drivers/media/dvb/dvb-usb/dibusb.h
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -107,14 +107,15 @@
 
 extern struct i2c_algorithm dibusb_i2c_algo;
 
-extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *);
-extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *);
+extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_adapter *);
+extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_adapter *);
 
-extern int dibusb_streaming_ctrl(struct dvb_usb_device *, int);
-extern int dibusb_pid_filter(struct dvb_usb_device *, int, u16, int);
-extern int dibusb_pid_filter_ctrl(struct dvb_usb_device *, int);
+extern int dibusb_streaming_ctrl(struct dvb_usb_adapter *, int);
+extern int dibusb_pid_filter(struct dvb_usb_adapter *, int, u16, int);
+extern int dibusb_pid_filter_ctrl(struct dvb_usb_adapter *, int);
+extern int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *, int);
+
 extern int dibusb_power_ctrl(struct dvb_usb_device *, int);
-extern int dibusb2_0_streaming_ctrl(struct dvb_usb_device *, int);
 extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
 
 #define DEFAULT_RC_INTERVAL 150
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 0158544..8fb3437 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -83,7 +83,7 @@
 
 /* Callbacks for DVB USB */
 static int digitv_identify_state (struct usb_device *udev, struct
-		dvb_usb_properties *props, struct dvb_usb_device_description **desc,
+		dvb_usb_device_properties *props, struct dvb_usb_device_description **desc,
 		int *cold)
 {
 	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
@@ -116,33 +116,33 @@
 
 static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
-	struct dvb_usb_device *d = fe->dvb->priv;
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
 	u8 b[5];
 	dvb_usb_tuner_calc_regs(fe,fep,b, 5);
-	return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
+	return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
 }
 
 static struct nxt6000_config digitv_nxt6000_config = {
 	.clock_inversion = 1,
 };
 
-static int digitv_frontend_attach(struct dvb_usb_device *d)
+static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	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;
+	if ((adap->fe = dvb_attach(mt352_attach, &digitv_mt352_config, &adap->dev->i2c_adap)) != NULL) {
+		adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 		return 0;
 	}
-	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;
+	if ((adap->fe = dvb_attach(nxt6000_attach, &digitv_nxt6000_config, &adap->dev->i2c_adap)) != NULL) {
+		adap->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
 		return 0;
 	}
 	return -EIO;
 }
 
-static int digitv_tuner_attach(struct dvb_usb_device *d)
+static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
 {
-	d->pll_addr = 0x60;
-	d->pll_desc = &dvb_pll_tded4;
+	adap->pll_addr = 0x60;
+	adap->pll_desc = &dvb_pll_tded4;
 	return 0;
 }
 
@@ -238,7 +238,7 @@
 }
 
 /* DVB USB Driver stuff */
-static struct dvb_usb_properties digitv_properties;
+static struct dvb_usb_device_properties digitv_properties;
 
 static int digitv_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -265,30 +265,21 @@
 };
 MODULE_DEVICE_TABLE (usb, digitv_table);
 
-static struct dvb_usb_properties digitv_properties = {
+static struct dvb_usb_device_properties digitv_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-digitv-02.fw",
 
-	.size_of_priv     = 0,
-
+	.num_adapters = 1,
+	.adapter = {
+		{
 	.frontend_attach  = digitv_frontend_attach,
 	.tuner_attach     = digitv_tuner_attach,
 
-	.rc_interval      = 1000,
-	.rc_key_map       = digitv_rc_keys,
-	.rc_key_map_size  = ARRAY_SIZE(digitv_rc_keys),
-	.rc_query         = digitv_rc_query,
-
-	.identify_state   = digitv_identify_state,
-
-	.i2c_algo         = &digitv_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
+			.stream = {
+				.type = USB_BULK,
 		.count = 7,
 		.endpoint = 0x02,
 		.u = {
@@ -297,6 +288,18 @@
 			}
 		}
 	},
+		}
+	},
+	.identify_state   = digitv_identify_state,
+
+	.rc_interval      = 1000,
+	.rc_key_map       = digitv_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(digitv_rc_keys),
+	.rc_query         = digitv_rc_query,
+
+	.i2c_algo         = &digitv_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
 
 	.num_device_descs = 1,
 	.devices = {
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
index 27af4e43..fa43a41 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -28,19 +28,19 @@
 	return 0;
 }
 
-static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
 	u8 b_streaming[2] = { SET_STREAMING, onoff };
 	u8 b_rst_pid = RESET_PID_FILTER;
 
-	dvb_usb_generic_write(d,b_streaming,2);
+	dvb_usb_generic_write(adap->dev, b_streaming, 2);
 
 	if (onoff == 0)
-		dvb_usb_generic_write(d,&b_rst_pid,1);
+		dvb_usb_generic_write(adap->dev, &b_rst_pid, 1);
 	return 0;
 }
 
-static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)
 {
 	u8 b_pid[4];
 	pid = onoff ? pid : 0;
@@ -50,7 +50,7 @@
 	b_pid[2] = pid & 0xff;
 	b_pid[3] = (pid >> 8) & 0x1f;
 
-	return dvb_usb_generic_write(d,b_pid,4);
+	return dvb_usb_generic_write(adap->dev, b_pid, 4);
 }
 
 /* remote control */
@@ -86,16 +86,16 @@
 	return 0;
 }
 
-static int dtt200u_frontend_attach(struct dvb_usb_device *d)
+static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	d->fe = dtt200u_fe_attach(d);
+	adap->fe = dtt200u_fe_attach(adap->dev);
 	return 0;
 }
 
-static struct dvb_usb_properties dtt200u_properties;
-static struct dvb_usb_properties wt220u_fc_properties;
-static struct dvb_usb_properties wt220u_properties;
-static struct dvb_usb_properties wt220u_zl0353_properties;
+static struct dvb_usb_device_properties dtt200u_properties;
+static struct dvb_usb_device_properties wt220u_fc_properties;
+static struct dvb_usb_device_properties wt220u_properties;
+static struct dvb_usb_device_properties wt220u_zl0353_properties;
 
 static int dtt200u_usb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -123,28 +123,22 @@
 };
 MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
 
-static struct dvb_usb_properties dtt200u_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
-	.pid_filter_count = 15,
-
+static struct dvb_usb_device_properties dtt200u_properties = {
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-dtt200u-01.fw",
 
-	.power_ctrl      = dtt200u_power_ctrl,
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
+			.pid_filter_count = 15,
+
 	.streaming_ctrl  = dtt200u_streaming_ctrl,
 	.pid_filter      = dtt200u_pid_filter,
 	.frontend_attach = dtt200u_frontend_attach,
-
-	.rc_interval     = 300,
-	.rc_key_map      = dtt200u_rc_keys,
-	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
-	.rc_query        = dtt200u_rc_query,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
+			.stream = {
+				.type = USB_BULK,
 		.count = 7,
 		.endpoint = 0x02,
 		.u = {
@@ -153,6 +147,16 @@
 			}
 		}
 	},
+		}
+	},
+	.power_ctrl      = dtt200u_power_ctrl,
+
+	.rc_interval     = 300,
+	.rc_key_map      = dtt200u_rc_keys,
+	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+	.rc_query        = dtt200u_rc_query,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
 
 	.num_device_descs = 1,
 	.devices = {
@@ -164,28 +168,22 @@
 	}
 };
 
-static struct dvb_usb_properties wt220u_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
-	.pid_filter_count = 15,
-
+static struct dvb_usb_device_properties wt220u_properties = {
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-wt220u-02.fw",
 
-	.power_ctrl      = dtt200u_power_ctrl,
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
+			.pid_filter_count = 15,
+
 	.streaming_ctrl  = dtt200u_streaming_ctrl,
 	.pid_filter      = dtt200u_pid_filter,
 	.frontend_attach = dtt200u_frontend_attach,
-
-	.rc_interval     = 300,
-	.rc_key_map      = dtt200u_rc_keys,
-	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
-	.rc_query        = dtt200u_rc_query,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
+			.stream = {
+				.type = USB_BULK,
 		.count = 7,
 		.endpoint = 0x02,
 		.u = {
@@ -194,6 +192,16 @@
 			}
 		}
 	},
+		}
+	},
+	.power_ctrl      = dtt200u_power_ctrl,
+
+	.rc_interval     = 300,
+	.rc_key_map      = dtt200u_rc_keys,
+	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+	.rc_query        = dtt200u_rc_query,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
 
 	.num_device_descs = 1,
 	.devices = {
@@ -205,17 +213,33 @@
 	}
 };
 
-static struct dvb_usb_properties wt220u_fc_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
-	.pid_filter_count = 15,
-
+static struct dvb_usb_device_properties wt220u_fc_properties = {
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-wt220u-fc03.fw",
 
-	.power_ctrl      = dtt200u_power_ctrl,
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
+			.pid_filter_count = 15,
+
 	.streaming_ctrl  = dtt200u_streaming_ctrl,
 	.pid_filter      = dtt200u_pid_filter,
 	.frontend_attach = dtt200u_frontend_attach,
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 7,
+				.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+		}
+	},
+	.power_ctrl      = dtt200u_power_ctrl,
 
 	.rc_interval     = 300,
 	.rc_key_map      = dtt200u_rc_keys,
@@ -224,18 +248,6 @@
 
 	.generic_bulk_ctrl_endpoint = 0x01,
 
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
-		.endpoint = 0x86,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
-
 	.num_device_descs = 1,
 	.devices = {
 		{ .name = "WideView WT-220U PenType Receiver (Typhoon/Freecom)",
@@ -246,28 +258,22 @@
 	}
 };
 
-static struct dvb_usb_properties wt220u_zl0353_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
-	.pid_filter_count = 15,
-
+static struct dvb_usb_device_properties wt220u_zl0353_properties = {
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-wt220u-zl0353-01.fw",
 
-	.power_ctrl      = dtt200u_power_ctrl,
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_NEED_PID_FILTERING,
+			.pid_filter_count = 15,
+
 	.streaming_ctrl  = dtt200u_streaming_ctrl,
 	.pid_filter      = dtt200u_pid_filter,
 	.frontend_attach = dtt200u_frontend_attach,
-
-	.rc_interval     = 300,
-	.rc_key_map      = dtt200u_rc_keys,
-	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
-	.rc_query        = dtt200u_rc_query,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
-
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
+			.stream = {
+				.type = USB_BULK,
 		.count = 7,
 		.endpoint = 0x02,
 		.u = {
@@ -276,6 +282,16 @@
 			}
 		}
 	},
+		}
+	},
+	.power_ctrl      = dtt200u_power_ctrl,
+
+	.rc_interval     = 300,
+	.rc_key_map      = dtt200u_rc_keys,
+	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+	.rc_query        = dtt200u_rc_query,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
 
 	.num_device_descs = 1,
 	.devices = {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
index a3460bf..35ab68f 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-common.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
@@ -14,31 +14,36 @@
 extern int dvb_usb_debug;
 extern int dvb_usb_disable_rc_polling;
 
-#define deb_info(args...) dprintk(dvb_usb_debug,0x01,args)
-#define deb_xfer(args...) dprintk(dvb_usb_debug,0x02,args)
-#define deb_pll(args...)  dprintk(dvb_usb_debug,0x04,args)
-#define deb_ts(args...)   dprintk(dvb_usb_debug,0x08,args)
-#define deb_err(args...)  dprintk(dvb_usb_debug,0x10,args)
-#define deb_rc(args...)   dprintk(dvb_usb_debug,0x20,args)
-#define deb_fw(args...)   dprintk(dvb_usb_debug,0x40,args)
-#define deb_mem(args...)  dprintk(dvb_usb_debug,0x80,args)
+#define deb_info(args...)  dprintk(dvb_usb_debug,0x001,args)
+#define deb_xfer(args...)  dprintk(dvb_usb_debug,0x002,args)
+#define deb_pll(args...)   dprintk(dvb_usb_debug,0x004,args)
+#define deb_ts(args...)    dprintk(dvb_usb_debug,0x008,args)
+#define deb_err(args...)   dprintk(dvb_usb_debug,0x010,args)
+#define deb_rc(args...)    dprintk(dvb_usb_debug,0x020,args)
+#define deb_fw(args...)    dprintk(dvb_usb_debug,0x040,args)
+#define deb_mem(args...)   dprintk(dvb_usb_debug,0x080,args)
+#define deb_uxfer(args...) dprintk(dvb_usb_debug,0x100,args)
 
 /* commonly used  methods */
-extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_properties *);
+extern int dvb_usb_download_firmware(struct usb_device *, struct dvb_usb_device_properties *);
 
-extern int dvb_usb_urb_submit(struct dvb_usb_device *);
-extern int dvb_usb_urb_kill(struct dvb_usb_device *);
-extern int dvb_usb_urb_init(struct dvb_usb_device *);
-extern int dvb_usb_urb_exit(struct dvb_usb_device *);
+extern int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff);
+
+extern int usb_urb_init(struct usb_data_stream *stream, struct usb_data_stream_properties *props);
+extern int usb_urb_exit(struct usb_data_stream *stream);
+extern int usb_urb_submit(struct usb_data_stream *stream);
+extern int usb_urb_kill(struct usb_data_stream *stream);
+
+extern int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap);
+extern int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap);
 
 extern int dvb_usb_i2c_init(struct dvb_usb_device *);
 extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
 
-extern int dvb_usb_dvb_init(struct dvb_usb_device *);
-extern int dvb_usb_dvb_exit(struct dvb_usb_device *);
-
-extern int dvb_usb_fe_init(struct dvb_usb_device *);
-extern int dvb_usb_fe_exit(struct dvb_usb_device *);
+extern int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap);
+extern int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap);
+extern int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap);
+extern int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap);
 
 extern int dvb_usb_remote_init(struct dvb_usb_device *);
 extern int dvb_usb_remote_exit(struct dvb_usb_device *);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index fe6208a..4561a67 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -1,6 +1,6 @@
 /* dvb-usb-dvb.c is part of the DVB USB library.
  *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  * see dvb-usb-init.c for copyright information.
  *
  * This file contains functions for initializing and handling the
@@ -8,55 +8,55 @@
  */
 #include "dvb-usb-common.h"
 
+/* does the complete input transfer handling */
 static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
 {
-	struct dvb_usb_device *d = dvbdmxfeed->demux->priv;
+	struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
 	int newfeedcount,ret;
 
-	if (d == NULL)
+	if (adap == NULL)
 		return -ENODEV;
 
-	newfeedcount = d->feedcount + (onoff ? 1 : -1);
+	newfeedcount = adap->feedcount + (onoff ? 1 : -1);
 
-	/*
-	 * stop feed before setting a new pid if there will be no pid anymore
-	 */
+	/* stop feed before setting a new pid if there will be no pid anymore */
 	if (newfeedcount == 0) {
 		deb_ts("stop feeding\n");
-		dvb_usb_urb_kill(d);
+		usb_urb_kill(&adap->stream);
 
-		if (d->props.streaming_ctrl != NULL)
-			if ((ret = d->props.streaming_ctrl(d,0)))
+		if (adap->props.streaming_ctrl != NULL)
+			if ((ret = adap->props.streaming_ctrl(adap,0)))
 				err("error while stopping stream.");
-
 	}
 
-	d->feedcount = newfeedcount;
+	adap->feedcount = newfeedcount;
 
 	/* activate the pid on the device specific pid_filter */
-	deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
-	if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
-		d->pid_filtering &&
-		d->props.pid_filter != NULL)
-		d->props.pid_filter(d,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+	deb_ts("setting pid (%s): %5d %04x at index %d '%s'\n",adap->pid_filtering ?
+		"yes" : "no", dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ?
+		"on" : "off");
+	if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+		adap->pid_filtering &&
+		adap->props.pid_filter != NULL)
+		adap->props.pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid,onoff);
 
 	/* start the feed if this was the first feed and there is still a feed
 	 * for reception.
 	 */
-	if (d->feedcount == onoff && d->feedcount > 0) {
+	if (adap->feedcount == onoff && adap->feedcount > 0) {
 		deb_ts("submitting all URBs\n");
-		dvb_usb_urb_submit(d);
+		usb_urb_submit(&adap->stream);
 
 		deb_ts("controlling pid parser\n");
-		if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
-			d->props.caps & DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF &&
-			d->props.pid_filter_ctrl != NULL)
-			if (d->props.pid_filter_ctrl(d,d->pid_filtering) < 0)
+		if (adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+			adap->props.caps & DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
+			adap->props.pid_filter_ctrl != NULL)
+			if (adap->props.pid_filter_ctrl(adap,adap->pid_filtering) < 0)
 				err("could not handle pid_parser");
 
 		deb_ts("start feeding\n");
-		if (d->props.streaming_ctrl != NULL)
-			if (d->props.streaming_ctrl(d,1)) {
+		if (adap->props.streaming_ctrl != NULL)
+			if (adap->props.streaming_ctrl(adap,1)) {
 				err("error while enabling fifo.");
 				return -ENODEV;
 			}
@@ -77,134 +77,130 @@
 	return dvb_usb_ctrl_feed(dvbdmxfeed,0);
 }
 
-int dvb_usb_dvb_init(struct dvb_usb_device *d)
+int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap)
 {
 	int ret;
 
-	if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
-			d->owner, &d->udev->dev)) < 0) {
+	if ((ret = dvb_register_adapter(&adap->dvb_adap, adap->dev->desc->name,
+			adap->dev->owner, &adap->dev->udev->dev)) < 0) {
 		deb_info("dvb_register_adapter failed: error %d", ret);
 		goto err;
 	}
-	d->dvb_adap.priv = d;
+	adap->dvb_adap.priv = adap;
 
-	if (d->props.read_mac_address) {
-		if (d->props.read_mac_address(d,d->dvb_adap.proposed_mac) == 0)
-			info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",d->dvb_adap.proposed_mac[0],
-					d->dvb_adap.proposed_mac[1],d->dvb_adap.proposed_mac[2],
-					d->dvb_adap.proposed_mac[3],d->dvb_adap.proposed_mac[4],
-					d->dvb_adap.proposed_mac[5]);
+	if (adap->dev->props.read_mac_address) {
+		if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0)
+			info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",adap->dvb_adap.proposed_mac[0],
+					adap->dvb_adap.proposed_mac[1], adap->dvb_adap.proposed_mac[2],
+					adap->dvb_adap.proposed_mac[3], adap->dvb_adap.proposed_mac[4],
+					adap->dvb_adap.proposed_mac[5]);
 		else
 			err("MAC address reading failed.");
 	}
 
 
-	d->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-	d->demux.priv = d;
+	adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+	adap->demux.priv             = adap;
 
-	d->demux.feednum = d->demux.filternum = d->max_feed_count;
-	d->demux.start_feed = dvb_usb_start_feed;
-	d->demux.stop_feed  = dvb_usb_stop_feed;
-	d->demux.write_to_decoder = NULL;
-	if ((ret = dvb_dmx_init(&d->demux)) < 0) {
+	adap->demux.feednum          = adap->demux.filternum = adap->max_feed_count;
+	adap->demux.start_feed       = dvb_usb_start_feed;
+	adap->demux.stop_feed        = dvb_usb_stop_feed;
+	adap->demux.write_to_decoder = NULL;
+	if ((ret = dvb_dmx_init(&adap->demux)) < 0) {
 		err("dvb_dmx_init failed: error %d",ret);
 		goto err_dmx;
 	}
 
-	d->dmxdev.filternum = d->demux.filternum;
-	d->dmxdev.demux = &d->demux.dmx;
-	d->dmxdev.capabilities = 0;
-	if ((ret = dvb_dmxdev_init(&d->dmxdev, &d->dvb_adap)) < 0) {
+	adap->dmxdev.filternum       = adap->demux.filternum;
+	adap->dmxdev.demux           = &adap->demux.dmx;
+	adap->dmxdev.capabilities    = 0;
+	if ((ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap)) < 0) {
 		err("dvb_dmxdev_init failed: error %d",ret);
 		goto err_dmx_dev;
 	}
 
-	dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
+	dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
 
-	d->state |= DVB_USB_STATE_DVB;
+	adap->state |= DVB_USB_ADAP_STATE_DVB;
 	return 0;
 
 err_dmx_dev:
-	dvb_dmx_release(&d->demux);
+	dvb_dmx_release(&adap->demux);
 err_dmx:
-	dvb_unregister_adapter(&d->dvb_adap);
+	dvb_unregister_adapter(&adap->dvb_adap);
 err:
 	return ret;
 }
 
-int dvb_usb_dvb_exit(struct dvb_usb_device *d)
+int dvb_usb_adapter_dvb_exit(struct dvb_usb_adapter *adap)
 {
-	if (d->state & DVB_USB_STATE_DVB) {
+	if (adap->state & DVB_USB_ADAP_STATE_DVB) {
 		deb_info("unregistering DVB part\n");
-		dvb_net_release(&d->dvb_net);
-		d->demux.dmx.close(&d->demux.dmx);
-		dvb_dmxdev_release(&d->dmxdev);
-		dvb_dmx_release(&d->demux);
-		dvb_unregister_adapter(&d->dvb_adap);
-		d->state &= ~DVB_USB_STATE_DVB;
+		dvb_net_release(&adap->dvb_net);
+		adap->demux.dmx.close(&adap->demux.dmx);
+		dvb_dmxdev_release(&adap->dmxdev);
+		dvb_dmx_release(&adap->demux);
+		dvb_unregister_adapter(&adap->dvb_adap);
+		adap->state &= ~DVB_USB_ADAP_STATE_DVB;
 	}
 	return 0;
 }
 
 static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
 {
-	struct dvb_usb_device *d = fe->dvb->priv;
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
-	if (d->props.power_ctrl)
-		d->props.power_ctrl(d,1);
+	dvb_usb_device_power_ctrl(adap->dev, 1);
 
-	if (d->fe_init)
-		d->fe_init(fe);
+	if (adap->fe_init)
+		adap->fe_init(fe);
 
 	return 0;
 }
 
 static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
 {
-	struct dvb_usb_device *d = fe->dvb->priv;
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
-	if (d->fe_sleep)
-		d->fe_sleep(fe);
+	if (adap->fe_sleep)
+		adap->fe_sleep(fe);
 
-	if (d->props.power_ctrl)
-		d->props.power_ctrl(d,0);
-
-	return 0;
+	return dvb_usb_device_power_ctrl(adap->dev, 0);
 }
 
-int dvb_usb_fe_init(struct dvb_usb_device* d)
+int dvb_usb_adapter_frontend_init(struct dvb_usb_adapter *adap)
 {
-	if (d->props.frontend_attach == NULL) {
-		err("strange: '%s' doesn't want to attach a frontend.",d->desc->name);
+	if (adap->props.frontend_attach == NULL) {
+		err("strange: '%s' #%d doesn't want to attach a frontend.",adap->dev->desc->name, adap->id);
 		return 0;
 	}
 
 	/* re-assign sleep and wakeup functions */
-	if (d->props.frontend_attach(d) == 0 && d->fe != NULL) {
-		d->fe_init = d->fe->ops.init;   d->fe->ops.init  = dvb_usb_fe_wakeup;
-		d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
+	if (adap->props.frontend_attach(adap) == 0 && adap->fe != NULL) {
+		adap->fe_init  = adap->fe->ops.init;  adap->fe->ops.init  = dvb_usb_fe_wakeup;
+		adap->fe_sleep = adap->fe->ops.sleep; adap->fe->ops.sleep = dvb_usb_fe_sleep;
 
-		if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
+		if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
 			err("Frontend registration failed.");
-			dvb_frontend_detach(d->fe);
-			d->fe = NULL;
+			dvb_frontend_detach(adap->fe);
+			adap->fe = NULL;
 			return -ENODEV;
 		}
 
 		/* only attach the tuner if the demod is there */
-		if (d->props.tuner_attach != NULL)
-			d->props.tuner_attach(d);
+		if (adap->props.tuner_attach != NULL)
+			adap->props.tuner_attach(adap);
 	} else
-		err("no frontend was attached by '%s'",d->desc->name);
+		err("no frontend was attached by '%s'",adap->dev->desc->name);
 
 	return 0;
 }
 
-int dvb_usb_fe_exit(struct dvb_usb_device *d)
+int dvb_usb_adapter_frontend_exit(struct dvb_usb_adapter *adap)
 {
-	if (d->fe != NULL) {
-		dvb_unregister_frontend(d->fe);
-		dvb_frontend_detach(d->fe);
+	if (adap->fe != NULL) {
+		dvb_unregister_frontend(adap->fe);
+		dvb_frontend_detach(adap->fe);
 	}
 	return 0;
 }
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
index 9222b0a..e1112e3 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -1,6 +1,6 @@
 /* dvb-usb-firmware.c is part of the DVB USB library.
  *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  * see dvb-usb-init.c for copyright information.
  *
  * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices.
@@ -24,9 +24,6 @@
 	{ .id = CYPRESS_FX2,     .name = "Cypress FX2",     .cpu_cs_register = 0xe600 },
 };
 
-static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
-			       int *pos);
-
 /*
  * load a firmware packet to the device
  */
@@ -78,7 +75,7 @@
 }
 EXPORT_SYMBOL(usb_cypress_load_firmware);
 
-int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_properties *props)
+int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_device_properties *props)
 {
 	int ret;
 	const struct firmware *fw = NULL;
@@ -115,7 +112,7 @@
 	return ret;
 }
 
-static int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
+int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx,
 			       int *pos)
 {
 	u8 *b = (u8 *) &fw->data[*pos];
@@ -146,3 +143,4 @@
 
 	return *pos;
 }
+EXPORT_SYMBOL(dvb_usb_get_hexline);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 6b611a7..55ba020 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -1,6 +1,6 @@
 /* dvb-usb-i2c.c is part of the DVB USB library.
  *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  * see dvb-usb-init.c for copyright information.
  *
  * This file contains functions for (de-)initializing an I2C adapter.
@@ -48,48 +48,48 @@
 
 int dvb_usb_tuner_init_i2c(struct dvb_frontend *fe)
 {
-	struct dvb_usb_device *d = fe->dvb->priv;
-	struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct i2c_msg msg = { .addr = adap->pll_addr, .flags = 0, .buf = adap->pll_init, .len = 4 };
 	int ret = 0;
 
 	/* if pll_desc is not used */
-	if (d->pll_desc == NULL)
+	if (adap->pll_desc == NULL)
 		return 0;
 
-	if (d->tuner_pass_ctrl)
-		d->tuner_pass_ctrl(fe,1,d->pll_addr);
+	if (adap->tuner_pass_ctrl)
+		adap->tuner_pass_ctrl(fe, 1, adap->pll_addr);
 
-	deb_pll("pll init: %x\n",d->pll_addr);
-	deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
-			d->pll_init[2],d->pll_init[3]);
+	deb_pll("pll init: %x\n",adap->pll_addr);
+	deb_pll("pll-buf: %x %x %x %x\n",adap->pll_init[0], adap->pll_init[1],
+			adap->pll_init[2], adap->pll_init[3]);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
+	if (i2c_transfer (&adap->dev->i2c_adap, &msg, 1) != 1) {
 		err("tuner i2c write failed for pll_init.");
 		ret = -EREMOTEIO;
 	}
 	msleep(1);
 
-	if (d->tuner_pass_ctrl)
-		d->tuner_pass_ctrl(fe,0,d->pll_addr);
+	if (adap->tuner_pass_ctrl)
+		adap->tuner_pass_ctrl(fe,0,adap->pll_addr);
 	return ret;
 }
 EXPORT_SYMBOL(dvb_usb_tuner_init_i2c);
 
 int dvb_usb_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 *b, int buf_len)
 {
-	struct dvb_usb_device *d = fe->dvb->priv;
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
 
 	if (buf_len != 5)
 		return -EINVAL;
-	if (d->pll_desc == NULL)
+	if (adap->pll_desc == NULL)
 		return 0;
 
-	deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
+	deb_pll("pll addr: %x, freq: %d %p\n",adap->pll_addr, fep->frequency, adap->pll_desc);
 
-	b[0] = d->pll_addr;
-	dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
+	b[0] = adap->pll_addr;
+	dvb_pll_configure(adap->pll_desc, &b[1], fep->frequency, fep->u.ofdm.bandwidth);
 
 	deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
 
@@ -99,26 +99,27 @@
 
 int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
-	struct dvb_usb_device *d = fe->dvb->priv;
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
 	int ret = 0;
 	u8 b[5];
-	struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
+	struct i2c_msg msg = { .addr = adap->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
 
 	dvb_usb_tuner_calc_regs(fe,fep,b,5);
 
-	if (d->tuner_pass_ctrl)
-		d->tuner_pass_ctrl(fe,1,d->pll_addr);
+	if (adap->tuner_pass_ctrl)
+		adap->tuner_pass_ctrl(fe, 1, adap->pll_addr);
 
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
-	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
+
+	if (i2c_transfer(&adap->dev->i2c_adap, &msg, 1) != 1) {
 		err("tuner i2c write failed for pll_set.");
 		ret = -EREMOTEIO;
 	}
 	msleep(1);
 
-	if (d->tuner_pass_ctrl)
-		d->tuner_pass_ctrl(fe,0,d->pll_addr);
+	if (adap->tuner_pass_ctrl)
+		adap->tuner_pass_ctrl(fe, 0, adap->pll_addr);
 
 	return ret;
 }
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index 57a10de..4d6b069 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -52,8 +52,7 @@
 #define USB_PID_DIBCOM_MOD3000_WARM			0x0bb9
 #define USB_PID_DIBCOM_MOD3001_COLD			0x0bc6
 #define USB_PID_DIBCOM_MOD3001_WARM			0x0bc7
-#define USB_PID_DIBCOM_STK7700				0x1e14
-#define USB_PID_DIBCOM_STK7700_REENUM			0x1e15
+#define USB_PID_DIBCOM_STK7700P				0x1e14
 #define USB_PID_DIBCOM_ANCHOR_2135_COLD			0x2131
 #define USB_PID_GRANDTEC_DVBT_USB_COLD			0x0fa0
 #define USB_PID_GRANDTEC_DVBT_USB_WARM			0x0fa1
@@ -95,6 +94,10 @@
 #define USB_PID_WT220U_ZL0353_WARM			0x022b
 #define USB_PID_WINTV_NOVA_T_USB2_COLD			0x9300
 #define USB_PID_WINTV_NOVA_T_USB2_WARM			0x9301
+#define USB_PID_HAUPPAUGE_NOVA_T_500			0x9941
+#define USB_PID_HAUPPAUGE_NOVA_T_500_2			0x9950
+#define USB_PID_HAUPPAUGE_NOVA_T_STICK			0x7050
+#define USB_PID_AVERMEDIA_VOLAR				0x1234
 #define USB_PID_NEBULA_DIGITV				0x0201
 #define USB_PID_DVICO_BLUEBIRD_LGDT			0xd820
 #define USB_PID_DVICO_BLUEBIRD_LG064F_COLD		0xd500
@@ -103,10 +106,12 @@
 #define USB_PID_DVICO_BLUEBIRD_LGZ201_WARM		0xdb01
 #define USB_PID_DVICO_BLUEBIRD_TH7579_COLD		0xdb10
 #define USB_PID_DVICO_BLUEBIRD_TH7579_WARM		0xdb11
-#define USB_PID_DVICO_BLUEBIRD_DEE1601_COLD		0xdb50
-#define USB_PID_DVICO_BLUEBIRD_DEE1601_WARM		0xdb51
-#define USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_COLD	0xdb54
-#define USB_PID_DIGITALNOW_BLUEBIRD_DEE1601_WARM	0xdb55
+#define USB_PID_DVICO_BLUEBIRD_DUAL_1_COLD		0xdb50
+#define USB_PID_DVICO_BLUEBIRD_DUAL_1_WARM		0xdb51
+#define USB_PID_DVICO_BLUEBIRD_DUAL_2_COLD		0xdb58
+#define USB_PID_DVICO_BLUEBIRD_DUAL_2_WARM		0xdb59
+#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_COLD	0xdb54
+#define USB_PID_DIGITALNOW_BLUEBIRD_DUAL_1_WARM	0xdb55
 #define USB_PID_MEDION_MD95700				0x0932
 #define USB_PID_KYE_DVB_T_COLD				0x701e
 #define USB_PID_KYE_DVB_T_WARM				0x701f
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
index a1705ec..ffdde83 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -3,7 +3,7 @@
  *
  * dvb-usb-init.c
  *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  *
  *	This program is free software; you can redistribute it and/or modify it
  *	under the terms of the GNU General Public License as published by the Free
@@ -16,21 +16,105 @@
 /* debug */
 int dvb_usb_debug;
 module_param_named(debug,dvb_usb_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64,mem=128,uxfer=256  (or-able))." DVB_USB_DEBUG_STATUS);
 
 int dvb_usb_disable_rc_polling;
 module_param_named(disable_rc_polling, dvb_usb_disable_rc_polling, int, 0644);
 MODULE_PARM_DESC(disable_rc_polling, "disable remote control polling (default: 0).");
 
+static int dvb_usb_force_pid_filter_usage;
+module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage, int, 0444);
+MODULE_PARM_DESC(disable_rc_polling, "force all dvb-usb-devices to use a PID filter, if any (default: 0).");
+
+static int dvb_usb_adapter_init(struct dvb_usb_device *d)
+{
+	struct dvb_usb_adapter *adap;
+	int ret,n;
+
+	for (n = 0; n < d->props.num_adapters; n++) {
+		adap = &d->adapter[n];
+		adap->dev = d;
+		adap->id  = n;
+
+		memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
+
+/* speed - when running at FULL speed we need a HW PID filter */
+		if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
+			err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
+			return -ENODEV;
+		}
+
+		if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
+			(adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
+			info("will use the device's hardware PID filter (table count: %d).",adap->props.pid_filter_count);
+			adap->pid_filtering  = 1;
+			adap->max_feed_count = adap->props.pid_filter_count;
+		} else {
+			info("will pass the complete MPEG2 transport stream to the software demuxer.");
+			adap->pid_filtering  = 0;
+			adap->max_feed_count = 255;
+		}
+
+		if (!adap->pid_filtering &&
+			dvb_usb_force_pid_filter_usage &&
+			adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) {
+			info("pid filter enabled by module option.");
+			adap->pid_filtering  = 1;
+			adap->max_feed_count = adap->props.pid_filter_count;
+		}
+
+		if (adap->props.size_of_priv > 0) {
+			adap->priv = kzalloc(adap->props.size_of_priv,GFP_KERNEL);
+			if (adap->priv == NULL) {
+				err("no memory for priv for adapter %d.",n);
+				return -ENOMEM;
+			}
+		}
+
+		if ((ret = dvb_usb_adapter_stream_init(adap)) ||
+			(ret = dvb_usb_adapter_dvb_init(adap)) ||
+			(ret = dvb_usb_adapter_frontend_init(adap))) {
+			return ret;
+		}
+
+		d->num_adapters_initialized++;
+		d->state |= DVB_USB_STATE_DVB;
+	}
+
+	/*
+	 * when reloading the driver w/o replugging the device
+	 * sometimes a timeout occures, this helps
+	 */
+	if (d->props.generic_bulk_ctrl_endpoint != 0) {
+		usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
+		usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
+	}
+
+	return 0;
+}
+
+static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
+{
+	int n;
+	for (n = 0; n < d->num_adapters_initialized; n++) {
+		dvb_usb_adapter_frontend_exit(&d->adapter[n]);
+		dvb_usb_adapter_dvb_exit(&d->adapter[n]);
+		dvb_usb_adapter_stream_exit(&d->adapter[n]);
+		kfree(d->adapter[n].priv);
+	}
+	d->num_adapters_initialized = 0;
+	d->state &= ~DVB_USB_STATE_DVB;
+	return 0;
+}
+
+
 /* general initialization functions */
 static int dvb_usb_exit(struct dvb_usb_device *d)
 {
 	deb_info("state before exiting everything: %x\n",d->state);
 	dvb_usb_remote_exit(d);
-	dvb_usb_fe_exit(d);
+	dvb_usb_adapter_exit(d);
 	dvb_usb_i2c_exit(d);
-	dvb_usb_dvb_exit(d);
-	dvb_usb_urb_exit(d);
 	deb_info("state should be zero now: %x\n",d->state);
 	d->state = DVB_USB_STATE_INIT;
 	kfree(d->priv);
@@ -47,32 +131,19 @@
 
 	d->state = DVB_USB_STATE_INIT;
 
+	if (d->props.size_of_priv > 0) {
+		d->priv = kzalloc(d->props.size_of_priv,GFP_KERNEL);
+		if (d->priv == NULL) {
+			err("no memory for priv in 'struct dvb_usb_device'");
+			return -ENOMEM;
+		}
+	}
+
 /* check the capabilities and set appropriate variables */
+	dvb_usb_device_power_ctrl(d, 1);
 
-/* speed - when running at FULL speed we need a HW PID filter */
-	if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) {
-		err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
-		return -ENODEV;
-	}
-
-	if ((d->udev->speed == USB_SPEED_FULL && d->props.caps & DVB_USB_HAS_PID_FILTER) ||
-		(d->props.caps & DVB_USB_NEED_PID_FILTERING)) {
-		info("will use the device's hardware PID filter (table count: %d).",d->props.pid_filter_count);
-		d->pid_filtering = 1;
-		d->max_feed_count = d->props.pid_filter_count;
-	} else {
-		info("will pass the complete MPEG2 transport stream to the software demuxer.");
-		d->pid_filtering = 0;
-		d->max_feed_count = 255;
-	}
-
-	if (d->props.power_ctrl)
-		d->props.power_ctrl(d,1);
-
-	if ((ret = dvb_usb_urb_init(d)) ||
-		(ret = dvb_usb_dvb_init(d)) ||
-		(ret = dvb_usb_i2c_init(d)) ||
-		(ret = dvb_usb_fe_init(d))) {
+	if ((ret = dvb_usb_i2c_init(d)) ||
+		(ret = dvb_usb_adapter_init(d))) {
 		dvb_usb_exit(d);
 		return ret;
 	}
@@ -80,14 +151,13 @@
 	if ((ret = dvb_usb_remote_init(d)))
 		err("could not initialize remote control.");
 
-	if (d->props.power_ctrl)
-		d->props.power_ctrl(d,0);
+	dvb_usb_device_power_ctrl(d, 0);
 
 	return 0;
 }
 
 /* determine the name and the state of the just found USB device */
-static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_properties *props, int *cold)
+static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_device_properties *props, int *cold)
 {
 	int i,j;
 	struct dvb_usb_device_description *desc = NULL;
@@ -125,11 +195,25 @@
 	return desc;
 }
 
+int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	if (onoff)
+		d->powered++;
+	else
+		d->powered--;
+
+	if (d->powered == 0 || (onoff && d->powered == 1)) { // when switching from 1 to 0 or from 0 to 1
+		deb_info("power control: %d\n", onoff);
+		if (d->props.power_ctrl)
+			return d->props.power_ctrl(d, onoff);
+	}
+	return 0;
+}
+
 /*
  * USB
  */
-
-int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties
+int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_device_properties
 		*props, struct module *owner,struct dvb_usb_device **du)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
@@ -149,7 +233,7 @@
 	if (cold) {
 		info("found a '%s' in cold state, will try to load a firmware",desc->name);
 		ret = dvb_usb_download_firmware(udev,props);
-		if (!props->no_reconnect)
+		if (!props->no_reconnect || ret != 0)
 			return ret;
 	}
 
@@ -161,19 +245,10 @@
 	}
 
 	d->udev = udev;
-	memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
+	memcpy(&d->props,props,sizeof(struct dvb_usb_device_properties));
 	d->desc = desc;
 	d->owner = owner;
 
-	if (d->props.size_of_priv > 0) {
-			d->priv = kzalloc(d->props.size_of_priv,GFP_KERNEL);
-		if (d->priv == NULL) {
-			err("no memory for priv in 'struct dvb_usb_device'");
-			kfree(d);
-			return -ENOMEM;
-		}
-	}
-
 	usb_set_intfdata(intf, d);
 
 	if (du != NULL)
@@ -204,7 +279,7 @@
 }
 EXPORT_SYMBOL(dvb_usb_device_exit);
 
-MODULE_VERSION("0.3");
+MODULE_VERSION("1.0");
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
 MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index 380b2a4..0a3a0b6 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -1,6 +1,6 @@
 /* dvb-usb-remote.c is part of the DVB USB library.
  *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  * see dvb-usb-init.c for copyright information.
  *
  * This file contains functions for initializing the the input-device and for handling remote-control-queries.
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
index 88b2837..5cef12a 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -1,9 +1,9 @@
 /* dvb-usb-urb.c is part of the DVB USB library.
  *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  * see dvb-usb-init.c for copyright information.
  *
- * This file contains functions for initializing and handling the
+ * This file keeps functions for initializing and handling the
  * USB and URB stuff.
  */
 #include "dvb-usb-common.h"
@@ -64,260 +64,32 @@
 }
 EXPORT_SYMBOL(dvb_usb_generic_write);
 
-
-/* URB stuff for streaming */
-static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buffer, size_t length)
 {
-	struct dvb_usb_device *d = urb->context;
-	int ptype = usb_pipetype(urb->pipe);
-	int i;
-	u8 *b;
-
-	deb_ts("'%s' urb completed. feedcount: %d, status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
-			ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk", d->feedcount,
-			urb->status,urb->actual_length,urb->transfer_buffer_length,
-			urb->number_of_packets,urb->error_count);
-
-	switch (urb->status) {
-		case 0:         /* success */
-			break;
-		case -ECONNRESET:   /* kill */
-		case -ENOENT:
-		case -ESHUTDOWN:
-			return;
-		default:        /* error */
-			deb_ts("urb completition error %d.", urb->status);
-			break;
-	}
-
-	if (d->feedcount > 0) {
-		if (d->state & DVB_USB_STATE_DVB) {
-			switch (ptype) {
-				case PIPE_ISOCHRONOUS:
-					b = (u8 *) urb->transfer_buffer;
-					for (i = 0; i < urb->number_of_packets; i++) {
-						if (urb->iso_frame_desc[i].status != 0)
-							deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status);
-						else if (urb->iso_frame_desc[i].actual_length > 0) {
-								dvb_dmx_swfilter(&d->demux,b + urb->iso_frame_desc[i].offset,
-										urb->iso_frame_desc[i].actual_length);
-							}
-						urb->iso_frame_desc[i].status = 0;
-						urb->iso_frame_desc[i].actual_length = 0;
-					}
-					debug_dump(b,20,deb_ts);
-					break;
-				case PIPE_BULK:
-					if (urb->actual_length > 0)
-						dvb_dmx_swfilter(&d->demux, (u8 *) urb->transfer_buffer,urb->actual_length);
-					break;
-				default:
-					err("unkown endpoint type in completition handler.");
-					return;
-			}
-		}
-	}
-
-	usb_submit_urb(urb,GFP_ATOMIC);
+	struct dvb_usb_adapter *adap = stream->user_priv;
+	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
+		dvb_dmx_swfilter(&adap->demux, buffer, length);
 }
 
-int dvb_usb_urb_kill(struct dvb_usb_device *d)
+static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buffer, size_t length)
 {
-	int i;
-	for (i = 0; i < d->urbs_submitted; i++) {
-		deb_ts("killing URB no. %d.\n",i);
-
-		/* stop the URB */
-		usb_kill_urb(d->urb_list[i]);
-	}
-	d->urbs_submitted = 0;
-	return 0;
+	struct dvb_usb_adapter *adap = stream->user_priv;
+	if (adap->feedcount > 0 && adap->state & DVB_USB_ADAP_STATE_DVB)
+		dvb_dmx_swfilter_204(&adap->demux, buffer, length);
 }
 
-int dvb_usb_urb_submit(struct dvb_usb_device *d)
+int dvb_usb_adapter_stream_init(struct dvb_usb_adapter *adap)
 {
-	int i,ret;
-	for (i = 0; i < d->urbs_initialized; i++) {
-		deb_ts("submitting URB no. %d\n",i);
-		if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) {
-			err("could not submit URB no. %d - get them all back",i);
-			dvb_usb_urb_kill(d);
-			return ret;
-		}
-		d->urbs_submitted++;
-	}
-	return 0;
+	adap->stream.udev      = adap->dev->udev;
+	if (adap->props.caps & DVB_USB_ADAP_RECEIVES_204_BYTE_TS)
+		adap->stream.complete = dvb_usb_data_complete_204;
+	else
+	adap->stream.complete  = dvb_usb_data_complete;
+	adap->stream.user_priv = adap;
+	return usb_urb_init(&adap->stream, &adap->props.stream);
 }
 
-static int dvb_usb_free_stream_buffers(struct dvb_usb_device *d)
+int dvb_usb_adapter_stream_exit(struct dvb_usb_adapter *adap)
 {
-	if (d->state & DVB_USB_STATE_URB_BUF) {
-		while (d->buf_num) {
-			d->buf_num--;
-			deb_mem("freeing buffer %d\n",d->buf_num);
-			usb_buffer_free(d->udev, d->buf_size,
-					d->buf_list[d->buf_num], d->dma_addr[d->buf_num]);
-		}
-		kfree(d->buf_list);
-		kfree(d->dma_addr);
-	}
-
-	d->state &= ~DVB_USB_STATE_URB_BUF;
-
-	return 0;
-}
-
-static int dvb_usb_allocate_stream_buffers(struct dvb_usb_device *d, int num, unsigned long size)
-{
-	d->buf_num = 0;
-	d->buf_size = size;
-
-	deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
-
-	if ((d->buf_list = kcalloc(num, sizeof(u8 *), GFP_ATOMIC)) == NULL)
-		return -ENOMEM;
-
-	if ((d->dma_addr = kcalloc(num, sizeof(dma_addr_t), GFP_ATOMIC)) == NULL) {
-		kfree(d->buf_list);
-		return -ENOMEM;
-	}
-
-	d->state |= DVB_USB_STATE_URB_BUF;
-
-	for (d->buf_num = 0; d->buf_num < num; d->buf_num++) {
-		deb_mem("allocating buffer %d\n",d->buf_num);
-		if (( d->buf_list[d->buf_num] =
-					usb_buffer_alloc(d->udev, size, SLAB_ATOMIC,
-					&d->dma_addr[d->buf_num]) ) == NULL) {
-			deb_mem("not enough memory for urb-buffer allocation.\n");
-			dvb_usb_free_stream_buffers(d);
-			return -ENOMEM;
-		}
-		deb_mem("buffer %d: %p (dma: %llu)\n",
-			d->buf_num, d->buf_list[d->buf_num],
-			(unsigned long long)d->dma_addr[d->buf_num]);
-		memset(d->buf_list[d->buf_num],0,size);
-	}
-	deb_mem("allocation successful\n");
-
-	return 0;
-}
-
-static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
-{
-	int i;
-
-	if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
-					d->props.urb.u.bulk.buffersize)) < 0)
-		return i;
-
-	/* allocate the URBs */
-	for (i = 0; i < d->props.urb.count; i++) {
-		if ((d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL)
-			return -ENOMEM;
-
-		usb_fill_bulk_urb( d->urb_list[i], d->udev,
-				usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
-				d->buf_list[i],
-				d->props.urb.u.bulk.buffersize,
-				dvb_usb_urb_complete, d);
-
-		d->urb_list[i]->transfer_flags = 0;
-		d->urbs_initialized++;
-	}
-	return 0;
-}
-
-static int dvb_usb_isoc_urb_init(struct dvb_usb_device *d)
-{
-	int i,j;
-
-	if ((i = dvb_usb_allocate_stream_buffers(d,d->props.urb.count,
-					d->props.urb.u.isoc.framesize*d->props.urb.u.isoc.framesperurb)) < 0)
-		return i;
-
-	/* allocate the URBs */
-	for (i = 0; i < d->props.urb.count; i++) {
-		struct urb *urb;
-		int frame_offset = 0;
-		if ((d->urb_list[i] =
-					usb_alloc_urb(d->props.urb.u.isoc.framesperurb,GFP_ATOMIC)) == NULL)
-			return -ENOMEM;
-
-		urb = d->urb_list[i];
-
-		urb->dev = d->udev;
-		urb->context = d;
-		urb->complete = dvb_usb_urb_complete;
-		urb->pipe = usb_rcvisocpipe(d->udev,d->props.urb.endpoint);
-		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-		urb->interval = d->props.urb.u.isoc.interval;
-		urb->number_of_packets = d->props.urb.u.isoc.framesperurb;
-		urb->transfer_buffer_length = d->buf_size;
-		urb->transfer_buffer = d->buf_list[i];
-		urb->transfer_dma = d->dma_addr[i];
-
-		for (j = 0; j < d->props.urb.u.isoc.framesperurb; j++) {
-			urb->iso_frame_desc[j].offset = frame_offset;
-			urb->iso_frame_desc[j].length = d->props.urb.u.isoc.framesize;
-			frame_offset += d->props.urb.u.isoc.framesize;
-		}
-
-		d->urbs_initialized++;
-	}
-	return 0;
-
-}
-
-int dvb_usb_urb_init(struct dvb_usb_device *d)
-{
-	/*
-	 * when reloading the driver w/o replugging the device
-	 * sometimes a timeout occures, this helps
-	 */
-	if (d->props.generic_bulk_ctrl_endpoint != 0) {
-		usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
-		usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
-	}
-	usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
-
-	/* allocate the array for the data transfer URBs */
-	d->urb_list = kzalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
-	if (d->urb_list == NULL)
-		return -ENOMEM;
-	d->state |= DVB_USB_STATE_URB_LIST;
-
-	switch (d->props.urb.type) {
-		case DVB_USB_BULK:
-			return dvb_usb_bulk_urb_init(d);
-		case DVB_USB_ISOC:
-			return dvb_usb_isoc_urb_init(d);
-		default:
-			err("unkown URB-type for data transfer.");
-			return -EINVAL;
-	}
-}
-
-int dvb_usb_urb_exit(struct dvb_usb_device *d)
-{
-	int i;
-
-	dvb_usb_urb_kill(d);
-
-	if (d->state & DVB_USB_STATE_URB_LIST) {
-		for (i = 0; i < d->urbs_initialized; i++) {
-			if (d->urb_list[i] != NULL) {
-				deb_mem("freeing URB no. %d.\n",i);
-				/* free the URBs */
-				usb_free_urb(d->urb_list[i]);
-			}
-		}
-		d->urbs_initialized = 0;
-		/* free the urb array */
-		kfree(d->urb_list);
-		d->state &= ~DVB_USB_STATE_URB_LIST;
-	}
-
-	dvb_usb_free_stream_buffers(d);
-	return 0;
+	return usb_urb_exit(&adap->stream);
 }
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index 97f8ea9..376c45a 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -1,9 +1,11 @@
 /* dvb-usb.h is part of the DVB USB library.
  *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
  * see dvb-usb-init.c for copyright information.
  *
  * the headerfile, all dvb-usb-drivers have to include.
+ *
+ * TODO: clean-up the structures for unused fields and update the comments
  */
 #ifndef __DVB_USB_H__
 #define __DVB_USB_H__
@@ -84,36 +86,84 @@
 };
 
 struct dvb_usb_device;
+struct dvb_usb_adapter;
+struct usb_data_stream;
 
 /**
- * struct dvb_usb_properties - properties of a dvb-usb-device
+ * Properties of USB streaming - TODO this structure should be somewhere else
+ * describes the kind of USB transfer used for data-streaming.
+ *  (BULK or ISOC)
+ */
+struct usb_data_stream_properties {
+#define USB_BULK  1
+#define USB_ISOC  2
+	int type;
+	int count;
+	int endpoint;
+
+	union {
+		struct {
+			int buffersize; /* per URB */
+		} bulk;
+		struct {
+			int framesperurb;
+			int framesize;
+			int interval;
+		} isoc;
+	} u;
+};
+
+/**
+ * struct dvb_usb_adapter_properties - properties of a dvb-usb-adapter.
+ *    A DVB-USB-Adapter is basically a dvb_adapter which is present on a USB-device.
  * @caps: capabilities of the DVB USB device.
  * @pid_filter_count: number of PID filter position in the optional hardware
  *  PID-filter.
- *
+ * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the
+ *  device (not URB submitting/killing).
+ * @pid_filter_ctrl: called to en/disable the PID filter, if any.
+ * @pid_filter: called to set/unset a PID for filtering.
+ * @frontend_attach: called to attach the possible frontends (fill fe-field
+ *  of struct dvb_usb_device).
+ * @tuner_attach: called to attach the correct tuner and to fill pll_addr,
+ *  pll_desc and pll_init_buf of struct dvb_usb_device).
+ * @stream: configuration of the USB streaming
+ */
+struct dvb_usb_adapter_properties {
+#define DVB_USB_ADAP_HAS_PID_FILTER               0x01
+#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
+#define DVB_USB_ADAP_NEED_PID_FILTERING           0x04
+#define DVB_USB_ADAP_RECEIVES_204_BYTE_TS         0x08
+	int caps;
+	int pid_filter_count;
+
+	int (*streaming_ctrl)  (struct dvb_usb_adapter *, int);
+	int (*pid_filter_ctrl) (struct dvb_usb_adapter *, int);
+	int (*pid_filter)      (struct dvb_usb_adapter *, int, u16, int);
+
+	int (*frontend_attach) (struct dvb_usb_adapter *);
+	int (*tuner_attach)    (struct dvb_usb_adapter *);
+
+	struct usb_data_stream_properties stream;
+
+	int size_of_priv;
+};
+
+/**
+ * struct dvb_usb_device_properties - properties of a dvb-usb-device
  * @usb_ctrl: which USB device-side controller is in use. Needed for firmware
  *  download.
  * @firmware: name of the firmware file.
  * @download_firmware: called to download the firmware when the usb_ctrl is
  *  DEVICE_SPECIFIC.
  * @no_reconnect: device doesn't do a reconnect after downloading the firmware,
-    so do the warm initialization right after it
-
+ *  so do the warm initialization right after it
+ *
  * @size_of_priv: how many bytes shall be allocated for the private field
  *  of struct dvb_usb_device.
  *
  * @power_ctrl: called to enable/disable power of the device.
- * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the
- *  device (not URB submitting/killing).
- * @pid_filter_ctrl: called to en/disable the PID filter, if any.
- * @pid_filter: called to set/unset a PID for filtering.
- *
  * @read_mac_address: called to read the MAC address of the device.
- *
- * @frontend_attach: called to attach the possible frontends (fill fe-field
- *  of struct dvb_usb_device).
- * @tuner_attach: called to attach the correct tuner and to fill pll_addr,
- *  pll_desc and pll_init_buf of struct dvb_usb_device).
  * @identify_state: called to determine the state (cold or warm), when it
  *  is not distinguishable by the USB IDs.
  *
@@ -130,50 +180,40 @@
  *  is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write-
  *  helper functions.
  *
- * @urb: describes the kind of USB transfer used for MPEG2-TS-streaming.
- *  (BULK or ISOC)
- *
  * @num_device_descs: number of struct dvb_usb_device_description in @devices
  * @devices: array of struct dvb_usb_device_description compatibles with these
  *  properties.
  */
-struct dvb_usb_properties {
+#define MAX_NO_OF_ADAPTER_PER_DEVICE 2
+struct dvb_usb_device_properties {
 
-#define DVB_USB_HAS_PID_FILTER               0x01
-#define DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF 0x02
-#define DVB_USB_NEED_PID_FILTERING           0x04
-#define DVB_USB_IS_AN_I2C_ADAPTER            0x08
+#define DVB_USB_IS_AN_I2C_ADAPTER            0x01
 	int caps;
-	int pid_filter_count;
 
 #define DEVICE_SPECIFIC 0
 #define CYPRESS_AN2135  1
 #define CYPRESS_AN2235  2
 #define CYPRESS_FX2     3
-	int usb_ctrl;
+	int        usb_ctrl;
+	int        (*download_firmware) (struct usb_device *, const struct firmware *);
 	const char firmware[FIRMWARE_NAME_MAX];
-	int (*download_firmware) (struct usb_device *, const struct firmware *);
-	int no_reconnect;
+	int        no_reconnect;
 
 	int size_of_priv;
 
-	int (*power_ctrl) (struct dvb_usb_device *, int);
-	int (*streaming_ctrl) (struct dvb_usb_device *, int);
-	int (*pid_filter_ctrl) (struct dvb_usb_device *, int);
-	int (*pid_filter) (struct dvb_usb_device *, int, u16, int);
+	int num_adapters;
+	struct dvb_usb_adapter_properties adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
 
+	int (*power_ctrl)       (struct dvb_usb_device *, int);
 	int (*read_mac_address) (struct dvb_usb_device *, u8 []);
-	int (*frontend_attach) (struct dvb_usb_device *);
-	int (*tuner_attach) (struct dvb_usb_device *);
-
-	int (*identify_state) (struct usb_device *, struct dvb_usb_properties *,
+	int (*identify_state)   (struct usb_device *, struct dvb_usb_device_properties *,
 			struct dvb_usb_device_description **, int *);
 
 /* remote control properties */
 #define REMOTE_NO_KEY_PRESSED      0x00
 #define REMOTE_KEY_PRESSED         0x01
 #define REMOTE_KEY_REPEAT          0x02
-	struct dvb_usb_rc_key *rc_key_map;
+	struct dvb_usb_rc_key  *rc_key_map;
 	int rc_key_map_size;
 	int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
 	int rc_interval;
@@ -182,40 +222,12 @@
 
 	int generic_bulk_ctrl_endpoint;
 
-	struct {
-#define DVB_USB_BULK  1
-#define DVB_USB_ISOC  2
-		int type;
-		int count;
-		int endpoint;
-
-		union {
-			struct {
-				int buffersize; /* per URB */
-			} bulk;
-			struct {
-				int framesperurb;
-				int framesize;
-				int interval;
-			} isoc;
-		} u;
-	} urb;
-
 	int num_device_descs;
 	struct dvb_usb_device_description devices[9];
 };
 
-
 /**
- * struct dvb_usb_device - object of a DVB USB device
- * @props: copy of the struct dvb_usb_properties this device belongs to.
- * @desc: pointer to the device's struct dvb_usb_device_description.
- * @state: initialization and runtime state of the device.
- *
- * @udev: pointer to the device's struct usb_device.
- * @urb_list: array of dynamically allocated struct urb for the MPEG2-TS-
- *  streaming.
- *
+ * struct usb_data_stream - generic object of an USB stream
  * @buf_num: number of buffer allocated.
  * @buf_size: size of each buffer in buf_list.
  * @buf_list: array containing all allocate buffers for streaming.
@@ -223,18 +235,40 @@
  *
  * @urbs_initialized: number of URBs initialized.
  * @urbs_submitted: number of URBs submitted.
+ */
+#define MAX_NO_URBS_FOR_DATA_STREAM 10
+struct usb_data_stream {
+	struct usb_device                 *udev;
+	struct usb_data_stream_properties  props;
+
+#define USB_STATE_INIT    0x00
+#define USB_STATE_URB_BUF 0x01
+	int state;
+
+	void (*complete) (struct usb_data_stream *, u8 *, size_t);
+
+	struct urb    *urb_list[MAX_NO_URBS_FOR_DATA_STREAM];
+	int            buf_num;
+	unsigned long  buf_size;
+	u8            *buf_list[MAX_NO_URBS_FOR_DATA_STREAM];
+	dma_addr_t     dma_addr[MAX_NO_URBS_FOR_DATA_STREAM];
+
+	int urbs_initialized;
+	int urbs_submitted;
+
+	void *user_priv;
+};
+
+/**
+ * struct dvb_usb_adapter - a DVB adapter on a USB device
+ * @id: index of this adapter (starting with 0).
  *
  * @feedcount: number of reqested feeds (used for streaming-activation)
  * @pid_filtering: is hardware pid_filtering used or not.
  *
- * @usb_mutex: semaphore of USB control messages (reading needs two messages)
- * @i2c_mutex: semaphore for i2c-transfers
- *
- * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
  * @pll_addr: I2C address of the tuner for programming
  * @pll_init: array containing the initialization buffer
  * @pll_desc: pointer to the appropriate struct dvb_pll_desc
- *
  * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod or the board
  *
  * @dvb_adap: device's dvb_adapter.
@@ -244,8 +278,62 @@
  * @dvb_frontend: device's frontend.
  * @max_feed_count: how many feeds can be handled simultaneously by this
  *  device
+ *
+ * @fe_init:  rerouted frontend-init (wakeup) function.
  * @fe_sleep: rerouted frontend-sleep function.
- * @fe_init: rerouted frontend-init (wakeup) function.
+ *
+ * @stream: the usb data stream.
+ */
+struct dvb_usb_adapter {
+	struct dvb_usb_device *dev;
+	struct dvb_usb_adapter_properties props;
+
+#define DVB_USB_ADAP_STATE_INIT 0x000
+#define DVB_USB_ADAP_STATE_DVB  0x001
+	int state;
+
+	u8  id;
+
+	int feedcount;
+	int pid_filtering;
+
+	/* tuner programming information */
+	u8 pll_addr;
+	u8 pll_init[4];
+	struct dvb_pll_desc *pll_desc;
+	int (*tuner_pass_ctrl) (struct dvb_frontend *, int, u8);
+
+	/* dvb */
+	struct dvb_adapter   dvb_adap;
+	struct dmxdev        dmxdev;
+	struct dvb_demux     demux;
+	struct dvb_net       dvb_net;
+	struct dvb_frontend *fe;
+	int                  max_feed_count;
+
+	int (*fe_init)  (struct dvb_frontend *);
+	int (*fe_sleep) (struct dvb_frontend *);
+
+	struct usb_data_stream stream;
+
+	void *priv;
+};
+
+/**
+ * struct dvb_usb_device - object of a DVB USB device
+ * @props: copy of the struct dvb_usb_properties this device belongs to.
+ * @desc: pointer to the device's struct dvb_usb_device_description.
+ * @state: initialization and runtime state of the device.
+ *
+ * @powered: indicated whether the device is power or not.
+ *  Powered is in/decremented for each call to modify the state.
+ * @udev: pointer to the device's struct usb_device.
+ *
+ * @usb_mutex: semaphore of USB control messages (reading needs two messages)
+ * @i2c_mutex: semaphore for i2c-transfers
+ *
+ * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
+ *
  * @rc_input_dev: input device for the remote control.
  * @rc_query_work: struct work_struct frequent rc queries
  * @last_event: last triggered event
@@ -255,32 +343,18 @@
  *  in size_of_priv of dvb_usb_properties).
  */
 struct dvb_usb_device {
-	struct dvb_usb_properties props;
+	struct dvb_usb_device_properties props;
 	struct dvb_usb_device_description *desc;
 
+	struct usb_device *udev;
+
 #define DVB_USB_STATE_INIT        0x000
-#define DVB_USB_STATE_URB_LIST    0x001
-#define DVB_USB_STATE_URB_BUF     0x002
-#define DVB_USB_STATE_DVB         0x004
-#define DVB_USB_STATE_I2C         0x008
-#define DVB_USB_STATE_REMOTE      0x010
-#define DVB_USB_STATE_URB_SUBMIT  0x020
+#define DVB_USB_STATE_I2C         0x001
+#define DVB_USB_STATE_DVB         0x002
+#define DVB_USB_STATE_REMOTE      0x004
 	int state;
 
-	/* usb */
-	struct usb_device *udev;
-	struct urb **urb_list;
-
-	int buf_num;
-	unsigned long buf_size;
-	u8 **buf_list;
-	dma_addr_t *dma_addr;
-
-	int urbs_initialized;
-	int urbs_submitted;
-
-	int feedcount;
-	int pid_filtering;
+	int powered;
 
 	/* locking */
 	struct mutex usb_mutex;
@@ -289,22 +363,8 @@
 	struct mutex i2c_mutex;
 	struct i2c_adapter i2c_adap;
 
-	/* tuner programming information */
-	u8 pll_addr;
-	u8 pll_init[4];
-	struct dvb_pll_desc *pll_desc;
-	int (*tuner_pass_ctrl)(struct dvb_frontend *, int, u8);
-
-	/* dvb */
-	struct dvb_adapter dvb_adap;
-	struct dmxdev dmxdev;
-	struct dvb_demux demux;
-	struct dvb_net dvb_net;
-	struct dvb_frontend* fe;
-	int max_feed_count;
-
-	int (*fe_sleep) (struct dvb_frontend *);
-	int (*fe_init)  (struct dvb_frontend *);
+	int                    num_adapters_initialized;
+	struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
 
 	/* remote control */
 	struct input_dev *rc_input_dev;
@@ -318,7 +378,7 @@
 	void *priv;
 };
 
-extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *, struct dvb_usb_device **);
+extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_device_properties *, struct module *, struct dvb_usb_device **);
 extern void dvb_usb_device_exit(struct usb_interface *);
 
 /* the generic read/write method for device control */
@@ -342,5 +402,7 @@
 	u8 chk;
 };
 extern int usb_cypress_load_firmware(struct usb_device *udev, const struct firmware *fw, int type);
+extern int dvb_usb_get_hexline(const struct firmware *fw, struct hexline *hx, int *pos);
+
 
 #endif
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
index 9a98f3f..7375eb2 100644
--- a/drivers/media/dvb/dvb-usb/gp8psk.c
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -161,19 +161,18 @@
 }
 
 
-static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+static int gp8psk_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-	return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0);
+	return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0);
 }
 
-static int gp8psk_frontend_attach(struct dvb_usb_device *d)
+static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	d->fe = gp8psk_fe_attach(d);
-
+	adap->fe = gp8psk_fe_attach(adap->dev);
 	return 0;
 }
 
-static struct dvb_usb_properties gp8psk_properties;
+static struct dvb_usb_device_properties gp8psk_properties;
 
 static int gp8psk_usb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -188,20 +187,18 @@
 };
 MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
 
-static struct dvb_usb_properties gp8psk_properties = {
-	.caps = 0,
-
+static struct dvb_usb_device_properties gp8psk_properties = {
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-gp8psk-01.fw",
 
+	.num_adapters = 1,
+	.adapter = {
+		{
 	.streaming_ctrl   = gp8psk_streaming_ctrl,
-	.power_ctrl       = gp8psk_power_ctrl,
 	.frontend_attach  = gp8psk_frontend_attach,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
+			.stream = {
+				.type = USB_BULK,
 		.count = 7,
 		.endpoint = 0x82,
 		.u = {
@@ -210,6 +207,11 @@
 			}
 		}
 	},
+		}
+	},
+	.power_ctrl       = gp8psk_power_ctrl,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
 
 	.num_device_descs = 1,
 	.devices = {
@@ -217,7 +219,7 @@
 		  .cold_ids = { &gp8psk_usb_table[0], NULL },
 		  .warm_ids = { &gp8psk_usb_table[1], NULL },
 		},
-		{ 0 },
+		{ NULL },
 	}
 };
 
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
index 79f0a02..a9219bf 100644
--- a/drivers/media/dvb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -135,7 +135,7 @@
 }
 
 /* USB Driver stuff */
-static struct dvb_usb_properties nova_t_properties;
+static struct dvb_usb_device_properties nova_t_properties;
 
 static int nova_t_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -151,21 +151,41 @@
 };
 MODULE_DEVICE_TABLE(usb, nova_t_table);
 
-static struct dvb_usb_properties nova_t_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
-	.pid_filter_count = 32,
+static struct dvb_usb_device_properties nova_t_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-nova-t-usb2-02.fw",
 
-	.size_of_priv     = sizeof(struct dibusb_state),
+	.num_adapters     = 1,
+	.adapter          = {
+		{
+			.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+			.pid_filter_count = 32,
 
 	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
 	.pid_filter       = dibusb_pid_filter,
 	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
-	.power_ctrl       = dibusb2_0_power_ctrl,
 	.frontend_attach  = dibusb_dib3000mc_frontend_attach,
 	.tuner_attach     = dibusb_dib3000mc_tuner_attach,
+
+	/* parameter for the MPEG2-data transfer */
+			.stream = {
+				.type = USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+			.size_of_priv     = sizeof(struct dibusb_state),
+		}
+	},
+
+	.power_ctrl       = dibusb2_0_power_ctrl,
 	.read_mac_address = nova_t_read_mac_address,
 
 	.rc_interval      = 100,
@@ -176,17 +196,6 @@
 	.i2c_algo         = &dibusb_i2c_algo,
 
 	.generic_bulk_ctrl_endpoint = 0x01,
-	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
-		.endpoint = 0x06,
-		.u = {
-			.bulk = {
-				.buffersize = 4096,
-			}
-		}
-	},
 
 	.num_device_descs = 1,
 	.devices = {
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 418a0b7..f9941ea 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -50,7 +50,7 @@
 	return 0;
 }
 
-static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
+static int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	struct mt352_config umt_config;
 
@@ -58,21 +58,21 @@
 	umt_config.demod_init = umt_mt352_demod_init;
 	umt_config.demod_address = 0xf;
 
-	d->fe = dvb_attach(mt352_attach, &umt_config, &d->i2c_adap);
+	adap->fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap);
 
 	return 0;
 }
 
-static int umt_tuner_attach (struct dvb_usb_device *d)
+static int umt_tuner_attach (struct dvb_usb_adapter *adap)
 {
-	d->pll_addr = 0x61;
-	d->pll_desc = &dvb_pll_tua6034;
-	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+	adap->pll_addr = 0x61;
+	adap->pll_desc = &dvb_pll_tua6034;
+	adap->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 }
 
 /* USB Driver stuff */
-static struct dvb_usb_properties umt_properties;
+static struct dvb_usb_device_properties umt_properties;
 
 static int umt_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -90,25 +90,22 @@
 };
 MODULE_DEVICE_TABLE (usb, umt_table);
 
-static struct dvb_usb_properties umt_properties = {
+static struct dvb_usb_device_properties umt_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-umt-010-02.fw",
 
-	.size_of_priv     = sizeof(struct dibusb_state),
-
+	.num_adapters = 1,
+	.adapter = {
+		{
 	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
-	.power_ctrl       = dibusb_power_ctrl,
 	.frontend_attach  = umt_mt352_frontend_attach,
 	.tuner_attach     = umt_tuner_attach,
 
-	.i2c_algo         = &dibusb_i2c_algo,
-
-	.generic_bulk_ctrl_endpoint = 0x01,
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
+			.stream = {
+				.type = USB_BULK,
 		.count = 20,
 		.endpoint = 0x06,
 		.u = {
@@ -118,6 +115,15 @@
 		}
 	},
 
+			.size_of_priv     = sizeof(struct dibusb_state),
+		}
+	},
+	.power_ctrl       = dibusb_power_ctrl,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+
 	.num_device_descs = 1,
 	.devices = {
 		{	"Hanftek UMT-010 DVB-T USB2.0",
diff --git a/drivers/media/dvb/dvb-usb/usb-urb.c b/drivers/media/dvb/dvb-usb/usb-urb.c
new file mode 100644
index 0000000..8728cf3
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/usb-urb.c
@@ -0,0 +1,242 @@
+/* usb-urb.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file keeps functions for initializing and handling the
+ * BULK and ISOC USB data transfers in a generic way.
+ * Can be used for DVB-only and also, that's the plan, for
+ * Hybrid USB devices (analog and DVB).
+ */
+#include "dvb-usb-common.h"
+
+/* URB stuff for streaming */
+static void usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+	struct usb_data_stream *stream = urb->context;
+	int ptype = usb_pipetype(urb->pipe);
+	int i;
+	u8 *b;
+
+	deb_uxfer("'%s' urb completed. status: %d, length: %d/%d, pack_num: %d, errors: %d\n",
+		ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk",
+		urb->status,urb->actual_length,urb->transfer_buffer_length,
+		urb->number_of_packets,urb->error_count);
+
+	switch (urb->status) {
+		case 0:         /* success */
+		case -ETIMEDOUT:    /* NAK */
+			break;
+		case -ECONNRESET:   /* kill */
+		case -ENOENT:
+		case -ESHUTDOWN:
+			return;
+		default:        /* error */
+			deb_ts("urb completition error %d.\n", urb->status);
+			break;
+	}
+
+	b = (u8 *) urb->transfer_buffer;
+	switch (ptype) {
+		case PIPE_ISOCHRONOUS:
+			for (i = 0; i < urb->number_of_packets; i++) {
+
+				if (urb->iso_frame_desc[i].status != 0)
+					deb_ts("iso frame descriptor has an error: %d\n",urb->iso_frame_desc[i].status);
+				else if (urb->iso_frame_desc[i].actual_length > 0)
+					stream->complete(stream, b + urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].actual_length);
+
+				urb->iso_frame_desc[i].status = 0;
+				urb->iso_frame_desc[i].actual_length = 0;
+			}
+			debug_dump(b,20,deb_uxfer);
+			break;
+		case PIPE_BULK:
+			if (urb->actual_length > 0)
+				stream->complete(stream, b, urb->actual_length);
+			break;
+		default:
+			err("unkown endpoint type in completition handler.");
+			return;
+	}
+	usb_submit_urb(urb,GFP_ATOMIC);
+}
+
+int usb_urb_kill(struct usb_data_stream *stream)
+{
+	int i;
+	for (i = 0; i < stream->urbs_submitted; i++) {
+		deb_ts("killing URB no. %d.\n",i);
+
+		/* stop the URB */
+		usb_kill_urb(stream->urb_list[i]);
+	}
+	stream->urbs_submitted = 0;
+	return 0;
+}
+
+int usb_urb_submit(struct usb_data_stream *stream)
+{
+	int i,ret;
+	for (i = 0; i < stream->urbs_initialized; i++) {
+		deb_ts("submitting URB no. %d\n",i);
+		if ((ret = usb_submit_urb(stream->urb_list[i],GFP_ATOMIC))) {
+			err("could not submit URB no. %d - get them all back",i);
+			usb_urb_kill(stream);
+			return ret;
+		}
+		stream->urbs_submitted++;
+	}
+	return 0;
+}
+
+static int usb_free_stream_buffers(struct usb_data_stream *stream)
+{
+	if (stream->state & USB_STATE_URB_BUF) {
+		while (stream->buf_num) {
+			stream->buf_num--;
+			deb_mem("freeing buffer %d\n",stream->buf_num);
+			usb_buffer_free(stream->udev, stream->buf_size,
+					stream->buf_list[stream->buf_num], stream->dma_addr[stream->buf_num]);
+		}
+	}
+
+	stream->state &= ~USB_STATE_URB_BUF;
+
+	return 0;
+}
+
+static int usb_allocate_stream_buffers(struct usb_data_stream *stream, int num, unsigned long size)
+{
+	stream->buf_num = 0;
+	stream->buf_size = size;
+
+	deb_mem("all in all I will use %lu bytes for streaming\n",num*size);
+
+	for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
+		deb_mem("allocating buffer %d\n",stream->buf_num);
+		if (( stream->buf_list[stream->buf_num] =
+					usb_buffer_alloc(stream->udev, size, SLAB_ATOMIC,
+					&stream->dma_addr[stream->buf_num]) ) == NULL) {
+			deb_mem("not enough memory for urb-buffer allocation.\n");
+			usb_free_stream_buffers(stream);
+			return -ENOMEM;
+		}
+		deb_mem("buffer %d: %p (dma: %u)\n",
+			stream->buf_num, stream->buf_list[stream->buf_num], stream->dma_addr[stream->buf_num]);
+		memset(stream->buf_list[stream->buf_num],0,size);
+		stream->state |= USB_STATE_URB_BUF;
+	}
+	deb_mem("allocation successful\n");
+
+	return 0;
+}
+
+static int usb_bulk_urb_init(struct usb_data_stream *stream)
+{
+	int i;
+
+	if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
+					stream->props.u.bulk.buffersize)) < 0)
+		return i;
+
+	/* allocate the URBs */
+	for (i = 0; i < stream->props.count; i++) {
+		if ((stream->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC)) == NULL)
+			return -ENOMEM;
+
+		usb_fill_bulk_urb( stream->urb_list[i], stream->udev,
+				usb_rcvbulkpipe(stream->udev,stream->props.endpoint),
+				stream->buf_list[i],
+				stream->props.u.bulk.buffersize,
+				usb_urb_complete, stream);
+
+		stream->urb_list[i]->transfer_flags = 0;
+		stream->urbs_initialized++;
+	}
+	return 0;
+}
+
+static int usb_isoc_urb_init(struct usb_data_stream *stream)
+{
+	int i,j;
+
+	if ((i = usb_allocate_stream_buffers(stream,stream->props.count,
+					stream->props.u.isoc.framesize*stream->props.u.isoc.framesperurb)) < 0)
+		return i;
+
+	/* allocate the URBs */
+	for (i = 0; i < stream->props.count; i++) {
+		struct urb *urb;
+		int frame_offset = 0;
+		if ((stream->urb_list[i] =
+					usb_alloc_urb(stream->props.u.isoc.framesperurb,GFP_ATOMIC)) == NULL)
+			return -ENOMEM;
+
+		urb = stream->urb_list[i];
+
+		urb->dev = stream->udev;
+		urb->context = stream;
+		urb->complete = usb_urb_complete;
+		urb->pipe = usb_rcvisocpipe(stream->udev,stream->props.endpoint);
+		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+		urb->interval = stream->props.u.isoc.interval;
+		urb->number_of_packets = stream->props.u.isoc.framesperurb;
+		urb->transfer_buffer_length = stream->buf_size;
+		urb->transfer_buffer = stream->buf_list[i];
+		urb->transfer_dma = stream->dma_addr[i];
+
+		for (j = 0; j < stream->props.u.isoc.framesperurb; j++) {
+			urb->iso_frame_desc[j].offset = frame_offset;
+			urb->iso_frame_desc[j].length = stream->props.u.isoc.framesize;
+			frame_offset += stream->props.u.isoc.framesize;
+		}
+
+		stream->urbs_initialized++;
+	}
+	return 0;
+}
+
+int usb_urb_init(struct usb_data_stream *stream, struct usb_data_stream_properties *props)
+{
+	if (stream == NULL || props == NULL)
+		return -EINVAL;
+
+	memcpy(&stream->props, props, sizeof(*props));
+
+	usb_clear_halt(stream->udev,usb_rcvbulkpipe(stream->udev,stream->props.endpoint));
+
+	if (stream->complete == NULL) {
+		err("there is no data callback - this doesn't make sense.");
+		return -EINVAL;
+	}
+
+	switch (stream->props.type) {
+		case USB_BULK:
+			return usb_bulk_urb_init(stream);
+		case USB_ISOC:
+			return usb_isoc_urb_init(stream);
+		default:
+			err("unkown URB-type for data transfer.");
+			return -EINVAL;
+	}
+}
+
+int usb_urb_exit(struct usb_data_stream *stream)
+{
+	int i;
+
+	usb_urb_kill(stream);
+
+	for (i = 0; i < stream->urbs_initialized; i++) {
+		if (stream->urb_list[i] != NULL) {
+			deb_mem("freeing URB no. %d.\n",i);
+			/* free the URBs */
+			usb_free_urb(stream->urb_list[i]);
+		}
+	}
+	stream->urbs_initialized = 0;
+
+	usb_free_stream_buffers(stream);
+	return 0;
+}
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index d4da494..3ecb2e0 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -24,6 +24,8 @@
 	struct dvb_frontend fe;
 	struct dvb_usb_device *d;
 
+	struct dvb_frontend_ops ops;
+
 	fe_sec_voltage_t voltage;
 	fe_sec_tone_mode_t tone_mode;
 
@@ -72,9 +74,6 @@
 	else
 		*status = 0;
 
-	deb_fe("real state: %x\n",*status);
-	*status = 0x1f;
-
 	if (*status & FE_HAS_LOCK)
 		st->status_check_interval = 1000;
 	else
@@ -171,8 +170,6 @@
 	st->status_check_interval = 250;
 	st->next_status_check = jiffies;
 
-	vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
-	msleep(30);
 	vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
 
 	if (ibuf[2] == 0 && ibuf[3] == 0)
@@ -183,6 +180,20 @@
 	return 0;
 }
 
+static int vp702x_fe_init(struct dvb_frontend *fe)
+{
+	struct vp702x_fe_state *st = fe->demodulator_priv;
+	deb_fe("%s\n",__FUNCTION__);
+	vp702x_usb_in_op(st->d, RESET_TUNER, 0, 0, NULL, 0);
+	return 0;
+}
+
+static int vp702x_fe_sleep(struct dvb_frontend *fe)
+{
+	deb_fe("%s\n",__FUNCTION__);
+	return 0;
+}
+
 static int vp702x_fe_get_frontend(struct dvb_frontend* fe,
 				  struct dvb_frontend_parameters *fep)
 {
@@ -193,8 +204,8 @@
 static int vp702x_fe_send_diseqc_msg (struct dvb_frontend* fe,
 				    struct dvb_diseqc_master_cmd *m)
 {
-	struct vp702x_fe_state *st = fe->demodulator_priv;
-	u8 cmd[8],ibuf[10];
+	//struct vp702x_fe_state *st = fe->demodulator_priv;
+	u8 cmd[8];//,ibuf[10];
 	memset(cmd,0,8);
 
 	deb_fe("%s\n",__FUNCTION__);
@@ -207,12 +218,12 @@
 	memcpy(&cmd[3], m->msg, m->msg_len);
 	cmd[7] = vp702x_chksum(cmd,0,7);
 
-	vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
+//	vp702x_usb_inout_op(st->d,cmd,8,ibuf,10,100);
 
-	if (ibuf[2] == 0 && ibuf[3] == 0)
-		deb_fe("diseqc cmd failed.\n");
-	else
-		deb_fe("diseqc cmd succeeded.\n");
+//	if (ibuf[2] == 0 && ibuf[3] == 0)
+//		deb_fe("diseqc cmd failed.\n");
+//	else
+//		deb_fe("diseqc cmd succeeded.\n");
 
 	return 0;
 }
@@ -318,8 +329,8 @@
 	},
 	.release = vp702x_fe_release,
 
-	.init = NULL,
-	.sleep = NULL,
+	.init  = vp702x_fe_init,
+	.sleep = vp702x_fe_sleep,
 
 	.set_frontend = vp702x_fe_set_frontend,
 	.get_frontend = vp702x_fe_get_frontend,
diff --git a/drivers/media/dvb/dvb-usb/vp702x.c b/drivers/media/dvb/dvb-usb/vp702x.c
index b2f098a..02bd61a 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.c
+++ b/drivers/media/dvb/dvb-usb/vp702x.c
@@ -22,50 +22,54 @@
 MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
 
 struct vp702x_state {
-	u8 pid_table[17]; /* [16] controls the pid_table state */
+	int pid_filter_count;
+	int pid_filter_can_bypass;
+	u8  pid_filter_state;
+};
+
+struct vp702x_device_state {
+	u8 power_state;
 };
 
 /* check for mutex FIXME */
 int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
 {
-	int ret = 0,try = 0;
+	int ret = -1;
 
-	while (ret >= 0 && ret != blen && try < 3) {
 		ret = usb_control_msg(d->udev,
 			usb_rcvctrlpipe(d->udev,0),
 			req,
 			USB_TYPE_VENDOR | USB_DIR_IN,
 			value,index,b,blen,
 			2000);
-		deb_info("reading number %d (ret: %d)\n",try,ret);
-		try++;
-	}
 
-	if (ret < 0 || ret != blen) {
-		warn("usb in operation failed.");
+	if (ret < 0) {
+		warn("usb in operation failed. (%d)", ret);
 		ret = -EIO;
 	} else
 		ret = 0;
 
-	deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+
+	deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
 	debug_dump(b,blen,deb_xfer);
 
 	return ret;
 }
 
-static int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
 			     u16 index, u8 *b, int blen)
 {
-	deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+	int ret;
+	deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ",req,value,index);
 	debug_dump(b,blen,deb_xfer);
 
-	if (usb_control_msg(d->udev,
+	if ((ret = usb_control_msg(d->udev,
 			usb_sndctrlpipe(d->udev,0),
 			req,
 			USB_TYPE_VENDOR | USB_DIR_OUT,
 			value,index,b,blen,
-			2000) != blen) {
-		warn("usb out operation failed.");
+			2000)) != blen) {
+		warn("usb out operation failed. (%d)",ret);
 		return -EIO;
 	} else
 		return 0;
@@ -78,12 +82,10 @@
 	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
 		return ret;
 
-	if ((ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen)) < 0)
-		goto unlock;
+	ret = vp702x_usb_out_op(d,REQUEST_OUT,0,0,o,olen);
 	msleep(msec);
 	ret = vp702x_usb_in_op(d,REQUEST_IN,0,0,i,ilen);
 
-unlock:
 	mutex_unlock(&d->usb_mutex);
 
 	return ret;
@@ -108,29 +110,65 @@
 	return ret;
 }
 
-static int vp702x_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+static int vp702x_set_pld_mode(struct dvb_usb_adapter *adap, u8 bypass)
 {
-	struct vp702x_state *st = d->priv;
-	u8 buf[9];
-
-	if (onoff) {
-		st->pid_table[16]   |=   1 << index;
-		st->pid_table[index*2]   = (pid >> 8) & 0xff;
-		st->pid_table[index*2+1] =  pid       & 0xff;
-	} else {
-		st->pid_table[16]   &= ~(1 << index);
-		st->pid_table[index*2] = st->pid_table[index*2+1] = 0;
-	}
-
-	return vp702x_usb_inout_cmd(d,SET_PID_FILTER,st->pid_table,17,buf,9,10);
+	u8 buf[16] = { 0 };
+	return vp702x_usb_in_op(adap->dev, 0xe0, (bypass << 8) | 0x0e, 0, buf, 16);
 }
 
-static int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff)
+static int vp702x_set_pld_state(struct dvb_usb_adapter *adap, u8 state)
 {
-	vp702x_usb_in_op(d,RESET_TUNER,0,0,NULL,0);
+	u8 buf[16] = { 0 };
+	return vp702x_usb_in_op(adap->dev, 0xe0, (state << 8) | 0x0f, 0, buf, 16);
+}
 
-	vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
-	return vp702x_usb_in_op(d,SET_TUNER_POWER_REQ,0,onoff,NULL,0);
+static int vp702x_set_pid(struct dvb_usb_adapter *adap, u16 pid, u8 id, int onoff)
+{
+	struct vp702x_state *st = adap->priv;
+	u8 buf[16] = { 0 };
+
+	if (onoff)
+		st->pid_filter_state |=  (1 << id);
+	else {
+		st->pid_filter_state &= ~(1 << id);
+		pid = 0xffff;
+	}
+
+	id = 0x10 + id*2;
+
+	vp702x_set_pld_state(adap, st->pid_filter_state);
+	vp702x_usb_in_op(adap->dev, 0xe0, (((pid >> 8) & 0xff) << 8) | (id), 0, buf, 16);
+	vp702x_usb_in_op(adap->dev, 0xe0, (((pid     ) & 0xff) << 8) | (id+1), 0, buf, 16);
+	return 0;
+}
+
+
+static int vp702x_init_pid_filter(struct dvb_usb_adapter *adap)
+{
+	struct vp702x_state *st = adap->priv;
+	int i;
+	u8 b[10] = { 0 };
+
+	st->pid_filter_count = 8;
+	st->pid_filter_can_bypass = 1;
+	st->pid_filter_state = 0x00;
+
+	vp702x_set_pld_mode(adap, 1); // bypass
+
+	for (i = 0; i < st->pid_filter_count; i++)
+		vp702x_set_pid(adap, 0xffff, i, 1);
+
+	vp702x_usb_in_op(adap->dev, 0xb5, 3, 0, b, 10);
+	vp702x_usb_in_op(adap->dev, 0xb5, 0, 0, b, 10);
+	vp702x_usb_in_op(adap->dev, 0xb5, 1, 0, b, 10);
+
+	//vp702x_set_pld_mode(d, 0); // filter
+	return 0;
+}
+
+static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	return 0;
 }
 
 /* keys for the enclosed remote control */
@@ -166,74 +204,83 @@
 	return 0;
 }
 
+int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	struct vp702x_device_state *st = d->priv;
+
+	if (st->power_state == 0 && onoff)
+		vp702x_usb_out_op(d, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
+	else if (st->power_state == 1 && onoff == 0)
+		vp702x_usb_out_op(d, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
+
+	st->power_state = onoff;
+
+	return 0;
+}
+
 static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
 {
-	u8 macb[9];
-	if (vp702x_usb_inout_cmd(d, GET_MAC_ADDRESS, NULL, 0, macb, 9, 10))
-		return -EIO;
-	memcpy(mac,&macb[3],6);
+	u8 i;
+	for (i = 6; i < 12; i++)
+		vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &mac[i - 6], 1);
 	return 0;
 }
 
-static int vp702x_frontend_attach(struct dvb_usb_device *d)
+static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
 {
-	u8 buf[9] = { 0 };
+	u8 buf[10] = { 0 };
 
-	if (vp702x_usb_inout_cmd(d, GET_SYSTEM_STRING, NULL, 0, buf, 9, 10))
+	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 0, 7, NULL, 0);
+
+	if (vp702x_usb_inout_cmd(adap->dev, GET_SYSTEM_STRING, NULL, 0, buf, 10, 10))
 		return -EIO;
 
-	buf[8] = '\0';
+	buf[9] = '\0';
 	info("system string: %s",&buf[1]);
 
-	d->fe = vp702x_fe_attach(d);
+	vp702x_init_pid_filter(adap);
+
+	adap->fe = vp702x_fe_attach(adap->dev);
+	vp702x_usb_out_op(adap->dev, SET_TUNER_POWER_REQ, 1, 7, NULL, 0);
+
 	return 0;
 }
 
-static struct dvb_usb_properties vp702x_properties;
+static struct dvb_usb_device_properties vp702x_properties;
 
 static int vp702x_usb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
-	struct usb_device *udev = interface_to_usbdev(intf);
-
-	usb_clear_halt(udev,usb_sndctrlpipe(udev,0));
-	usb_clear_halt(udev,usb_rcvctrlpipe(udev,0));
-
 	return dvb_usb_device_init(intf,&vp702x_properties,THIS_MODULE,NULL);
 }
 
 static struct usb_device_id vp702x_usb_table [] = {
 	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_COLD) },
-	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7021_WARM) },
-	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) },
-	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) },
+//	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_COLD) },
+//	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7020_WARM) },
 	    { 0 },
 };
 MODULE_DEVICE_TABLE(usb, vp702x_usb_table);
 
-static struct dvb_usb_properties vp702x_properties = {
-	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
-	.pid_filter_count = 8, /* !!! */
-
+static struct dvb_usb_device_properties vp702x_properties = {
 	.usb_ctrl = CYPRESS_FX2,
-	.firmware = "dvb-usb-vp702x-01.fw",
+	.firmware            = "dvb-usb-vp702x-02.fw",
+	.no_reconnect        = 1,
 
-	.pid_filter       = vp702x_pid_filter,
-	.power_ctrl       = vp702x_power_ctrl,
+	.size_of_priv     = sizeof(struct vp702x_device_state),
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.caps             = DVB_USB_ADAP_RECEIVES_204_BYTE_TS,
+
+			.streaming_ctrl   = vp702x_streaming_ctrl,
 	.frontend_attach  = vp702x_frontend_attach,
-	.read_mac_address = vp702x_read_mac_addr,
-
-	.rc_key_map       = vp702x_rc_keys,
-	.rc_key_map_size  = ARRAY_SIZE(vp702x_rc_keys),
-	.rc_interval      = 400,
-	.rc_query         = vp702x_rc_query,
-
-	.size_of_priv     = sizeof(struct vp702x_state),
 
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
-		.count = 7,
+			.stream = {
+				.type = USB_BULK,
+				.count = 10,
 		.endpoint = 0x02,
 		.u = {
 			.bulk = {
@@ -241,24 +288,33 @@
 			}
 		}
 	},
+			.size_of_priv     = sizeof(struct vp702x_state),
+		}
+		},
+	.read_mac_address = vp702x_read_mac_addr,
 
-	.num_device_descs = 2,
+	.rc_key_map       = vp702x_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(vp702x_rc_keys),
+	.rc_interval      = 400,
+	.rc_query         = vp702x_rc_query,
+
+	.num_device_descs = 1,
 	.devices = {
 		{ .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7021)",
 		  .cold_ids = { &vp702x_usb_table[0], NULL },
-		  .warm_ids = { &vp702x_usb_table[1], NULL },
+		  .warm_ids = { NULL },
 		},
-		{ .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)",
+/*		{ .name = "TwinhanDTV StarBox DVB-S USB2.0 (VP7020)",
 		  .cold_ids = { &vp702x_usb_table[2], NULL },
 		  .warm_ids = { &vp702x_usb_table[3], NULL },
 		},
-		{ 0 },
+*/		{ NULL },
 	}
 };
 
 /* usb specific object needed to register this driver with the usb subsystem */
 static struct usb_driver vp702x_usb_driver = {
-	.name		= "dvb-usb-vp702x",
+	.name		= "dvb_usb_vp702x",
 	.probe 		= vp702x_usb_probe,
 	.disconnect = dvb_usb_device_exit,
 	.id_table 	= vp702x_usb_table,
@@ -287,5 +343,5 @@
 
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
 MODULE_DESCRIPTION("Driver for Twinhan StarBox DVB-S USB2.0 and clones");
-MODULE_VERSION("1.0-alpha");
+MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp702x.h b/drivers/media/dvb/dvb-usb/vp702x.h
index c2f97f9..25a9dee 100644
--- a/drivers/media/dvb/dvb-usb/vp702x.h
+++ b/drivers/media/dvb/dvb-usb/vp702x.h
@@ -102,5 +102,7 @@
 
 extern int vp702x_usb_inout_op(struct dvb_usb_device *d, u8 *o, int olen, u8 *i, int ilen, int msec);
 extern int vp702x_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int vp702x_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int vp702x_power_ctrl(struct dvb_usb_device *d, int onoff);
 
 #endif
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
index 8ea3834..b4cf002 100644
--- a/drivers/media/dvb/dvb-usb/vp7045.c
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -169,31 +169,31 @@
 	return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
 }
 
-static int vp7045_frontend_attach(struct dvb_usb_device *d)
+static int vp7045_frontend_attach(struct dvb_usb_adapter *adap)
 {
 	u8 buf[255] = { 0 };
 
-	vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0);
+	vp7045_usb_op(adap->dev,VENDOR_STRING_READ,NULL,0,buf,20,0);
 	buf[10] = '\0';
 	deb_info("firmware says: %s ",buf);
 
-	vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0);
+	vp7045_usb_op(adap->dev,PRODUCT_STRING_READ,NULL,0,buf,20,0);
 	buf[10] = '\0';
 	deb_info("%s ",buf);
 
-	vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0);
+	vp7045_usb_op(adap->dev,FW_VERSION_READ,NULL,0,buf,20,0);
 	buf[10] = '\0';
 	deb_info("v%s\n",buf);
 
 /*	Dump the EEPROM */
 /*	vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
 
-	d->fe = vp7045_fe_attach(d);
+	adap->fe = vp7045_fe_attach(adap->dev);
 
 	return 0;
 }
 
-static struct dvb_usb_properties vp7045_properties;
+static struct dvb_usb_device_properties vp7045_properties;
 
 static int vp7045_usb_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
@@ -210,24 +210,17 @@
 };
 MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
 
-static struct dvb_usb_properties vp7045_properties = {
-	.caps = 0,
-
+static struct dvb_usb_device_properties vp7045_properties = {
 	.usb_ctrl = CYPRESS_FX2,
 	.firmware = "dvb-usb-vp7045-01.fw",
 
-	.power_ctrl       = vp7045_power_ctrl,
+	.num_adapters = 1,
+	.adapter = {
+		{
 	.frontend_attach  = vp7045_frontend_attach,
-	.read_mac_address = vp7045_read_mac_addr,
-
-	.rc_interval      = 400,
-	.rc_key_map       = vp7045_rc_keys,
-	.rc_key_map_size  = ARRAY_SIZE(vp7045_rc_keys),
-	.rc_query         = vp7045_rc_query,
-
 	/* parameter for the MPEG2-data transfer */
-	.urb = {
-		.type = DVB_USB_BULK,
+			.stream = {
+				.type = USB_BULK,
 		.count = 7,
 		.endpoint = 0x02,
 		.u = {
@@ -236,6 +229,15 @@
 			}
 		}
 	},
+		}
+	},
+	.power_ctrl       = vp7045_power_ctrl,
+	.read_mac_address = vp7045_read_mac_addr,
+
+	.rc_interval      = 400,
+	.rc_key_map       = vp7045_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(vp7045_rc_keys),
+	.rc_query         = vp7045_rc_query,
 
 	.num_device_descs = 2,
 	.devices = {
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index 62d69a6..a356d28 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -553,8 +553,8 @@
 	ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff;
 	adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f;
 
-	if (adiv == 0)
-		ndiv++;
+	if (adiv == 0 && ndiv > 0)
+		ndiv--;
 
 	/* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */
 	state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv;
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index cc28417..ccc813b 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -37,6 +37,8 @@
 
 	struct dibx000_i2c_master i2c_master;
 
+	u32 timf;
+
 	fe_bandwidth_t current_bandwidth;
 
 	u16 dev_id;
@@ -92,50 +94,31 @@
 
 static int dib3000mc_set_timing(struct dib3000mc_state *state, s16 nfft, u8 bw, u8 update_offset)
 {
-/*
-	u32 timf_msb, timf_lsb, i;
-	int tim_sgn ;
-	LUInt comp1, comp2, comp ;
-//	u32 tim_offset ;
-	comp = 27700 * BW_INDEX_TO_KHZ(bw) / 1000;
-	timf_msb = (comp >> 16) & 0x00FF;
-	timf_lsb =  comp        & 0xFFFF;
+	u32 timf;
 
-	// Update the timing offset ;
+	if (state->timf == 0) {
+		timf = 1384402; // default value for 8MHz
+		if (update_offset)
+			msleep(200); // first time we do an update
+	} else
+		timf = state->timf;
+
+	timf *= (BW_INDEX_TO_KHZ(bw) / 1000);
+
 	if (update_offset) {
-		if (state->timing_offset_comp_done == 0) {
-			usleep(200000);
-			state->timing_offset_comp_done = 1;
-		}
-		tim_offset = dib3000mc_read_word(state, 416);
-		if ((tim_offset & 0x2000) == 0x2000)
-			tim_offset |= 0xC000; // PB: This only works if tim_offset is s16 - weird
+		s16 tim_offs = dib3000mc_read_word(state, 416);
+
+		if (tim_offs &  0x2000)
+			tim_offs -= 0x4000;
 
 		if (nfft == 0)
-			tim_offset = tim_offset << 2; // PB: Do not store the offset for different things in one variable
-		state->timing_offset += tim_offset;
+			tim_offs *= 4;
+
+		timf += tim_offs;
+		state->timf = timf / (BW_INDEX_TO_KHZ(bw) / 1000);
 	}
-	tim_offset = state->timing_offset;
 
-	if (tim_offset < 0) {
-		tim_sgn = 1;
-		tim_offset = -tim_offset;
-	} else
-		tim_sgn = 0;
-
-	comp1 = tim_offset * timf_lsb;
-	comp2 = tim_offset * timf_msb;
-	comp  = ((comp1 >> 16) + comp2) >> 7;
-
-	if (tim_sgn == 0)
-		comp = timf_msb * (1<<16) + timf_lsb + comp;
-	else
-		comp = timf_msb * (1<<16) + timf_lsb - comp;
-
-	timf_msb = (comp>>16)&0xFF ;
-	timf_lsb = comp&0xFFFF;
-*/
-	u32 timf = 1384402 * (BW_INDEX_TO_KHZ(bw) / 1000);
+	dprintk("timf: %d\n", timf);
 
 	dib3000mc_write_word(state, 23, timf >> 16);
 	dib3000mc_write_word(state, 24, timf & 0xffff);
@@ -143,15 +126,18 @@
 	return 0;
 }
 
-static int dib3000mc_setup_pwm3_state(struct dib3000mc_state *state)
+static int dib3000mc_setup_pwm_state(struct dib3000mc_state *state)
 {
+	u16 reg_51, reg_52 = state->cfg->agc->setup & 0xfefb;
     if (state->cfg->pwm3_inversion) {
-		dib3000mc_write_word(state, 51, (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
-		dib3000mc_write_word(state, 52, (0 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (1 << 2) | (2 << 0));
+		reg_51 =  (2 << 14) | (0 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
+		reg_52 |= (1 << 2);
 	} else {
-		dib3000mc_write_word(state, 51, (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0));
-		dib3000mc_write_word(state, 52, (1 << 8) | (5 << 5) | (1 << 4) | (1 << 3) | (0 << 2) | (2 << 0));
+		reg_51 = (2 << 14) | (4 << 10) | (7 << 6) | (2 << 2) | (2 << 0);
+		reg_52 |= (1 << 8);
 	}
+	dib3000mc_write_word(state, 51, reg_51);
+	dib3000mc_write_word(state, 52, reg_52);
 
     if (state->cfg->use_pwm3)
 		dib3000mc_write_word(state, 245, (1 << 3) | (1 << 0));
@@ -326,10 +312,10 @@
 		dib3000mc_write_word(state, 175,  0x0000);
 		dib3000mc_write_word(state, 1032, 0x012C);
 	}
-	dib3000mc_write_word(state, 1033, 0);
+	dib3000mc_write_word(state, 1033, 0x0000);
 
 	// P_clk_cfg
-	dib3000mc_write_word(state, 1037, 12592);
+	dib3000mc_write_word(state, 1037, 0x3130);
 
 	// other configurations
 
@@ -350,7 +336,7 @@
 	dib3000mc_write_word(state, 50, 0x8000);
 
 	// agc setup misc
-	dib3000mc_setup_pwm3_state(state);
+	dib3000mc_setup_pwm_state(state);
 
 	// P_agc_counter_lock
 	dib3000mc_write_word(state, 53, 0x87);
@@ -426,10 +412,9 @@
 {
 	struct dib3000mc_state *state = demod->demodulator_priv;
 
-	dib3000mc_write_word(state, 1037, dib3000mc_read_word(state, 1037) | 0x0003);
 	dib3000mc_write_word(state, 1031, 0xFFFF);
 	dib3000mc_write_word(state, 1032, 0xFFFF);
-	dib3000mc_write_word(state, 1033, 0xFFF4);   // ****  Bin2
+	dib3000mc_write_word(state, 1033, 0xFFF0);
 
     return 0;
 }
@@ -539,6 +524,7 @@
 
 	reg = dib3000mc_read_word(state, 0);
 	dib3000mc_write_word(state, 0, reg | (1 << 8));
+	dib3000mc_read_word(state, 511);
 	dib3000mc_write_word(state, 0, reg);
 
 	return 0;
@@ -578,62 +564,12 @@
 		dib3000mc_write_word(state, 33, 6);
 	}
 
-	// if (lock)
-	//	dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
+	if (dib3000mc_read_word(state, 509) & 0x80)
+		dib3000mc_set_timing(state, ch->nfft, ch->Bw, 1);
 
 	return 0;
 }
 
-static int dib3000mc_demod_output_mode(struct dvb_frontend *demod, int mode)
-{
-	struct dib3000mc_state *state = demod->demodulator_priv;
-	return dib3000mc_set_output_mode(state, mode);
-}
-
-static int dib3000mc_i2c_enumeration(struct dvb_frontend *demod[], int no_of_demods, u8 default_addr)
-{
-	struct dib3000mc_state *st;
-	int k,ret=0;
-	u8 new_addr;
-
-	static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
-
-	for (k = no_of_demods-1; k >= 0; k--) {
-		st = demod[k]->demodulator_priv;
-
-		/* designated i2c address */
-		new_addr          = DIB3000MC_I2C_ADDRESS[k];
-
-		st->i2c_addr = new_addr;
-		if (dib3000mc_identify(st) != 0) {
-			st->i2c_addr = default_addr;
-			if (dib3000mc_identify(st) != 0) {
-				dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
-				return -EINVAL;
-			}
-		}
-
-		/* turn on div_out */
-		dib3000mc_demod_output_mode(demod[k], OUTMODE_MPEG2_PAR_CONT_CLK);
-
-		// set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
-		ret |= dib3000mc_write_word(st, 1024, (new_addr << 3) | 0x1);
-		st->i2c_addr = new_addr;
-	}
-
-	for (k = 0; k < no_of_demods; k++) {
-		st = demod[k]->demodulator_priv;
-
-		ret |= dib3000mc_write_word(st, 1024, st->i2c_addr << 3);
-
-		/* turn off data output */
-		dib3000mc_demod_output_mode(demod[k],OUTMODE_HIGH_Z);
-		dib3000mc_write_word(st, 769, (1 << 7) );
-
-	}
-	return 0;
-}
-
 struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating)
 {
 	struct dib3000mc_state *st = demod->demodulator_priv;
@@ -826,61 +762,79 @@
 }
 EXPORT_SYMBOL(dib3000mc_set_config);
 
-static struct dvb_frontend_ops dib3000mc_ops;
-
-int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8	default_addr,				u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[])
+int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[])
 {
-	struct dib3000mc_state *st;
-	int k, num=0;
+	struct dib3000mc_state st = { .i2c_adap = i2c };
+	int k;
+	u8 new_addr;
 
-	if (no_of_demods < 1)
-		return -EINVAL;
+	static u8 DIB3000MC_I2C_ADDRESS[] = {20,22,24,26};
+
+	for (k = no_of_demods-1; k >= 0; k--) {
+		st.cfg = &cfg[k];
+
+		/* designated i2c address */
+		new_addr          = DIB3000MC_I2C_ADDRESS[k];
+		st.i2c_addr = new_addr;
+		if (dib3000mc_identify(&st) != 0) {
+			st.i2c_addr = default_addr;
+			if (dib3000mc_identify(&st) != 0) {
+				dprintk("-E-  DiB3000P/MC #%d: not identified\n", k);
+				return -ENODEV;
+			}
+		}
+
+		dib3000mc_set_output_mode(&st, OUTMODE_MPEG2_PAR_CONT_CLK);
+
+		// set new i2c address and force divstr (Bit 1) to value 0 (Bit 0)
+		dib3000mc_write_word(&st, 1024, (new_addr << 3) | 0x1);
+		st.i2c_addr = new_addr;
+	}
 
 	for (k = 0; k < no_of_demods; k++) {
-		st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
-		if (st == NULL)
-			goto error;
+		st.cfg = &cfg[k];
+		st.i2c_addr = DIB3000MC_I2C_ADDRESS[k];
 
-		num++;
+		dib3000mc_write_word(&st, 1024, st.i2c_addr << 3);
 
-		st->cfg = &cfg[k];
-	//	st->gpio_val = cfg[k].gpio_val;
-	//	st->gpio_dir = cfg[k].gpio_dir;
-		st->i2c_adap = i2c_adap;
-
-		demod[k]           = &st->demod;
-		demod[k]->demodulator_priv     = st;
-		memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
-
-//		INIT_COMPONENT_REGISTER_ACCESS(&st->register_access, 12, 16, dib7000p_register_read, dib7000p_register_write, st);
-//		demod[k]->register_access = &st->register_access;
+		/* turn off data output */
+		dib3000mc_set_output_mode(&st, OUTMODE_HIGH_Z);
 	}
-
-	if (do_i2c_enum) {
-		if (dib3000mc_i2c_enumeration(demod,no_of_demods,default_addr) != 0)
-			goto error;
-	} else {
-		st = demod[0]->demodulator_priv;
-		st->i2c_addr = default_addr;
-		if (dib3000mc_identify(st) != 0)
-			goto error;
-	}
-
-	for (k = 0; k < num; k++) {
-		st = demod[k]->demodulator_priv;
-		dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
-	}
-
 	return 0;
+}
+EXPORT_SYMBOL(dib3000mc_i2c_enumeration);
+
+static struct dvb_frontend_ops dib3000mc_ops;
+
+struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
+{
+	struct dvb_frontend *demod;
+	struct dib3000mc_state *st;
+	st = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+
+	st->cfg = cfg;
+	st->i2c_adap = i2c_adap;
+	st->i2c_addr = i2c_addr;
+
+	demod                   = &st->demod;
+	demod->demodulator_priv = st;
+	memcpy(&st->demod.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
+
+	if (dib3000mc_identify(st) != 0)
+		goto error;
+
+	dibx000_init_i2c_master(&st->i2c_master, DIB3000MC, st->i2c_adap, st->i2c_addr);
+
+	dib3000mc_write_word(st, 1037, 0x3130);
+
+	return demod;
 
 error:
-	for (k = 0; k < num; k++) {
-		kfree(demod[k]->demodulator_priv);
-		demod[k] = NULL;
-	}
-	return -EINVAL;
+	kfree(st);
+	return NULL;
 }
-
 EXPORT_SYMBOL(dib3000mc_attach);
 
 static struct dvb_frontend_ops dib3000mc_ops = {
diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h
index fd0b2e7..b198cd5 100644
--- a/drivers/media/dvb/frontends/dib3000mc.h
+++ b/drivers/media/dvb/frontends/dib3000mc.h
@@ -37,17 +37,17 @@
 #define DEFAULT_DIB3000P_I2C_ADDRESS  24
 
 #if defined(CONFIG_DVB_DIB3000MC) || defined(CONFIG_DVB_DIB3000MC_MODULE)
-extern int dib3000mc_attach(struct i2c_adapter *i2c_adap, int no_of_demods, u8 default_addr,
-    u8 do_i2c_enum, struct dib3000mc_config cfg[], struct dvb_frontend *demod[]);
+extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg);
 #else
-static inline struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
-					     struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops)
+static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__);
 	return NULL;
 }
 #endif // CONFIG_DVB_DIB3000MC
 
+extern int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib3000mc_config cfg[]);
+
 extern struct i2c_adapter * dib3000mc_get_tuner_i2c_master(struct dvb_frontend *demod, int gating);
 
 extern int dib3000mc_pid_control(struct dvb_frontend *fe, int index, int pid,int onoff);
diff --git a/drivers/media/dvb/frontends/mt2060.c b/drivers/media/dvb/frontends/mt2060.c
index 508ec1b..450fad8 100644
--- a/drivers/media/dvb/frontends/mt2060.c
+++ b/drivers/media/dvb/frontends/mt2060.c
@@ -247,6 +247,9 @@
 	if (mt2060_writeregs(priv,mt2060_config2,sizeof(mt2060_config2)))
 		return;
 
+	/* initialize the clock output */
+	mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
+
 	do {
 		b |= (1 << 6); // FM1SS;
 		mt2060_writereg(priv, REG_LO2C1,b);
@@ -294,13 +297,13 @@
 static int mt2060_init(struct dvb_frontend *fe)
 {
 	struct mt2060_priv *priv = fe->tuner_priv;
-	return mt2060_writereg(priv, REG_VGAG,0x33);
+	return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x33);
 }
 
 static int mt2060_sleep(struct dvb_frontend *fe)
 {
 	struct mt2060_priv *priv = fe->tuner_priv;
-	return mt2060_writereg(priv, REG_VGAG,0x30);
+	return mt2060_writereg(priv, REG_VGAG, (priv->cfg->clock_out << 6) | 0x30);
 }
 
 static int mt2060_release(struct dvb_frontend *fe)
@@ -329,14 +332,14 @@
 };
 
 /* This functions tries to identify a MT2060 tuner by reading the PART/REV register. This is hasty. */
-int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
+struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1)
 {
 	struct mt2060_priv *priv = NULL;
 	u8 id = 0;
 
 	priv = kzalloc(sizeof(struct mt2060_priv), GFP_KERNEL);
 	if (priv == NULL)
-		return -ENOMEM;
+		return NULL;
 
 	priv->cfg      = cfg;
 	priv->i2c      = i2c;
@@ -344,12 +347,12 @@
 
 	if (mt2060_readreg(priv,REG_PART_REV,&id) != 0) {
 		kfree(priv);
-		return -ENODEV;
+		return NULL;
 	}
 
 	if (id != PART_REV) {
 		kfree(priv);
-		return -ENODEV;
+		return NULL;
 	}
 	printk(KERN_INFO "MT2060: successfully identified (IF1 = %d)\n", if1);
 	memcpy(&fe->ops.tuner_ops, &mt2060_tuner_ops, sizeof(struct dvb_tuner_ops));
@@ -358,7 +361,7 @@
 
 	mt2060_calibrate(priv);
 
-	return 0;
+	return fe;
 }
 EXPORT_SYMBOL(mt2060_attach);
 
diff --git a/drivers/media/dvb/frontends/mt2060.h b/drivers/media/dvb/frontends/mt2060.h
index c58b03e..34a37c2 100644
--- a/drivers/media/dvb/frontends/mt2060.h
+++ b/drivers/media/dvb/frontends/mt2060.h
@@ -27,9 +27,9 @@
 
 struct mt2060_config {
 	u8 i2c_address;
-	/* Shall we add settings for the discrete outputs ? */
+	u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */
 };
 
-extern int mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
+extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1);
 
 #endif
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index d1183c9..5c53fe6 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -36,7 +36,7 @@
 menu "Encoders/decoders and other helper chips"
 	depends on VIDEO_DEV && !VIDEO_HELPER_CHIPS_AUTO
 
-comment "Audio Decoders"
+comment "Audio decoders"
 
 config VIDEO_TVAUDIO
 	tristate "Simple audio decoder chips"
@@ -51,7 +51,7 @@
 	  module will be called tvaudio.
 
 config VIDEO_TDA7432
-	tristate "Philips TDA7432 audio processor chip"
+	tristate "Philips TDA7432 audio processor"
 	depends on VIDEO_V4L1 && I2C
 	---help---
 	  Support for tda7432 audio decoder chip found on some bt8xx boards.
@@ -60,7 +60,7 @@
 	  module will be called tda7432.
 
 config VIDEO_TDA9840
-	tristate "Philips TDA9840 audio processor chip"
+	tristate "Philips TDA9840 audio processor"
 	depends on VIDEO_DEV && I2C
 	---help---
 	  Support for tda9840 audio decoder chip found on some Zoran boards.
@@ -69,7 +69,7 @@
 	  module will be called tda9840.
 
 config VIDEO_TDA9875
-	tristate "Philips TDA9875 audio processor chip"
+	tristate "Philips TDA9875 audio processor"
 	depends on VIDEO_V4L1 && I2C
 	---help---
 	  Support for tda9875 audio decoder chip found on some bt8xx boards.
@@ -78,7 +78,7 @@
 	  module will be called tda9875.
 
 config VIDEO_TEA6415C
-	tristate "Philips TEA6415C audio processor chip"
+	tristate "Philips TEA6415C audio processor"
 	depends on VIDEO_DEV && I2C
 	---help---
 	  Support for tea6415c audio decoder chip found on some bt8xx boards.
@@ -87,7 +87,7 @@
 	  module will be called tea6415c.
 
 config VIDEO_TEA6420
-	tristate "Philips TEA6420 audio processor chip"
+	tristate "Philips TEA6420 audio processor"
 	depends on VIDEO_DEV && I2C
 	---help---
 	  Support for tea6420 audio decoder chip found on some bt8xx boards.
@@ -143,64 +143,10 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called wm8739.
 
-comment "MPEG video encoders"
-
-config VIDEO_CX2341X
-	tristate "Conexant CX2341x MPEG encoders"
-	depends on VIDEO_V4L2 && EXPERIMENTAL
-	---help---
-	  Support for the Conexant CX23416 MPEG encoders
-	  and CX23415 MPEG encoder/decoders.
-
-	  This module currently supports the encoding functions only.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called cx2341x.
-
-source "drivers/media/video/cx25840/Kconfig"
-
-comment "Video encoders"
-
-config VIDEO_SAA7127
-	tristate "Philips SAA7127/9 digital video encoders"
-	depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
-	---help---
-	  Support for the Philips SAA7127/9 digital video encoders.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called saa7127.
-
-config VIDEO_SAA7185
-	tristate "Philips SAA7185 video encoder"
-	depends on VIDEO_V4L1 && I2C
-	---help---
-	  Support for the Philips SAA7185 video encoder.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called saa7185.
-
-config VIDEO_ADV7170
-	tristate "Analog Devices ADV7170 video encoder driver"
-	depends on VIDEO_V4L1 && I2C
-	---help---
-	  Support for the Analog Devices ADV7170 video encoder driver
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called adv7170.
-
-config VIDEO_ADV7175
-	tristate "Analog Devices ADV7175 video encoder driver"
-	depends on VIDEO_V4L1 && I2C
-	---help---
-	  Support for the Analog Devices ADV7175 video encoder driver
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called adv7175.
-
 comment "Video decoders"
 
 config VIDEO_BT819
-	tristate "BT819A VideoStream Decoder"
+	tristate "BT819A VideoStream decoder"
 	depends on VIDEO_V4L1 && I2C
 	---help---
 	  Support for BT819A video decoder.
@@ -209,7 +155,7 @@
 	  module will be called bt819.
 
 config VIDEO_BT856
-	tristate "BT856 VideoStream Decoder"
+	tristate "BT856 VideoStream decoder"
 	depends on VIDEO_V4L1 && I2C
 	---help---
 	  Support for BT856 video decoder.
@@ -218,7 +164,7 @@
 	  module will be called bt856.
 
 config VIDEO_BT866
-	tristate "BT866 VideoStream Decoder"
+	tristate "BT866 VideoStream decoder"
 	depends on VIDEO_V4L1 && I2C
 	---help---
 	  Support for BT866 video decoder.
@@ -295,7 +241,7 @@
 	  module will be called tvp5150.
 
 config VIDEO_VPX3220
-	tristate "vpx3220a, vpx3216b & vpx3214c video decoder driver"
+	tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
 	depends on VIDEO_V4L1 && I2C
 	---help---
 	  Support for VPX322x video decoders.
@@ -303,6 +249,62 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called vpx3220.
 
+comment "Video and audio decoders"
+
+source "drivers/media/video/cx25840/Kconfig"
+
+comment "MPEG video encoders"
+
+config VIDEO_CX2341X
+	tristate "Conexant CX2341x MPEG encoders"
+	depends on VIDEO_V4L2 && EXPERIMENTAL
+	---help---
+	  Support for the Conexant CX23416 MPEG encoders
+	  and CX23415 MPEG encoder/decoders.
+
+	  This module currently supports the encoding functions only.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx2341x.
+
+comment "Video encoders"
+
+config VIDEO_SAA7127
+	tristate "Philips SAA7127/9 digital video encoders"
+	depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
+	---help---
+	  Support for the Philips SAA7127/9 digital video encoders.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7127.
+
+config VIDEO_SAA7185
+	tristate "Philips SAA7185 video encoder"
+	depends on VIDEO_V4L1 && I2C
+	---help---
+	  Support for the Philips SAA7185 video encoder.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called saa7185.
+
+config VIDEO_ADV7170
+	tristate "Analog Devices ADV7170 video encoder"
+	depends on VIDEO_V4L1 && I2C
+	---help---
+	  Support for the Analog Devices ADV7170 video encoder driver
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7170.
+
+config VIDEO_ADV7175
+	tristate "Analog Devices ADV7175 video encoder"
+	depends on VIDEO_V4L1 && I2C
+	---help---
+	  Support for the Analog Devices ADV7175 video encoder driver
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called adv7175.
+
 comment "Video improvement chips"
 
 config VIDEO_UPD64031A
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index d23a42b..a84903e 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -2000,7 +2000,7 @@
 		.no_msp34xx     = 1,
 		.no_tda9875     = 1,
 		.no_tda7432     = 1,
-		.muxsel         = { 3, 0, 1, 2 },
+		.muxsel         = { 3, 1 },
 		.pll            = PLL_28,
 		.no_gpioirq     = 1,
 		.has_dvb        = 1,
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index a7921f9d..4673832 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -896,7 +896,7 @@
 		snprintf(name, sizeof(name), "%s/2", core->name);
 		printk("%s/2: ============  START LOG STATUS  ============\n",
 		       core->name);
-		cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, 0);
+		cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, NULL);
 		cx2341x_log_status(&dev->params, name);
 		printk("%s/2: =============  END LOG STATUS  =============\n",
 		       core->name);
@@ -1086,7 +1086,7 @@
 		return -EINVAL;
 
 	err = -ENODEV;
-	if (!cx88_boards[core->board].blackbird)
+	if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
 		goto fail_core;
 
 	err = -ENOMEM;
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 6214eb8..af71d422 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -294,7 +294,7 @@
 			.type   = CX88_RADIO,
 			.gpio0  = 0x0000bd62,
 		},
-		.blackbird = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 	},
 	[CX88_BOARD_IODATA_GVVCP3PCI] = {
 		.name		= "IODATA GV-VCP3/PCI",
@@ -358,7 +358,7 @@
 			.type   = CX88_RADIO,
 			.gpio0  = 0x0000fde2,
 		},
-		.blackbird = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 	},
 	[CX88_BOARD_MSI_TVANYWHERE] = {
 		.name           = "MSI TV-@nywhere",
@@ -401,7 +401,7 @@
 			.gpio0  = 0x0700,
 			.gpio2  = 0x0101,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
 		.name           = "DViCO FusionHDTV DVB-T1",
@@ -418,7 +418,7 @@
 			.vmux   = 2,
 			.gpio0  = 0x000027df,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_KWORLD_LTV883] = {
 		.name           = "KWorld LTV883RF",
@@ -488,7 +488,7 @@
 			.vmux   = 2,
 			.gpio0	= 0x0f00,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_HAUPPAUGE_DVB_T1] = {
 		.name           = "Hauppauge Nova-T DVB-T",
@@ -500,7 +500,7 @@
 			.type   = CX88_VMUX_DVB,
 			.vmux   = 0,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_CONEXANT_DVB_T1] = {
 		.name           = "Conexant DVB-T reference design",
@@ -512,7 +512,7 @@
 			.type   = CX88_VMUX_DVB,
 			.vmux   = 0,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_PROVIDEO_PV259] = {
 		.name		= "Provideo PV259",
@@ -524,7 +524,7 @@
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
 		}},
-		.blackbird = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
 		.name           = "DViCO FusionHDTV DVB-T Plus",
@@ -541,7 +541,7 @@
 			.vmux   = 2,
 			.gpio0  = 0x000027df,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_DNTV_LIVE_DVB_T] = {
 		.name		= "digitalnow DNTV Live! DVB-T",
@@ -560,7 +560,7 @@
 			.gpio0  = 0x00000700,
 			.gpio2  = 0x00000101,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_PCHDTV_HD3000] = {
 		.name           = "pcHDTV HD3000 HDTV",
@@ -599,7 +599,7 @@
 			.gpio2  = 0x00000000,
 			.gpio3  = 0x00000000,
 		},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_HAUPPAUGE_ROSLYN] = {
 		// entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
@@ -633,7 +633,7 @@
 			 .gpio0  = 0xed96,
 			 .gpio2  = 0x00ff,
 		 },
-		.blackbird = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 	},
 	[CX88_BOARD_DIGITALLOGIC_MEC] = {
 		.name           = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
@@ -659,7 +659,7 @@
 			.type   = CX88_RADIO,
 			.gpio0  = 0x00009d00,
 		},
-		.blackbird = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 	},
 	[CX88_BOARD_IODATA_GVBCTV7E] = {
 		.name           = "IODATA GV/BCTV7E",
@@ -727,7 +727,7 @@
 			.vmux   = 2,
 			.gpio0  = 0x97e9,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_ADSTECH_DVB_T_PCI] = {
 		.name           = "ADS Tech Instant TV DVB-T PCI",
@@ -746,7 +746,7 @@
 			.gpio0  = 0x0700,
 			.gpio2  = 0x0101,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
 		.name           = "TerraTec Cinergy 1400 DVB-T",
@@ -755,7 +755,7 @@
 			.type   = CX88_VMUX_DVB,
 			.vmux   = 0,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
 		.name           = "DViCO FusionHDTV 5 Gold",
@@ -777,7 +777,7 @@
 			.vmux   = 2,
 			.gpio0  = 0x87f9,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = {
 		.name           = "AverMedia UltraTV Media Center PCI 550",
@@ -786,7 +786,7 @@
 		.tuner_addr     = ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
-		.blackbird      = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 		.input          = {{
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 0,
@@ -854,7 +854,7 @@
 			.gpio2  = 0x00000001,
 			.gpio3  = 0x00000000,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_WINFAST_DTV1000] = {
 		.name           = "WinFast DTV1000-T",
@@ -866,7 +866,7 @@
 			.type   = CX88_VMUX_DVB,
 			.vmux   = 0,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_AVERTV_303] = {
 		.name           = "AVerTV 303 (M126)",
@@ -914,7 +914,7 @@
 			.type	= CX88_VMUX_SVIDEO,
 			.vmux	= 2,
 		}},
-		.dvb		= 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
 		.name		= "Hauppauge Nova-SE2 DVB-S",
@@ -926,7 +926,7 @@
 			.type	= CX88_VMUX_DVB,
 			.vmux	= 0,
 		}},
-		.dvb		= 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_KWORLD_DVBS_100] = {
 		.name		= "KWorld DVB-S 100",
@@ -944,7 +944,7 @@
 			.type	= CX88_VMUX_SVIDEO,
 			.vmux	= 2,
 		}},
-		.dvb		= 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_HAUPPAUGE_HVR1100] = {
 		.name		= "Hauppauge WinTV-HVR1100 DVB-T/Hybrid",
@@ -964,7 +964,7 @@
 			.vmux	= 2,
 		}},
 		/* fixme: Add radio support */
-		.dvb		= 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_HAUPPAUGE_HVR1100LP] = {
 		.name		= "Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)",
@@ -981,7 +981,7 @@
 			.vmux	= 1,
 		}},
 		/* fixme: Add radio support */
-		.dvb		= 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
 		.name           = "digitalnow DNTV Live! DVB-T Pro",
@@ -1008,7 +1008,7 @@
 			 .type  = CX88_RADIO,
 			 .gpio0 = 0xf80808,
 		},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_KWORLD_DVB_T_CX22702] = {
 		/* Kworld V-stream Xpert DVB-T with Thomson tuner */
@@ -1030,7 +1030,7 @@
 			.gpio0  = 0x0700,
 			.gpio2  = 0x0101,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
 		.name           = "DViCO FusionHDTV DVB-T Dual Digital",
@@ -1047,7 +1047,7 @@
 			.vmux   = 2,
 			.gpio0  = 0x000067df,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
 		/* FIXME: Audio not working for s-video / composite inputs. */
@@ -1075,7 +1075,7 @@
 			.gpio0  = 0x3de6,
 			.gpio2  = 0x00ff,
 		},
-		.blackbird      = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = {
 		.name           = "DViCO FusionHDTV DVB-T Hybrid",
@@ -1096,7 +1096,7 @@
 			.vmux   = 2,
 			.gpio0  = 0x0000a75b,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_PCHDTV_HD5500] = {
 		.name           = "pcHDTV HD5500 HDTV",
@@ -1118,7 +1118,7 @@
 			.vmux   = 2,
 			.gpio0  = 0x87f9,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_KWORLD_MCE200_DELUXE] = {
 		/* FIXME: tested TV input only, disabled composite,
@@ -1134,7 +1134,7 @@
 			.vmux   = 0,
 			.gpio0  = 0x0000BDE6
 		}},
-		.blackbird = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 	},
 	[CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = {
 		/* FIXME: SVideo, Composite and FM inputs are untested */
@@ -1150,7 +1150,7 @@
 			.vmux   = 0,
 			.gpio0  = 0x5da6,
 		}},
-		.blackbird = 1,
+		.mpeg           = CX88_MPEG_BLACKBIRD,
 	},
 	[CX88_BOARD_NPGTECH_REALTV_TOP10FM] = {
 		.name           = "NPG Tech Real TV FM Top 10",
@@ -1192,7 +1192,7 @@
 			.gpio2  = 0x00017304,
 			.gpio3  = 0x02000000,
 		}},
-		.dvb            = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_GENIATECH_DVBS] = {
 		.name          = "Geniatech DVB-S",
@@ -1207,7 +1207,7 @@
 			.type  = CX88_VMUX_COMPOSITE1,
 			.vmux  = 1,
 		}},
-		.dvb      = 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 	[CX88_BOARD_HAUPPAUGE_HVR3000] = {
 		/* FIXME: Add dvb & radio support */
@@ -1287,6 +1287,7 @@
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
+		.audio_chip     = AUDIO_CHIP_WM8775,
 		.input		= {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -1301,7 +1302,7 @@
 			.gpio0	= 0xe780,
 		}},
 		/* fixme: Add radio support */
-		.dvb		= 1,
+		.mpeg           = CX88_MPEG_DVB,
 	},
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -1581,6 +1582,14 @@
 		.subvendor = 0x107d,
 		.subdevice = 0x6632,
 		.card      = CX88_BOARD_LEADTEK_PVR2000,
+	},{
+		.subvendor = 0x12ab,
+		.subdevice = 0x2300, /* Club3D Zap TV2100 */
+		.card      = CX88_BOARD_KWORLD_DVB_T_CX22702,
+	},{
+		.subvendor = 0x0070,
+		.subdevice = 0x9000,
+		.card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
 	},
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index f379ede..4b655f2 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -658,13 +658,6 @@
 	return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
 }
 
-static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
-{
-	return (norm->id & V4L2_STD_625_50)
-		? HLNotchFilter135PAL
-		: HLNotchFilter135NTSC;
-}
-
 static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
 {
 	/* Should always be Line Draw Time / (4*FSC) */
@@ -937,7 +930,7 @@
 	// htotal
 	tmp64 = norm_htotal(norm) * (u64)vdec_clock;
 	do_div(tmp64, fsc8);
-	htotal = (u32)tmp64 | (norm_notchfilter(norm) << 11);
+	htotal = (u32)tmp64 | (HLNotchFilter4xFsc << 11);
 	dprintk(1,"set_tvnorm: MO_HTOTAL        0x%08x [old=0x%08x,htotal=%d]\n",
 		htotal, cx_read(MO_HTOTAL), (u32)tmp64);
 	cx_write(MO_HTOTAL, htotal);
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index c87041d..bd0c879 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -802,7 +802,7 @@
 		return -EINVAL;
 
 	err = -ENODEV;
-	if (!cx88_boards[core->board].dvb)
+	if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
 		goto fail_core;
 
 	err = -ENOMEM;
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 27b5dbb..88af23a 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -145,7 +145,7 @@
 	if (0 != core->i2c_rc)
 		return;
 
-	if (core->dvbdev) {
+	if ( (core->dvbdev) && (core->dvbdev->dvb.frontend) ) {
 		if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
 			core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
 
@@ -220,7 +220,7 @@
 
 	if (core->tuner_type != TUNER_ABSENT)
 		core->i2c_adap.class |= I2C_CLASS_TV_ANALOG;
-	if (cx88_boards[core->board].dvb)
+	if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB)
 		core->i2c_adap.class |= I2C_CLASS_TV_DIGITAL;
 
 	core->i2c_adap.dev.parent = &pci->dev;
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 138a4f6..d6d9807 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -65,8 +65,17 @@
 
 	/* FIXME: this needs a review.
 	 * also: move to cx88-blackbird + cx88-dvb source files? */
+	if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) {
+		/* Report a warning until the mini driver patch is applied,
+		 * else the following conditions will set the dma registers incorrectly.
+		 * This will be removed in the next major patch and changes to the conditions
+		 * will be made.
+		 */
+		printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__);
+		return -EINVAL;
+	}
 
-	if (cx88_boards[core->board].dvb) {
+	if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) {
 		/* negedge driven & software reset */
 		cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
 		udelay(100);
@@ -92,7 +101,7 @@
 		udelay(100);
 	}
 
-	if (cx88_boards[core->board].blackbird) {
+	if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
 		cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
 
 		cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 741e7c5e..58ba9f7 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -142,7 +142,7 @@
 	cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
 	cx88_start_audio_dma(core);
 
-	if (cx88_boards[core->board].blackbird) {
+	if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
 		/* sets sound input from external adc */
 		switch (core->board) {
 		case CX88_BOARD_HAUPPAUGE_ROSLYN:
@@ -164,7 +164,7 @@
 		cx_write(AUD_I2SCNTL, 0);
 		/* cx_write(AUD_APB_IN_RATE_ADJ, 0); */
 	}
-	if ((always_analog) || (!cx88_boards[core->board].blackbird)) {
+	if ((always_analog) || (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))) {
 		ctl |= EN_DAC_ENABLE;
 		cx_write(AUD_CTL, ctl);
 	}
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index fbc79e9..cb0c0ee 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1928,6 +1928,9 @@
 	if (TUNER_ABSENT != core->tuner_type)
 		request_module("tuner");
 
+	if (cx88_boards[ core->board ].audio_chip == AUDIO_CHIP_WM8775)
+		request_module("wm8775");
+
 	/* register v4l devices */
 	dev->video_dev = cx88_vdev_init(core,dev->pci,
 					&cx8800_video_template,"video");
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 89f12e2..3bc91aa 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -30,6 +30,7 @@
 #include <media/tveeprom.h>
 #include <media/video-buf.h>
 #include <media/cx2341x.h>
+#include <media/audiochip.h>
 #include <media/video-buf-dvb.h>
 
 #include "btcx-risc.h"
@@ -39,12 +40,6 @@
 #include <linux/mutex.h>
 #define CX88_VERSION_CODE KERNEL_VERSION(0,0,6)
 
-#ifndef TRUE
-# define TRUE (1==1)
-#endif
-#ifndef FALSE
-# define FALSE (1==0)
-#endif
 #define UNSET (-1U)
 
 #define CX88_MAXBOARDS 8
@@ -73,6 +68,12 @@
 	FM_DEEMPH_75
 };
 
+enum cx88_board_type {
+	CX88_BOARD_NONE = 0,
+	CX88_MPEG_DVB,
+	CX88_MPEG_BLACKBIRD
+};
+
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
 
@@ -230,8 +231,8 @@
 	int                     tda9887_conf;
 	struct cx88_input       input[MAX_CX88_INPUT];
 	struct cx88_input       radio;
-	unsigned int            blackbird:1;
-	unsigned int            dvb:1;
+	enum cx88_board_type    mpeg;
+	enum audiochip          audio_chip;
 };
 
 struct cx88_subid {
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index fba30a4..1457b16 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -64,23 +64,32 @@
 static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 {
 	unsigned char buf[3];
-	int start, toggle, dev, code;
+	int start, range, toggle, dev, code;
 
 	/* poll IR chip */
 	if (3 != i2c_master_recv(&ir->c,buf,3))
 		return -EIO;
 
 	/* split rc5 data block ... */
-	start  = (buf[0] >> 6) &    3;
+	start  = (buf[0] >> 7) &    1;
+	range  = (buf[0] >> 6) &    1;
 	toggle = (buf[0] >> 5) &    1;
 	dev    =  buf[0]       & 0x1f;
 	code   = (buf[1] >> 2) & 0x3f;
 
-	if (3 != start)
+	/* rc5 has two start bits
+	 * the first bit must be one
+	 * the second bit defines the command range (1 = 0-63, 0 = 64 - 127)
+	 */
+	if (!start)
 		/* no key pressed */
 		return 0;
-	dprintk(1,"ir hauppauge (rc5): s%d t%d dev=%d code=%d\n",
-		start, toggle, dev, code);
+
+	if (!range)
+		code += 64;
+
+	dprintk(1,"ir hauppauge (rc5): s%d r%d t%d dev=%d code=%d\n",
+		start, range, toggle, dev, code);
 
 	/* return key */
 	*ir_key = code;
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index 56246b8..cf43df3 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -904,6 +904,8 @@
 	state->has_virtual_dolby_surround = msp_revision == 'G' && msp_prod_lo == 1;
 	/* Has Virtual Dolby Surround & Dolby Pro Logic: only in msp34x2 */
 	state->has_dolby_pro_logic = msp_revision == 'G' && msp_prod_lo == 2;
+	/* The msp343xG supports BTSC only and cannot do Automatic Standard Detection. */
+	state->force_btsc = msp_family == 3 && msp_revision == 'G' && msp_prod_hi == 3;
 
 	state->opmode = opmode;
 	if (state->opmode == OPMODE_AUTO) {
diff --git a/drivers/media/video/msp3400-driver.h b/drivers/media/video/msp3400-driver.h
index 545e4ac0..7531efa 100644
--- a/drivers/media/video/msp3400-driver.h
+++ b/drivers/media/video/msp3400-driver.h
@@ -64,6 +64,7 @@
 	u8 has_sound_processing;
 	u8 has_virtual_dolby_surround;
 	u8 has_dolby_pro_logic;
+	u8 force_btsc;
 
 	int radio;
 	int opmode;
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index ed02ff8..4c7f85b 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -960,9 +960,10 @@
 
 		/* setup the chip*/
 		msp34xxg_reset(client);
-		state->std = state->radio ? 0x40 : msp_standard;
-		/* start autodetect */
+		state->std = state->radio ? 0x40 :
+			(state->force_btsc && msp_standard == 1) ? 32 : msp_standard;
 		msp_write_dem(client, 0x20, state->std);
+		/* start autodetect */
 		if (state->std != 1)
 			goto unmute;
 
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
index a52171e..5645c93 100644
--- a/drivers/media/video/pvrusb2/Kconfig
+++ b/drivers/media/video/pvrusb2/Kconfig
@@ -18,8 +18,8 @@
 	select VIDEO_SAA711X
 	select VIDEO_MSP3400
 	---help---
-	  This option enables support for WinTV-PVR USB2 devices whose 
-	  model number is of the form "29xxx" (leading prefix of "29" 
+	  This option enables support for WinTV-PVR USB2 devices whose
+	  model number is of the form "29xxx" (leading prefix of "29"
 	  followed by 3 digits).
 	  To see if you may need this option, examine the white
 	  sticker on the underside of your device.
@@ -37,14 +37,9 @@
 	  form "24xxx" (leading prefix of "24" followed by 3 digits).
 	  To see if you may need this option, examine the white
 	  sticker on the underside of your device.  Enabling this
-	  option will not harm support for older devices, however it
-	  is a separate option because of the experimental nature of
-	  this new feature.
+	  option will not harm support for older devices.
 
-	  If you are in doubt, say N.
-
-	  Note: This feature is _very_ experimental.  You have been
-	  warned.
+	  If you are in doubt, say Y.
 
 config VIDEO_PVRUSB2_SYSFS
 	bool "pvrusb2 sysfs support (EXPERIMENTAL)"
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 8860436..3d8cd0d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/firmware.h>
 #include <linux/videodev2.h>
+#include <media/v4l2-common.h>
 #include <asm/semaphore.h>
 #include "pvrusb2.h"
 #include "pvrusb2-std.h"
@@ -3131,6 +3132,42 @@
 }
 
 
+int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
+			     u32 chip_id,unsigned long reg_id,
+			     int setFl,u32 *val_ptr)
+{
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	struct list_head *item;
+	struct pvr2_i2c_client *cp;
+	struct v4l2_register req;
+	int stat = 0;
+	int okFl = 0;
+
+	req.i2c_id = chip_id;
+	req.reg = reg_id;
+	if (setFl) req.val = *val_ptr;
+	mutex_lock(&hdw->i2c_list_lock); do {
+		list_for_each(item,&hdw->i2c_clients) {
+			cp = list_entry(item,struct pvr2_i2c_client,list);
+			if (cp->client->driver->id != chip_id) continue;
+			stat = pvr2_i2c_client_cmd(
+				cp,(setFl ? VIDIOC_INT_S_REGISTER :
+				    VIDIOC_INT_G_REGISTER),&req);
+			if (!setFl) *val_ptr = req.val;
+			okFl = !0;
+			break;
+		}
+	} while (0); mutex_unlock(&hdw->i2c_list_lock);
+	if (okFl) {
+		return stat;
+	}
+	return -EINVAL;
+#else
+	return -ENOSYS;
+#endif
+}
+
+
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
   *** Local Variables: ***
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
index fd931b5..29979bb 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.h
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -211,6 +211,14 @@
 /* Store the v4l minor device number */
 void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int);
 
+/* Direct read/write access to chip's registers:
+   chip_id - unique id of chip (e.g. I2C_DRIVERD_xxxx)
+   reg_id  - register number to access
+   setFl   - true to set the register, false to read it
+   val_ptr - storage location for source / result. */
+int pvr2_hdw_register_access(struct pvr2_hdw *,
+			     u32 chip_id,unsigned long reg_id,
+			     int setFl,u32 *val_ptr);
 
 /* The following entry points are all lower level things you normally don't
    want to worry about. */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
index ed3e810..0512166 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -19,6 +19,7 @@
  *
  */
 
+#include <linux/kernel.h>
 #include "pvrusb2-i2c-core.h"
 #include "pvrusb2-hdw-internal.h"
 #include "pvrusb2-debug.h"
@@ -89,7 +90,8 @@
 
 const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx)
 {
-	if (idx >= sizeof(ops)/sizeof(ops[0])) return 0;
+	if (idx >= ARRAY_SIZE(ops))
+		return NULL;
 	return ops[idx];
 }
 
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
index 3608c2f..97e974d 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -29,27 +29,17 @@
 #include "pvrusb2-v4l2.h"
 #include "pvrusb2-ioread.h"
 #include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
 #include <media/v4l2-common.h>
 
 struct pvr2_v4l2_dev;
 struct pvr2_v4l2_fh;
 struct pvr2_v4l2;
 
-/* V4L no longer provide the ability to set / get a private context pointer
-   (i.e. video_get_drvdata / video_set_drvdata), which means we have to
-   concoct our own context locating mechanism.  Supposedly this is intended
-   to simplify driver implementation.  It's not clear to me how that can
-   possibly be true.  Our solution here is to maintain a lookup table of
-   our context instances, indexed by the minor device number of the V4L
-   device.  See pvr2_v4l2_open() for some implications of this approach. */
-static struct pvr2_v4l2_dev *devices[256];
-static DEFINE_MUTEX(device_lock);
-
 struct pvr2_v4l2_dev {
+	struct video_device devbase; /* MUST be first! */
 	struct pvr2_v4l2 *v4lp;
-	struct video_device *vdev;
 	struct pvr2_context_stream *stream;
-	int ctxt_idx;
 	enum pvr2_config config;
 };
 
@@ -74,7 +64,7 @@
 	struct v4l2_prio_state prio;
 
 	/* streams */
-	struct pvr2_v4l2_dev video_dev;
+	struct pvr2_v4l2_dev *vdev;
 };
 
 static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
@@ -671,6 +661,20 @@
 		ret = 0;
 		break;
 	}
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	case VIDIOC_INT_G_REGISTER:
+	case VIDIOC_INT_S_REGISTER:
+	{
+		u32 val;
+		struct v4l2_register *req = (struct v4l2_register *)arg;
+		if (cmd == VIDIOC_INT_S_REGISTER) val = req->val;
+		ret = pvr2_hdw_register_access(
+			hdw,req->i2c_id,req->reg,
+			cmd == VIDIOC_INT_S_REGISTER,&val);
+		if (cmd == VIDIOC_INT_G_REGISTER) req->val = val;
+		break;
+	}
+#endif
 
 	default :
 		ret = v4l_compat_translate_ioctl(inode,file,cmd,
@@ -704,21 +708,22 @@
 static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
 {
 	printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n",
-	       dip->vdev->minor,pvr2_config_get_name(dip->config));
-	if (dip->ctxt_idx >= 0) {
-		mutex_lock(&device_lock);
-		devices[dip->ctxt_idx] = NULL;
-		dip->ctxt_idx = -1;
-		mutex_unlock(&device_lock);
-	}
-	video_unregister_device(dip->vdev);
+	       dip->devbase.minor,pvr2_config_get_name(dip->config));
+
+	/* Paranoia */
+	dip->v4lp = 0;
+	dip->stream = 0;
+
+	/* Actual deallocation happens later when all internal references
+	   are gone. */
+	video_unregister_device(&dip->devbase);
 }
 
 
 static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
 {
 	pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1);
-	pvr2_v4l2_dev_destroy(&vp->video_dev);
+	pvr2_v4l2_dev_destroy(vp->vdev);
 
 	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
 	pvr2_channel_done(&vp->channel);
@@ -726,6 +731,14 @@
 }
 
 
+static void pvr2_video_device_release(struct video_device *vdev)
+{
+	struct pvr2_v4l2_dev *dev;
+	dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
+	kfree(dev);
+}
+
+
 static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
 {
 	struct pvr2_v4l2 *vp;
@@ -797,40 +810,12 @@
 
 static int pvr2_v4l2_open(struct inode *inode, struct file *file)
 {
-	struct pvr2_v4l2_dev *dip = NULL; /* Our own context pointer */
+	struct pvr2_v4l2_dev *dip; /* Our own context pointer */
 	struct pvr2_v4l2_fh *fhp;
 	struct pvr2_v4l2 *vp;
 	struct pvr2_hdw *hdw;
 
-	mutex_lock(&device_lock);
-	/* MCI 7-Jun-2006 Even though we're just doing what amounts to an
-	   atomic read of the device mapping array here, we still need the
-	   mutex.  The problem is that there is a tiny race possible when
-	   we register the device.  We can't update the device mapping
-	   array until after the device has been registered, owing to the
-	   fact that we can't know the minor device number until after the
-	   registration succeeds.  And if another thread tries to open the
-	   device in the window of time after registration but before the
-	   map is updated, then it will get back an erroneous null pointer
-	   and the open will result in a spurious failure.  The only way to
-	   prevent that is to (a) be inside the mutex here before we access
-	   the array, and (b) cover the entire registration process later
-	   on with this same mutex.  Thus if we get inside the mutex here,
-	   then we can be assured that the registration process actually
-	   completed correctly.  This is an unhappy complication from the
-	   use of global data in a driver that lives in a preemptible
-	   environment.  It sure would be nice if the video device itself
-	   had a means for storing and retrieving a local context pointer.
-	   Oh wait.  It did.  But now it's gone.  Silly me. */
-	{
-		unsigned int midx = iminor(file->f_dentry->d_inode);
-		if (midx < sizeof(devices)/sizeof(devices[0])) {
-			dip = devices[midx];
-		}
-	}
-	mutex_unlock(&device_lock);
-
-	if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */
+	dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
 
 	vp = dip->v4lp;
 	hdw = vp->channel.hdw;
@@ -1060,38 +1045,24 @@
 		return;
 	}
 
-	dip->vdev = video_device_alloc();
-	if (!dip->vdev) {
-		err("Alloc of pvrusb2 v4l video device failed");
-		return;
-	}
-
-	memcpy(dip->vdev,&vdev_template,sizeof(vdev_template));
-	dip->vdev->release = video_device_release;
-	mutex_lock(&device_lock);
+	memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
+	dip->devbase.release = pvr2_video_device_release;
 
 	mindevnum = -1;
 	unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
 	if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
 		mindevnum = video_nr[unit_number];
 	}
-	if ((video_register_device(dip->vdev, v4l_type, mindevnum) < 0) &&
-	    (video_register_device(dip->vdev, v4l_type, -1) < 0)) {
+	if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) &&
+	    (video_register_device(&dip->devbase, v4l_type, -1) < 0)) {
 		err("Failed to register pvrusb2 v4l video device");
 	} else {
 		printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n",
-		       dip->vdev->minor,pvr2_config_get_name(dip->config));
+		       dip->devbase.minor,pvr2_config_get_name(dip->config));
 	}
 
-	if ((dip->vdev->minor < sizeof(devices)/sizeof(devices[0])) &&
-	    (devices[dip->vdev->minor] == NULL)) {
-		dip->ctxt_idx = dip->vdev->minor;
-		devices[dip->ctxt_idx] = dip;
-	}
-	mutex_unlock(&device_lock);
-
 	pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
-					dip->vdev->minor);
+					dip->devbase.minor);
 }
 
 
@@ -1102,15 +1073,19 @@
 	vp = kmalloc(sizeof(*vp),GFP_KERNEL);
 	if (!vp) return vp;
 	memset(vp,0,sizeof(*vp));
-	vp->video_dev.ctxt_idx = -1;
+	vp->vdev = kmalloc(sizeof(*vp->vdev),GFP_KERNEL);
+	if (!vp->vdev) {
+		kfree(vp);
+		return 0;
+	}
+	memset(vp->vdev,0,sizeof(*vp->vdev));
 	pvr2_channel_init(&vp->channel,mnp);
 	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
 
 	vp->channel.check_func = pvr2_v4l2_internal_check;
 
 	/* register streams */
-	pvr2_v4l2_dev_init(&vp->video_dev,vp,pvr2_config_mpeg);
-
+	pvr2_v4l2_dev_init(vp->vdev,vp,pvr2_config_mpeg);
 
 	return vp;
 }
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index aa1db50..fe3c83c 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -2965,6 +2965,35 @@
 			.amux = LINE1,
 		},
 	},
+	[SAA7134_BOARD_AVERMEDIA_A16AR] = {
+		/* Petr Baudis <pasky@ucw.cz> */
+		.name           = "AVerMedia TV Hybrid A16AR",
+		.audio_clock    = 0x187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290, /* untested */
+		.radio_type     = TUNER_TEA5767, /* untested */
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.mpeg           = SAA7134_MPEG_DVB,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE2,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+		},
+	},
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -3562,6 +3591,12 @@
 		.subdevice    = 0x2003,
 		.driver_data  = SAA7134_BOARD_PROTEUS_2309,
 	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461,
+		.subdevice    = 0x2c00,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_A16AR,
+	},{
 		/* --- boards without eeprom + subsystem ID --- */
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
@@ -3703,6 +3738,7 @@
 		saa_writeb(SAA7134_GPIO_GPMODE3, 0x08);
 		saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x00);
 		break;
+	case SAA7134_BOARD_AVERMEDIA_A16AR:
 	case SAA7134_BOARD_AVERMEDIA_CARDBUS:
 		/* power-up tuner chip */
 		saa_andorl(SAA7134_GPIO_GPMODE0 >> 2,   0xffffffff, 0xffffffff);
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index b688154..fb741fa 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1055,6 +1055,7 @@
 		}
 		break;
 	case SAA7134_BOARD_AVERMEDIA_777:
+	case SAA7134_BOARD_AVERMEDIA_A16AR:
 		printk("%s: avertv 777 dvb setup\n",dev->name);
 		dev->dvb.frontend = dvb_attach(mt352_attach, &avermedia_777,
 					       &dev->i2c_adap);
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index f7ea857..ff59911 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -185,6 +185,7 @@
 	case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
 	case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
 	case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
+	case SAA7134_BOARD_AVERMEDIA_A16AR:
 		ir_codes     = ir_codes_avermedia;
 		mask_keycode = 0x0007C8;
 		mask_keydown = 0x000010;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 7db7b97..701a909 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -226,6 +226,7 @@
 #define SAA7134_BOARD_MEDION_MD8800_QUADRO 96
 #define SAA7134_BOARD_FLYDVBS_LR300 97
 #define SAA7134_BOARD_PROTEUS_2309 98
+#define SAA7134_BOARD_AVERMEDIA_A16AR   99
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index acc5ea9..f429f49 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -365,7 +365,12 @@
 		if (NULL == fbuf)
 			return -EINVAL;
 		/* FIXME: need sanity checks for vb->boff */
-		bus   = (dma_addr_t)fbuf->base + vb->boff;
+		/*
+		 * Using a double cast to avoid compiler warnings when
+		 * building for PAE. Compiler doesn't like direct casting
+		 * of a 32 bit ptr to 64 bit integer.
+		 */
+		bus   = (dma_addr_t)(unsigned long)fbuf->base + vb->boff;
 		pages = PAGE_ALIGN(vb->size) >> PAGE_SHIFT;
 		err = videobuf_dma_init_overlay(&vb->dma,PCI_DMA_FROMDEVICE,
 						bus, pages);
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 44c59da..c5fdf62 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -276,6 +276,82 @@
 
 #define V4L2_FMT_FLAG_COMPRESSED 0x0001
 
+#if 1
+	/* Experimental Frame Size and frame rate enumeration */
+/*
+ *	F R A M E   S I Z E   E N U M E R A T I O N
+ */
+enum v4l2_frmsizetypes
+{
+	V4L2_FRMSIZE_TYPE_DISCRETE	= 1,
+	V4L2_FRMSIZE_TYPE_CONTINUOUS	= 2,
+	V4L2_FRMSIZE_TYPE_STEPWISE	= 3,
+};
+
+struct v4l2_frmsize_discrete
+{
+	__u32			width;		/* Frame width [pixel] */
+	__u32			height;		/* Frame height [pixel] */
+};
+
+struct v4l2_frmsize_stepwise
+{
+	__u32			min_width;	/* Minimum frame width [pixel] */
+	__u32			max_width;	/* Maximum frame width [pixel] */
+	__u32			step_width;	/* Frame width step size [pixel] */
+	__u32			min_height;	/* Minimum frame height [pixel] */
+	__u32			max_height;	/* Maximum frame height [pixel] */
+	__u32			step_height;	/* Frame height step size [pixel] */
+};
+
+struct v4l2_frmsizeenum
+{
+	__u32			index;		/* Frame size number */
+	__u32			pixel_format;	/* Pixel format */
+	__u32			type;		/* Frame size type the device supports. */
+
+	union {					/* Frame size */
+		struct v4l2_frmsize_discrete	discrete;
+		struct v4l2_frmsize_stepwise	stepwise;
+	};
+
+	__u32   reserved[2];			/* Reserved space for future use */
+};
+
+/*
+ *	F R A M E   R A T E   E N U M E R A T I O N
+ */
+enum v4l2_frmivaltypes
+{
+	V4L2_FRMIVAL_TYPE_DISCRETE	= 1,
+	V4L2_FRMIVAL_TYPE_CONTINUOUS	= 2,
+	V4L2_FRMIVAL_TYPE_STEPWISE	= 3,
+};
+
+struct v4l2_frmival_stepwise
+{
+	struct v4l2_fract	min;		/* Minimum frame interval [s] */
+	struct v4l2_fract	max;		/* Maximum frame interval [s] */
+	struct v4l2_fract	step;		/* Frame interval step size [s] */
+};
+
+struct v4l2_frmivalenum
+{
+	__u32			index;		/* Frame format index */
+	__u32			pixel_format;	/* Pixel format */
+	__u32			width;		/* Frame width */
+	__u32			height;		/* Frame height */
+	__u32			type;		/* Frame interval type the device supports. */
+
+	union {					/* Frame interval */
+		struct v4l2_fract		discrete;
+		struct v4l2_frmival_stepwise	stepwise;
+	};
+
+	__u32	reserved[2];			/* Reserved space for future use */
+};
+#endif
+
 /*
  *	T I M E C O D E
  */
@@ -1249,6 +1325,10 @@
 #define VIDIOC_G_EXT_CTRLS	_IOWR ('V', 71, struct v4l2_ext_controls)
 #define VIDIOC_S_EXT_CTRLS	_IOWR ('V', 72, struct v4l2_ext_controls)
 #define VIDIOC_TRY_EXT_CTRLS	_IOWR ('V', 73, struct v4l2_ext_controls)
+#if 1
+#define VIDIOC_ENUM_FRAMESIZES	_IOWR ('V', 74, struct v4l2_frmsizeenum)
+#define VIDIOC_ENUM_FRAMEINTERVALS	_IOWR ('V', 75, struct v4l2_frmivalenum)
+#endif
 
 #ifdef __OLD_VIDIOC_
 /* for compatibility, will go away some day */
diff --git a/include/media/audiochip.h b/include/media/audiochip.h
index 1fd4a22..db8823d 100644
--- a/include/media/audiochip.h
+++ b/include/media/audiochip.h
@@ -18,7 +18,9 @@
 	AUDIO_CHIP_TDA9874,
 	AUDIO_CHIP_PIC16C54,
 	/* Provided by msp3400.c */
-	AUDIO_CHIP_MSP34XX
+	AUDIO_CHIP_MSP34XX,
+	/* Provided by wm8775.c */
+	AUDIO_CHIP_WM8775
 };
 
 #endif /* AUDIOCHIP_H */