Index: linux/drivers/media/video/cx88/Makefile
===================================================================
RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/Makefile,v
retrieving revision 1.5
diff -u -p -r1.5 Makefile
--- linux/drivers/media/video/cx88/Makefile	26 Nov 2005 20:54:34 -0000	1.5
+++ linux/drivers/media/video/cx88/Makefile	17 Dec 2005 15:36:48 -0000
@@ -4,7 +4,7 @@ cx8800-objs	:= cx88-video.o cx88-vbi.o
 cx8802-objs	:= cx88-mpeg.o
 
 obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o cx88-vp3054-i2c.o
 
 EXTRA_CFLAGS += -I$(src)/..
 EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core
@@ -17,5 +17,6 @@ extra-cflags-$(CONFIG_DVB_LGDT330X)  += 
 extra-cflags-$(CONFIG_DVB_MT352)     += -DHAVE_MT352=1
 extra-cflags-$(CONFIG_DVB_NXT200X)   += -DHAVE_NXT200X=1
 extra-cflags-$(CONFIG_DVB_CX24123)   += -DHAVE_CX24123=1
+extra-cflags-$(CONFIG_VIDEO_CX88_DVB)+= -DHAVE_VP3054_I2C=1
 
 EXTRA_CFLAGS += $(extra-cflags-y) $(extra-cflags-m)
Index: linux/drivers/media/video/cx88/cx88-cards.c
===================================================================
RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88-cards.c,v
retrieving revision 1.113
diff -u -p -r1.113 cx88-cards.c
--- linux/drivers/media/video/cx88/cx88-cards.c	5 Dec 2005 02:31:46 -0000	1.113
+++ linux/drivers/media/video/cx88/cx88-cards.c	17 Dec 2005 15:36:48 -0000
@@ -984,6 +984,33 @@ struct cx88_board cx88_boards[] = {
 		/* fixme: Add radio support */
 		.dvb		= 1,
 	},
+	[CX88_BOARD_DNTV_LIVE_DVB_T_PRO] = {
+		.name           = "digitalnow DNTV Live! DVB-T Pro",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+				  TDA9887_PORT2_ACTIVE,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xf80808,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0	= 0xf80808,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0	= 0xf80808,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0xf80808,
+		},
+		.dvb            = 1,
+	},
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
 
@@ -1167,6 +1194,10 @@ struct cx88_subid cx88_subids[] = {
 		.subvendor = 0x0070,
 		.subdevice = 0x9001,
 		.card      = CX88_BOARD_HAUPPAUGE_DVB_T1,
+	},{
+		.subvendor = 0x1822,
+		.subdevice = 0x0025,
+		.card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
 	},
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
@@ -1364,6 +1395,9 @@ void cx88_card_setup(struct cx88_core *c
 		cx_clear(MO_GP0_IO, 0x00000007);
 		cx_set(MO_GP2_IO, 0x00000101);
 		break;
+	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+		cx_write(MO_GP0_IO, 0x00080808);
+		break;
 	case CX88_BOARD_ATI_HDTVWONDER:
 		if (0 == core->i2c_rc) {
 			/* enable tuner */
Index: linux/drivers/media/video/cx88/cx88-dvb.c
===================================================================
RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88-dvb.c,v
retrieving revision 1.76
diff -u -p -r1.76 cx88-dvb.c
--- linux/drivers/media/video/cx88/cx88-dvb.c	2 Dec 2005 22:08:07 -0000	1.76
+++ linux/drivers/media/video/cx88/cx88-dvb.c	17 Dec 2005 15:36:51 -0000
@@ -4,7 +4,7 @@
  * device driver for Conexant 2388x based TV cards
  * MPEG Transport Stream (DVB) routines
  *
- * (c) 2004 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+ * (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -37,6 +37,9 @@
 #ifdef HAVE_MT352
 # include "mt352.h"
 # include "mt352_priv.h"
+# ifdef HAVE_VP3054_I2C
+#  include "cx88-vp3054-i2c.h"
+# endif
 #endif
 #ifdef HAVE_CX22702
 # include "cx22702.h"
@@ -110,7 +113,7 @@ static struct videobuf_queue_ops dvb_qop
 /* ------------------------------------------------------------------ */
 
 #ifdef HAVE_MT352
-static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
+static int generic_mt352_demod_init(struct dvb_frontend* fe)
 {
 	static u8 clock_config []  = { CLOCK_CTL,  0x38, 0x39 };
 	static u8 reset []         = { RESET,      0x80 };
@@ -168,7 +171,7 @@ static int mt352_pll_set(struct dvb_fron
 
 static struct mt352_config dvico_fusionhdtv = {
 	.demod_address = 0x0F,
-	.demod_init    = dvico_fusionhdtv_demod_init,
+	.demod_init    = generic_mt352_demod_init,
 	.pll_set       = mt352_pll_set,
 };
 
@@ -177,6 +180,69 @@ static struct mt352_config dntv_live_dvb
 	.demod_init    = dntv_live_dvbt_demod_init,
 	.pll_set       = mt352_pll_set,
 };
+
+#ifdef HAVE_VP3054_I2C
+static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+
+	/* this message is to set up ATC and ALC */
+	static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
+	struct i2c_msg msg =
+		{ .addr = dev->core->pll_addr, .flags = 0,
+		  .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
+	int err;
+
+	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+		if (err < 0)
+			return err;
+		else
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
+				      struct dvb_frontend_parameters* params,
+				      u8* pllbuf)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	struct i2c_msg msg =
+		{ .addr = dev->core->pll_addr, .flags = 0,
+		  .buf = pllbuf+1, .len = 4 };
+	int err;
+
+	/* Switch PLL to DVB mode */
+	err = philips_fmd1216_pll_init(fe);
+	if (err)
+		return err;
+
+	/* Tune PLL */
+	pllbuf[0] = dev->core->pll_addr << 1;
+	dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
+			  params->frequency,
+			  params->u.ofdm.bandwidth);
+	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+		printk(KERN_WARNING "cx88-dvb: %s error "
+			   "(addr %02x <- %02x, err = %i)\n",
+			   __FUNCTION__, pllbuf[0], pllbuf[1], err);
+		if (err < 0)
+			return err;
+		else
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static struct mt352_config dntv_live_dvbt_pro_config = {
+	.demod_address = 0x0f,
+	.no_tuner      = 1,
+	.demod_init    = generic_mt352_demod_init,
+	.pll_set       = dntv_live_dvbt_pro_pll_set,
+};
+#endif
 #endif
 
 #ifdef HAVE_CX22702
@@ -405,6 +471,16 @@ static int dvb_register(struct cx8802_de
 		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
 						 &dev->core->i2c_adap);
 		break;
+	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+#ifdef HAVE_VP3054_I2C
+		dev->core->pll_addr = 0x61;
+		dev->core->pll_desc = &dvb_pll_fmd1216me;
+		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
+			&((struct vp3054_i2c_state *)dev->card_priv)->adap);
+#else
+		printk("%s: built without vp3054 support\n", dev->core->name);
+#endif
+		break;
 #endif
 #ifdef HAVE_OR51132
 	case CX88_BOARD_PCHDTV_HD3000:
@@ -534,6 +610,12 @@ static int __devinit dvb_probe(struct pc
 	if (0 != err)
 		goto fail_free;
 
+#ifdef HAVE_VP3054_I2C
+	err = vp3054_i2c_probe(dev);
+	if (0 != err)
+		goto fail_free;
+#endif
+
 	/* dvb stuff */
 	printk("%s/2: cx2388x based dvb card\n", core->name);
 	videobuf_queue_init(&dev->dvb.dvbq, &dvb_qops,
@@ -569,6 +651,10 @@ static void __devexit dvb_remove(struct 
 	/* dvb */
 	videobuf_dvb_unregister(&dev->dvb);
 
+#ifdef HAVE_VP3054_I2C
+	vp3054_i2c_remove(dev);
+#endif
+
 	/* common */
 	cx8802_fini_common(dev);
 	cx88_core_put(dev->core,dev->pci);
Index: linux/drivers/media/video/cx88/cx88-input.c
===================================================================
RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88-input.c,v
retrieving revision 1.26
diff -u -p -r1.26 cx88-input.c
--- linux/drivers/media/video/cx88/cx88-input.c	6 Dec 2005 16:54:58 -0000	1.26
+++ linux/drivers/media/video/cx88/cx88-input.c	17 Dec 2005 15:36:51 -0000
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 2003 Pavel Machek
  * Copyright (c) 2004 Gerd Knorr
- * Copyright (c) 2004 Chris Pascoe
+ * Copyright (c) 2004, 2005 Chris Pascoe
  *
  * 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
@@ -307,6 +307,66 @@ static IR_KEYTAB_TYPE ir_codes_avertv_30
 
 /* ---------------------------------------------------------------------- */
 
+/* DigitalNow DNTV Live! DVB-T Pro Remote */
+static IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE] = {
+	[ 0x16 ] = KEY_POWER,
+	[ 0x5b ] = KEY_HOME,
+
+	[ 0x55 ] = KEY_TV,		/* live tv */
+	[ 0x58 ] = KEY_TUNER,		/* digital Radio */
+	[ 0x5a ] = KEY_RADIO,		/* FM radio */
+	[ 0x59 ] = KEY_DVD,		/* dvd menu */
+	[ 0x03 ] = KEY_1,
+	[ 0x01 ] = KEY_2,
+	[ 0x06 ] = KEY_3,
+	[ 0x09 ] = KEY_4,
+	[ 0x1d ] = KEY_5,
+	[ 0x1f ] = KEY_6,
+	[ 0x0d ] = KEY_7,
+	[ 0x19 ] = KEY_8,
+	[ 0x1b ] = KEY_9,
+	[ 0x0c ] = KEY_CANCEL,
+	[ 0x15 ] = KEY_0,
+	[ 0x4a ] = KEY_CLEAR,
+	[ 0x13 ] = KEY_BACK,
+	[ 0x00 ] = KEY_TAB,
+	[ 0x4b ] = KEY_UP,
+	[ 0x4e ] = KEY_LEFT,
+	[ 0x4f ] = KEY_OK,
+	[ 0x52 ] = KEY_RIGHT,
+	[ 0x51 ] = KEY_DOWN,
+	[ 0x1e ] = KEY_VOLUMEUP,
+	[ 0x0a ] = KEY_VOLUMEDOWN,
+	[ 0x02 ] = KEY_CHANNELDOWN,
+	[ 0x05 ] = KEY_CHANNELUP,
+	[ 0x11 ] = KEY_RECORD,
+	[ 0x14 ] = KEY_PLAY,
+	[ 0x4c ] = KEY_PAUSE,
+	[ 0x1a ] = KEY_STOP,
+	[ 0x40 ] = KEY_REWIND,
+	[ 0x12 ] = KEY_FASTFORWARD,
+	[ 0x41 ] = KEY_PREVIOUSSONG,	/* replay |< */
+	[ 0x42 ] = KEY_NEXTSONG,	/* skip >| */
+	[ 0x54 ] = KEY_CAMERA,		/* capture */
+	[ 0x50 ] = KEY_LANGUAGE,	/* sap */
+	[ 0x47 ] = KEY_TV2,		/* pip */
+	[ 0x4d ] = KEY_SCREEN,
+	[ 0x43 ] = KEY_SUBTITLE,
+	[ 0x10 ] = KEY_MUTE,
+	[ 0x49 ] = KEY_AUDIO,		/* l/r */
+	[ 0x07 ] = KEY_SLEEP,
+	[ 0x08 ] = KEY_VIDEO,		/* a/v */
+	[ 0x0e ] = KEY_PREVIOUS,	/* recall */
+	[ 0x45 ] = KEY_ZOOM,		/* zoom + */
+	[ 0x46 ] = KEY_ANGLE,		/* zoom - */
+	[ 0x56 ] = KEY_RED,
+	[ 0x57 ] = KEY_GREEN,
+	[ 0x5c ] = KEY_YELLOW,
+	[ 0x5d ] = KEY_BLUE,
+};
+
+/* ---------------------------------------------------------------------- */
+
 struct cx88_IR {
 	struct cx88_core *core;
 	struct input_dev *input;
@@ -315,7 +375,7 @@ struct cx88_IR {
 	char phys[32];
 
 	/* sample from gpio pin 16 */
-	int sampling;
+	u32 sampling;
 	u32 samples[16];
 	int scount;
 	unsigned long release;
@@ -433,7 +493,7 @@ int cx88_ir_init(struct cx88_core *core,
 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
 		ir_codes = ir_codes_cinergy_1400;
 		ir_type = IR_TYPE_PD;
-		ir->sampling = 1;
+		ir->sampling = 0xeb04; /* address */
 		break;
 	case CX88_BOARD_HAUPPAUGE:
 	case CX88_BOARD_HAUPPAUGE_DVB_T1:
@@ -486,6 +546,11 @@ int cx88_ir_init(struct cx88_core *core,
 		ir->mask_keydown = 0x02;
 		ir->polling      = 50; /* ms */
 		break;
+	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
+		ir_codes = ir_codes_dntv_live_dvbt_pro;
+		ir_type = IR_TYPE_PD;
+		ir->sampling = 0xff00; /* address */
+		break;
 	}
 
 	if (NULL == ir_codes) {
@@ -549,6 +614,10 @@ int cx88_ir_fini(struct cx88_core *core)
 	if (NULL == ir)
 		return 0;
 
+	if (ir->sampling) {
+		cx_write(MO_DDSCFG_IO, 0x0);
+		core->pci_irqmask &= ~(1 << 18);
+	}
 	if (ir->polling) {
 		del_timer(&ir->timer);
 		flush_scheduled_work();
@@ -600,6 +669,7 @@ void cx88_ir_irq(struct cx88_core *core)
 	/* decode it */
 	switch (core->board) {
 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
+	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
 		ircode = ir_decode_pulsedistance(ir->samples, ir->scount, 1, 4);
 
 		if (ircode == 0xffffffff) { /* decoding error */
@@ -615,7 +685,7 @@ void cx88_ir_irq(struct cx88_core *core)
 			break;
 		}
 
-		if ((ircode & 0xffff) != 0xeb04) { /* wrong address */
+		if ((ircode & 0xffff) != (ir->sampling & 0xffff)) { /* wrong address */
 			ir_dprintk("pulse distance decoded wrong address\n");
 			break;
 		}
Index: linux/drivers/media/video/cx88/cx88.h
===================================================================
RCS file: /cvs/video4linux/v4l-dvb/linux/drivers/media/video/cx88/cx88.h,v
retrieving revision 1.94
diff -u -p -r1.94 cx88.h
--- linux/drivers/media/video/cx88/cx88.h	7 Dec 2005 11:51:19 -0000	1.94
+++ linux/drivers/media/video/cx88/cx88.h	17 Dec 2005 15:36:52 -0000
@@ -191,6 +191,7 @@ extern struct sram_channel cx88_sram_cha
 #define CX88_BOARD_KWORLD_DVBS_100         39
 #define CX88_BOARD_HAUPPAUGE_HVR1100       40
 #define CX88_BOARD_HAUPPAUGE_HVR1100LP     41
+#define CX88_BOARD_DNTV_LIVE_DVB_T_PRO     42
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,
@@ -456,6 +457,8 @@ struct cx8802_dev {
 	struct videobuf_dvb        dvb;
 	void*                      fe_handle;
 	int                        (*fe_release)(void *handle);
+
+	void			   *card_priv;
 #endif
 	/* for switching modulation types */
 	unsigned char              ts_gen_cntrl;
Index: v4l/Makefile
===================================================================
RCS file: /cvs/video4linux/v4l-dvb/v4l/Makefile,v
retrieving revision 1.123
diff -u -p -r1.123 Makefile
--- v4l/Makefile	16 Dec 2005 04:15:08 -0000	1.123
+++ v4l/Makefile	17 Dec 2005 15:36:53 -0000
@@ -89,7 +89,7 @@ obj-$(CONFIG_VIDEO_TUNER)	+= tuner.o tda
 obj-$(CONFIG_VIDEO_TVAUDIO)	+= msp3400.o tvaudio.o tvmixer.o wm8775.o \
 				   cs53l32a.o
 
-obj-$(CONFIG_VIDEO_CX88_DVB)	+= video-buf-dvb.o cx88-dvb.o
+obj-$(CONFIG_VIDEO_CX88_DVB)	+= video-buf-dvb.o cx88-dvb.o cx88-vp3054-i2c.o
 obj-$(CONFIG_VIDEO_SAA7134_DVB) += video-buf-dvb.o saa7134-dvb.o
 obj-$(CONFIG_DVB_BT8XX)		+= bt878.o dvb-bt8xx.o dst.o dst_ca.o
 obj-$(CONFIG_DVB_FRONTENDS)	+= dvb-pll.o cx22702.o or51132.o lgdt330x.o \
@@ -156,6 +156,7 @@ ifeq ($(CONFIG_VIDEO_CX88_DVB),m)
  EXTRA_CFLAGS += -DHAVE_MT352=1
  EXTRA_CFLAGS += -DHAVE_NXT200X=1
  EXTRA_CFLAGS += -DHAVE_CX24123=1
+ EXTRA_CFLAGS += -DHAVE_VP3054_I2C=1
 endif
 ifeq ($(CONFIG_VIDEO_SAA7134_DVB),m)
  EXTRA_CFLAGS += -DHAVE_MT352=1
--- /dev/null	2005-03-26 23:52:38.000000000 +1000
+++ linux/drivers/media/video/cx88/cx88-vp3054-i2c.h	2005-12-18 01:36:15.000000000 +1000
@@ -0,0 +1,36 @@
+/*
+    $Id: $
+
+    cx88-vp3054-i2c.h  --  support for the secondary I2C bus of the
+                           DNTV Live! DVB-T Pro (VP-3054), wired as:
+                           GPIO[0] -> SCL, GPIO[1] -> SDA
+
+    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/* ----------------------------------------------------------------------- */
+struct vp3054_i2c_state {
+	struct i2c_adapter         adap;
+	struct i2c_algo_bit_data   algo;
+	struct i2c_client          client;
+	u32                        state;
+};
+
+/* ----------------------------------------------------------------------- */
+int  vp3054_i2c_probe(struct cx8802_dev *dev);
+void vp3054_i2c_remove(struct cx8802_dev *dev);
--- /dev/null	2005-03-26 23:52:38.000000000 +1000
+++ linux/drivers/media/video/cx88/cx88-vp3054-i2c.c	2005-12-18 01:36:26.000000000 +1000
@@ -0,0 +1,184 @@
+/*
+    $Id: $
+
+    cx88-vp3054-i2c.c  --  support for the secondary I2C bus of the
+                           DNTV Live! DVB-T Pro (VP-3054), wired as:
+                           GPIO[0] -> SCL, GPIO[1] -> SDA
+
+    (c) 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#include "compat.h"
+#include "cx88.h"
+#include "cx88-vp3054-i2c.h"
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+#include <media/i2c-compat.h>
+#endif
+
+/* ----------------------------------------------------------------------- */
+
+static void vp3054_bit_setscl(void *data, int state)
+{
+	struct cx8802_dev *dev = data;
+	struct cx88_core *core = dev->core;
+	struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+	if (state) {
+		vp3054_i2c->state |=  0x0001;	/* SCL high */
+		vp3054_i2c->state &= ~0x0100;	/* external pullup */
+	} else {
+		vp3054_i2c->state &= ~0x0001;	/* SCL low */
+		vp3054_i2c->state |=  0x0100;	/* drive pin */
+	}
+	cx_write(MO_GP0_IO, 0x010000 | vp3054_i2c->state);
+	cx_read(MO_GP0_IO);
+}
+
+static void vp3054_bit_setsda(void *data, int state)
+{
+	struct cx8802_dev *dev = data;
+	struct cx88_core *core = dev->core;
+	struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+	if (state) {
+		vp3054_i2c->state |=  0x0002;	/* SDA high */
+		vp3054_i2c->state &= ~0x0200;	/* tristate pin */
+	} else {
+		vp3054_i2c->state &= ~0x0002;	/* SDA low */
+		vp3054_i2c->state |=  0x0200;	/* drive pin */
+	}
+	cx_write(MO_GP0_IO, 0x020000 | vp3054_i2c->state);
+	cx_read(MO_GP0_IO);
+}
+
+static int vp3054_bit_getscl(void *data)
+{
+	struct cx8802_dev *dev = data;
+	struct cx88_core *core = dev->core;
+	u32 state;
+
+	state = cx_read(MO_GP0_IO);
+	return (state & 0x01) ? 1 : 0;
+}
+
+static int vp3054_bit_getsda(void *data)
+{
+	struct cx8802_dev *dev = data;
+	struct cx88_core *core = dev->core;
+	u32 state;
+
+	state = cx_read(MO_GP0_IO);
+	return (state & 0x02) ? 1 : 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
+	.setsda  = vp3054_bit_setsda,
+	.setscl  = vp3054_bit_setscl,
+	.getsda  = vp3054_bit_getsda,
+	.getscl  = vp3054_bit_getscl,
+	.udelay  = 16,
+	.mdelay  = 10,
+	.timeout = 200,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter vp3054_i2c_adap_template = {
+	.name              = "cx2388x",
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+	.owner             = THIS_MODULE,
+#endif
+	.id                = I2C_HW_B_CX2388x,
+};
+
+static struct i2c_client vp3054_i2c_client_template = {
+	.name	= "VP-3054",
+};
+
+int vp3054_i2c_probe(struct cx8802_dev *dev)
+{
+	struct cx88_core *core = dev->core;
+	struct vp3054_i2c_state *vp3054_i2c;
+	int rc;
+
+	if (core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+		return 0;
+
+	dev->card_priv = kzalloc(sizeof(*vp3054_i2c), GFP_KERNEL);
+	if (dev->card_priv == NULL)
+		return -ENOMEM;
+	vp3054_i2c = dev->card_priv;
+
+	memcpy(&vp3054_i2c->adap, &vp3054_i2c_adap_template,
+	       sizeof(vp3054_i2c->adap));
+	memcpy(&vp3054_i2c->algo, &vp3054_i2c_algo_template,
+	       sizeof(vp3054_i2c->algo));
+	memcpy(&vp3054_i2c->client, &vp3054_i2c_client_template,
+	       sizeof(vp3054_i2c->client));
+
+#ifdef I2C_CLASS_TV_DIGITAL
+	vp3054_i2c->adap.class |= I2C_CLASS_TV_DIGITAL;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,66)
+	vp3054_i2c->adap.dev.parent = &dev->pci->dev;
+#endif
+	strlcpy(vp3054_i2c->adap.name, core->name,
+		sizeof(vp3054_i2c->adap.name));
+	vp3054_i2c->algo.data = dev;
+	i2c_set_adapdata(&vp3054_i2c->adap, dev);
+	vp3054_i2c->adap.algo_data = &vp3054_i2c->algo;
+	vp3054_i2c->client.adapter = &vp3054_i2c->adap;
+
+	vp3054_bit_setscl(dev,1);
+	vp3054_bit_setsda(dev,1);
+
+	rc = i2c_bit_add_bus(&vp3054_i2c->adap);
+	if (0 != rc) {
+		printk("%s: vp3054_i2c register FAILED\n", core->name);
+
+		kfree(dev->card_priv);
+		dev->card_priv = NULL;
+	}
+
+	return rc;
+}
+
+void vp3054_i2c_remove(struct cx8802_dev *dev)
+{
+	struct vp3054_i2c_state *vp3054_i2c = dev->card_priv;
+
+	if (vp3054_i2c == NULL ||
+	    dev->core->board != CX88_BOARD_DNTV_LIVE_DVB_T_PRO)
+		return;
+
+	i2c_bit_del_bus(&vp3054_i2c->adap);
+	kfree(vp3054_i2c);
+}
+
+EXPORT_SYMBOL(vp3054_i2c_probe);
+EXPORT_SYMBOL(vp3054_i2c_remove);
