Merge branch 'mantis' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'mantis' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (117 commits)
  V4L/DVB (13851): Fix Input dependency for Mantis
  V4L/DVB(13824a): mantis: Fix __devexit bad annotations
  V4L/DVB (13808b): mantis: replace DMA_nnBIT_MASK to DMA_BIT_MASK(32)
  V4L/DVB (13808): [Mantis/Hopper] Build update for Mantis/Hopper based cards
  V4L/DVB(13808a): mantis: convert it to the new ir-core register/unregister functions
  V4L/DVB (13812): [Mantis/Hopper] Update Copyright header
  V4L/DVB (13811): [MB86A16] Update Copyright header
  V4L/DVB (13810): [MB86A16] Use DVB_* macros
  V4L/DVB (13809): Fix Checkpatch violations
  V4L/DVB (13807): Fix: Free device in the device registration failure case
  V4L/DVB (13806): Register and Initialize Remote control
  V4L/DVB (13805): Fix: Unregister the frontend before detaching
  V4L/DVB (13804): Remove unused I2C Adapter ID
  V4L/DVB (13803): Remove unused dependency on CU1216
  V4L/DVB (13802): [Mantis/Hopper] Fix all build related warnings
  V4L/DVB (13801): [MB86A16] Use the search callback
  V4L/DVB (13800): [Mantis] I2C optimization. Required delay is much lesser than 1mS.
  V4L/DVB (13799): [Mantis] Unregister frontend
  V4L/DVB (13798): [Mantis] Enable power for all cards, use byte mode only on relevant devices
  V4L/DVB (13797): [Mantis/Hopper/TDA665x] Large overhaul,
  ...
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 35d0817..cf8f65f 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -72,6 +72,10 @@
 	depends on DVB_CORE && PCI && I2C
 source "drivers/media/dvb/pt1/Kconfig"
 
+comment "Supported Mantis Adapters"
+	depends on DVB_CORE && PCI && I2C
+	source "drivers/media/dvb/mantis/Kconfig"
+
 comment "Supported DVB Frontends"
 	depends on DVB_CORE
 source "drivers/media/dvb/frontends/Kconfig"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index 16d262d..c12922c 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,6 +2,18 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dvb-usb/ pluto2/ siano/ dm1105/ pt1/
+obj-y        := dvb-core/	\
+		frontends/	\
+		ttpci/		\
+		ttusb-dec/	\
+		ttusb-budget/	\
+		b2c2/		\
+		bt8xx/		\
+		dvb-usb/	\
+		pluto2/		\
+		siano/		\
+		dm1105/		\
+		pt1/		\
+		mantis/
 
 obj-$(CONFIG_DVB_FIREDTV)	+= firewire/
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index a3b8b697..cd7f9b7 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -208,6 +208,14 @@
 	help
 	  A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
 
+config DVB_MB86A16
+	tristate "Fujitsu MB86A16 based"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-S/DSS Direct Conversion reveiver.
+	  Say Y when you want to support this frontend.
+
 comment "DVB-T (terrestrial) frontends"
 	depends on DVB_CORE
 
@@ -587,6 +595,17 @@
 	help
 	  A DMB-TH tuner module. Say Y when you want to support this frontend.
 
+config DVB_TDA665x
+	tristate "TDA665x tuner"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  Support for tuner modules based on Philips TDA6650/TDA6651 chips.
+	  Say Y when you want to support this chip.
+
+	  Currently supported tuners:
+	  * Panasonic ENV57H12D5 (ET-50DT)
+
 comment "Tools to develop new frontends"
 
 config DVB_DUMMY_FE
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 47575cc..874e8ad 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -64,6 +64,7 @@
 obj-$(CONFIG_DVB_TUNER_CX24113) += cx24113.o
 obj-$(CONFIG_DVB_S5H1411) += s5h1411.o
 obj-$(CONFIG_DVB_LGS8GL5) += lgs8gl5.o
+obj-$(CONFIG_DVB_TDA665x) += tda665x.o
 obj-$(CONFIG_DVB_LGS8GXX) += lgs8gxx.o
 obj-$(CONFIG_DVB_ATBM8830) += atbm8830.o
 obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
@@ -80,3 +81,4 @@
 obj-$(CONFIG_DVB_ISL6423) += isl6423.o
 obj-$(CONFIG_DVB_EC100) += ec100.o
 obj-$(CONFIG_DVB_DS3000) += ds3000.o
+obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
diff --git a/drivers/media/dvb/frontends/mb86a16.c b/drivers/media/dvb/frontends/mb86a16.c
new file mode 100644
index 0000000..d05f750
--- /dev/null
+++ b/drivers/media/dvb/frontends/mb86a16.c
@@ -0,0 +1,1878 @@
+/*
+	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include "dvb_frontend.h"
+#include "mb86a16.h"
+#include "mb86a16_priv.h"
+
+unsigned int verbose = 5;
+module_param(verbose, int, 0644);
+
+#define ABS(x)		((x) < 0 ? (-x) : (x))
+
+struct mb86a16_state {
+	struct i2c_adapter		*i2c_adap;
+	const struct mb86a16_config	*config;
+	struct dvb_frontend		frontend;
+
+	/* tuning parameters */
+	int				frequency;
+	int				srate;
+
+	/* Internal stuff */
+	int				master_clk;
+	int				deci;
+	int				csel;
+	int				rsel;
+};
+
+#define MB86A16_ERROR		0
+#define MB86A16_NOTICE		1
+#define MB86A16_INFO		2
+#define MB86A16_DEBUG		3
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((x > MB86A16_ERROR) && (x > y))				\
+			printk(KERN_ERR "%s: " format "\n", __func__, ##arg);		\
+		else if ((x > MB86A16_NOTICE) && (x > y))				\
+			printk(KERN_NOTICE "%s: " format "\n", __func__, ##arg);	\
+		else if ((x > MB86A16_INFO) && (x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__, ##arg);		\
+		else if ((x > MB86A16_DEBUG) && (x > y))				\
+			printk(KERN_DEBUG "%s: " format "\n", __func__, ##arg);		\
+	} else {									\
+		if (x > y)								\
+			printk(format, ##arg);						\
+	}										\
+} while (0)
+
+#define TRACE_IN	dprintk(verbose, MB86A16_DEBUG, 1, "-->()")
+#define TRACE_OUT	dprintk(verbose, MB86A16_DEBUG, 1, "()-->")
+
+static int mb86a16_write(struct mb86a16_state *state, u8 reg, u8 val)
+{
+	int ret;
+	u8 buf[] = { reg, val };
+
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address,
+		.flags = 0,
+		.buf = buf,
+		.len = 2
+	};
+
+	dprintk(verbose, MB86A16_DEBUG, 1,
+		"writing to [0x%02x],Reg[0x%02x],Data[0x%02x]",
+		state->config->demod_address, buf[0], buf[1]);
+
+	ret = i2c_transfer(state->i2c_adap, &msg, 1);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int mb86a16_read(struct mb86a16_state *state, u8 reg, u8 *val)
+{
+	int ret;
+	u8 b0[] = { reg };
+	u8 b1[] = { 0 };
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = state->config->demod_address,
+			.flags = 0,
+			.buf = b0,
+			.len = 1
+		}, {
+			.addr = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+	ret = i2c_transfer(state->i2c_adap, msg, 2);
+	if (ret != 2) {
+		dprintk(verbose, MB86A16_ERROR, 1, "read error(reg=0x%02x, ret=0x%i)",
+			reg, ret);
+
+		return -EREMOTEIO;
+	}
+	*val = b1[0];
+
+	return ret;
+}
+
+static int CNTM_set(struct mb86a16_state *state,
+		    unsigned char timint1,
+		    unsigned char timint2,
+		    unsigned char cnext)
+{
+	unsigned char val;
+
+	val = (timint1 << 4) | (timint2 << 2) | cnext;
+	if (mb86a16_write(state, MB86A16_CNTMR, val) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int smrt_set(struct mb86a16_state *state, int rate)
+{
+	int tmp ;
+	int m ;
+	unsigned char STOFS0, STOFS1;
+
+	m = 1 << state->deci;
+	tmp = (8192 * state->master_clk - 2 * m * rate * 8192 + state->master_clk / 2) / state->master_clk;
+
+	STOFS0 = tmp & 0x0ff;
+	STOFS1 = (tmp & 0xf00) >> 8;
+
+	if (mb86a16_write(state, MB86A16_SRATE1, (state->deci << 2) |
+				       (state->csel << 1) |
+					state->rsel) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_SRATE2, STOFS0) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_SRATE3, STOFS1) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -1;
+}
+
+static int srst(struct mb86a16_state *state)
+{
+	if (mb86a16_write(state, MB86A16_RESET, 0x04) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+
+}
+
+static int afcex_data_set(struct mb86a16_state *state,
+			  unsigned char AFCEX_L,
+			  unsigned char AFCEX_H)
+{
+	if (mb86a16_write(state, MB86A16_AFCEXL, AFCEX_L) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_AFCEXH, AFCEX_H) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+
+	return -1;
+}
+
+static int afcofs_data_set(struct mb86a16_state *state,
+			   unsigned char AFCEX_L,
+			   unsigned char AFCEX_H)
+{
+	if (mb86a16_write(state, 0x58, AFCEX_L) < 0)
+		goto err;
+	if (mb86a16_write(state, 0x59, AFCEX_H) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int stlp_set(struct mb86a16_state *state,
+		    unsigned char STRAS,
+		    unsigned char STRBS)
+{
+	if (mb86a16_write(state, MB86A16_STRFILTCOEF1, (STRBS << 3) | (STRAS)) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int Vi_set(struct mb86a16_state *state, unsigned char ETH, unsigned char VIA)
+{
+	if (mb86a16_write(state, MB86A16_VISET2, 0x04) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_VISET3, 0xf5) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int initial_set(struct mb86a16_state *state)
+{
+	if (stlp_set(state, 5, 7))
+		goto err;
+
+	udelay(100);
+	if (afcex_data_set(state, 0, 0))
+		goto err;
+
+	udelay(100);
+	if (afcofs_data_set(state, 0, 0))
+		goto err;
+
+	udelay(100);
+	if (mb86a16_write(state, MB86A16_CRLFILTCOEF1, 0x16) < 0)
+		goto err;
+	if (mb86a16_write(state, 0x2f, 0x21) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_VIMAG, 0x38) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS1, 0x00) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS2, 0x1c) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS3, 0x20) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS4, 0x1e) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_FAGCS5, 0x23) < 0)
+		goto err;
+	if (mb86a16_write(state, 0x54, 0xff) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_TSOUT, 0x00) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int S01T_set(struct mb86a16_state *state,
+		    unsigned char s1t,
+		    unsigned s0t)
+{
+	if (mb86a16_write(state, 0x33, (s1t << 3) | s0t) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+
+static int EN_set(struct mb86a16_state *state,
+		  int cren,
+		  int afcen)
+{
+	unsigned char val;
+
+	val = 0x7a | (cren << 7) | (afcen << 2);
+	if (mb86a16_write(state, 0x49, val) < 0)
+		goto err;
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int AFCEXEN_set(struct mb86a16_state *state,
+		       int afcexen,
+		       int smrt)
+{
+	unsigned char AFCA ;
+
+	if (smrt > 18875)
+		AFCA = 4;
+	else if (smrt > 9375)
+		AFCA = 3;
+	else if (smrt > 2250)
+		AFCA = 2;
+	else
+		AFCA = 1;
+
+	if (mb86a16_write(state, 0x2a, 0x02 | (afcexen << 5) | (AFCA << 2)) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int DAGC_data_set(struct mb86a16_state *state,
+			 unsigned char DAGCA,
+			 unsigned char DAGCW)
+{
+	if (mb86a16_write(state, 0x2d, (DAGCA << 3) | DAGCW) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static void smrt_info_get(struct mb86a16_state *state, int rate)
+{
+	if (rate >= 37501) {
+		state->deci = 0; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 30001) {
+		state->deci = 0; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 26251) {
+		state->deci = 0; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 22501) {
+		state->deci = 0; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 18751) {
+		state->deci = 1; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 15001) {
+		state->deci = 1; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 13126) {
+		state->deci = 1; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 11251) {
+		state->deci = 1; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 9376) {
+		state->deci = 2; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 7501) {
+		state->deci = 2; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 6563) {
+		state->deci = 2; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 5626) {
+		state->deci = 2; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 4688) {
+		state->deci = 3; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 3751) {
+		state->deci = 3; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 3282) {
+		state->deci = 3; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 2814) {
+		state->deci = 3; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 2344) {
+		state->deci = 4; state->csel = 0; state->rsel = 0;
+	} else if (rate >= 1876) {
+		state->deci = 4; state->csel = 0; state->rsel = 1;
+	} else if (rate >= 1641) {
+		state->deci = 4; state->csel = 1; state->rsel = 0;
+	} else if (rate >= 1407) {
+		state->deci = 4; state->csel = 1; state->rsel = 1;
+	} else if (rate >= 1172) {
+		state->deci = 5; state->csel = 0; state->rsel = 0;
+	} else if (rate >=  939) {
+		state->deci = 5; state->csel = 0; state->rsel = 1;
+	} else if (rate >=  821) {
+		state->deci = 5; state->csel = 1; state->rsel = 0;
+	} else {
+		state->deci = 5; state->csel = 1; state->rsel = 1;
+	}
+
+	if (state->csel == 0)
+		state->master_clk = 92000;
+	else
+		state->master_clk = 61333;
+
+}
+
+static int signal_det(struct mb86a16_state *state,
+		      int smrt,
+		      unsigned char *SIG)
+{
+
+	int ret ;
+	int smrtd ;
+	int wait_sym ;
+
+	u32 wait_t;
+	unsigned char S[3] ;
+	int i ;
+
+	if (*SIG > 45) {
+		if (CNTM_set(state, 2, 1, 2) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
+			return -1;
+		}
+		wait_sym = 40000;
+	} else {
+		if (CNTM_set(state, 3, 1, 2) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
+			return -1;
+		}
+		wait_sym = 80000;
+	}
+	for (i = 0; i < 3; i++) {
+		if (i == 0)
+			smrtd = smrt * 98 / 100;
+		else if (i == 1)
+			smrtd = smrt;
+		else
+			smrtd = smrt * 102 / 100;
+		smrt_info_get(state, smrtd);
+		smrt_set(state, smrtd);
+		srst(state);
+		wait_t = (wait_sym + 99 * smrtd / 100) / smrtd;
+		if (wait_t == 0)
+			wait_t = 1;
+		msleep_interruptible(10);
+		if (mb86a16_read(state, 0x37, &(S[i])) != 2) {
+			dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+			return -EREMOTEIO;
+		}
+	}
+	if ((S[1] > S[0] * 112 / 100) &&
+	    (S[1] > S[2] * 112 / 100)) {
+
+		ret = 1;
+	} else {
+		ret = 0;
+	}
+	*SIG = S[1];
+
+	if (CNTM_set(state, 0, 1, 2) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "CNTM set Error");
+		return -1;
+	}
+
+	return ret;
+}
+
+static int rf_val_set(struct mb86a16_state *state,
+		      int f,
+		      int smrt,
+		      unsigned char R)
+{
+	unsigned char C, F, B;
+	int M;
+	unsigned char rf_val[5];
+	int ack = -1;
+
+	if (smrt > 37750)
+		C = 1;
+	else if (smrt > 18875)
+		C = 2;
+	else if (smrt > 5500)
+		C = 3;
+	else
+		C = 4;
+
+	if (smrt > 30500)
+		F = 3;
+	else if (smrt > 9375)
+		F = 1;
+	else if (smrt > 4625)
+		F = 0;
+	else
+		F = 2;
+
+	if (f < 1060)
+		B = 0;
+	else if (f < 1175)
+		B = 1;
+	else if (f < 1305)
+		B = 2;
+	else if (f < 1435)
+		B = 3;
+	else if (f < 1570)
+		B = 4;
+	else if (f < 1715)
+		B = 5;
+	else if (f < 1845)
+		B = 6;
+	else if (f < 1980)
+		B = 7;
+	else if (f < 2080)
+		B = 8;
+	else
+		B = 9;
+
+	M = f * (1 << R) / 2;
+
+	rf_val[0] = 0x01 | (C << 3) | (F << 1);
+	rf_val[1] = (R << 5) | ((M & 0x1f000) >> 12);
+	rf_val[2] = (M & 0x00ff0) >> 4;
+	rf_val[3] = ((M & 0x0000f) << 4) | B;
+
+	/* Frequency Set */
+	if (mb86a16_write(state, 0x21, rf_val[0]) < 0)
+		ack = 0;
+	if (mb86a16_write(state, 0x22, rf_val[1]) < 0)
+		ack = 0;
+	if (mb86a16_write(state, 0x23, rf_val[2]) < 0)
+		ack = 0;
+	if (mb86a16_write(state, 0x24, rf_val[3]) < 0)
+		ack = 0;
+	if (mb86a16_write(state, 0x25, 0x01) < 0)
+		ack = 0;
+	if (ack == 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "RF Setup - I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int afcerr_chk(struct mb86a16_state *state)
+{
+	unsigned char AFCM_L, AFCM_H ;
+	int AFCM ;
+	int afcm, afcerr ;
+
+	if (mb86a16_read(state, 0x0e, &AFCM_L) != 2)
+		goto err;
+	if (mb86a16_read(state, 0x0f, &AFCM_H) != 2)
+		goto err;
+
+	AFCM = (AFCM_H << 8) + AFCM_L;
+
+	if (AFCM > 2048)
+		afcm = AFCM - 4096;
+	else
+		afcm = AFCM;
+	afcerr = afcm * state->master_clk / 8192;
+
+	return afcerr;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int dagcm_val_get(struct mb86a16_state *state)
+{
+	int DAGCM;
+	unsigned char DAGCM_H, DAGCM_L;
+
+	if (mb86a16_read(state, 0x45, &DAGCM_L) != 2)
+		goto err;
+	if (mb86a16_read(state, 0x46, &DAGCM_H) != 2)
+		goto err;
+
+	DAGCM = (DAGCM_H << 8) + DAGCM_L;
+
+	return DAGCM;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int mb86a16_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	u8 stat, stat2;
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	*status = 0;
+
+	if (mb86a16_read(state, MB86A16_SIG1, &stat) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_SIG2, &stat2) != 2)
+		goto err;
+	if ((stat > 25) && (stat2 > 25))
+		*status |= FE_HAS_SIGNAL;
+	if ((stat > 45) && (stat2 > 45))
+		*status |= FE_HAS_CARRIER;
+
+	if (mb86a16_read(state, MB86A16_STATUS, &stat) != 2)
+		goto err;
+
+	if (stat & 0x01)
+		*status |= FE_HAS_SYNC;
+	if (stat & 0x01)
+		*status |= FE_HAS_VITERBI;
+
+	if (mb86a16_read(state, MB86A16_FRAMESYNC, &stat) != 2)
+		goto err;
+
+	if ((stat & 0x0f) && (*status & FE_HAS_VITERBI))
+		*status |= FE_HAS_LOCK;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int sync_chk(struct mb86a16_state *state,
+		    unsigned char *VIRM)
+{
+	unsigned char val;
+	int sync;
+
+	if (mb86a16_read(state, 0x0d, &val) != 2)
+		goto err;
+
+	dprintk(verbose, MB86A16_INFO, 1, "Status = %02x,", val);
+	sync = val & 0x01;
+	*VIRM = (val & 0x1c) >> 2;
+
+	return sync;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+
+}
+
+static int freqerr_chk(struct mb86a16_state *state,
+		       int fTP,
+		       int smrt,
+		       int unit)
+{
+	unsigned char CRM, AFCML, AFCMH;
+	unsigned char temp1, temp2, temp3;
+	int crm, afcm, AFCM;
+	int crrerr, afcerr;		/* kHz */
+	int frqerr;			/* MHz */
+	int afcen, afcexen = 0;
+	int R, M, fOSC, fOSC_OFS;
+
+	if (mb86a16_read(state, 0x43, &CRM) != 2)
+		goto err;
+
+	if (CRM > 127)
+		crm = CRM - 256;
+	else
+		crm = CRM;
+
+	crrerr = smrt * crm / 256;
+	if (mb86a16_read(state, 0x49, &temp1) != 2)
+		goto err;
+
+	afcen = (temp1 & 0x04) >> 2;
+	if (afcen == 0) {
+		if (mb86a16_read(state, 0x2a, &temp1) != 2)
+			goto err;
+		afcexen = (temp1 & 0x20) >> 5;
+	}
+
+	if (afcen == 1) {
+		if (mb86a16_read(state, 0x0e, &AFCML) != 2)
+			goto err;
+		if (mb86a16_read(state, 0x0f, &AFCMH) != 2)
+			goto err;
+	} else if (afcexen == 1) {
+		if (mb86a16_read(state, 0x2b, &AFCML) != 2)
+			goto err;
+		if (mb86a16_read(state, 0x2c, &AFCMH) != 2)
+			goto err;
+	}
+	if ((afcen == 1) || (afcexen == 1)) {
+		smrt_info_get(state, smrt);
+		AFCM = ((AFCMH & 0x01) << 8) + AFCML;
+		if (AFCM > 255)
+			afcm = AFCM - 512;
+		else
+			afcm = AFCM;
+
+		afcerr = afcm * state->master_clk / 8192;
+	} else
+		afcerr = 0;
+
+	if (mb86a16_read(state, 0x22, &temp1) != 2)
+		goto err;
+	if (mb86a16_read(state, 0x23, &temp2) != 2)
+		goto err;
+	if (mb86a16_read(state, 0x24, &temp3) != 2)
+		goto err;
+
+	R = (temp1 & 0xe0) >> 5;
+	M = ((temp1 & 0x1f) << 12) + (temp2 << 4) + (temp3 >> 4);
+	if (R == 0)
+		fOSC = 2 * M;
+	else
+		fOSC = M;
+
+	fOSC_OFS = fOSC - fTP;
+
+	if (unit == 0) {	/* MHz */
+		if (crrerr + afcerr + fOSC_OFS * 1000 >= 0)
+			frqerr = (crrerr + afcerr + fOSC_OFS * 1000 + 500) / 1000;
+		else
+			frqerr = (crrerr + afcerr + fOSC_OFS * 1000 - 500) / 1000;
+	} else {	/* kHz */
+		frqerr = crrerr + afcerr + fOSC_OFS * 1000;
+	}
+
+	return frqerr;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static unsigned char vco_dev_get(struct mb86a16_state *state, int smrt)
+{
+	unsigned char R;
+
+	if (smrt > 9375)
+		R = 0;
+	else
+		R = 1;
+
+	return R;
+}
+
+static void swp_info_get(struct mb86a16_state *state,
+			 int fOSC_start,
+			 int smrt,
+			 int v, int R,
+			 int swp_ofs,
+			 int *fOSC,
+			 int *afcex_freq,
+			 unsigned char *AFCEX_L,
+			 unsigned char *AFCEX_H)
+{
+	int AFCEX ;
+	int crnt_swp_freq ;
+
+	crnt_swp_freq = fOSC_start * 1000 + v * swp_ofs;
+
+	if (R == 0)
+		*fOSC = (crnt_swp_freq + 1000) / 2000 * 2;
+	else
+		*fOSC = (crnt_swp_freq + 500) / 1000;
+
+	if (*fOSC >= crnt_swp_freq)
+		*afcex_freq = *fOSC * 1000 - crnt_swp_freq;
+	else
+		*afcex_freq = crnt_swp_freq - *fOSC * 1000;
+
+	AFCEX = *afcex_freq * 8192 / state->master_clk;
+	*AFCEX_L =  AFCEX & 0x00ff;
+	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
+}
+
+
+static int swp_freq_calcuation(struct mb86a16_state *state, int i, int v, int *V,  int vmax, int vmin,
+			       int SIGMIN, int fOSC, int afcex_freq, int swp_ofs, unsigned char *SIG1)
+{
+	int swp_freq ;
+
+	if ((i % 2 == 1) && (v <= vmax)) {
+		/* positive v (case 1) */
+		if ((v - 1 == vmin)				&&
+		    (*(V + 30 + v) >= 0)			&&
+		    (*(V + 30 + v - 1) >= 0)			&&
+		    (*(V + 30 + v - 1) > *(V + 30 + v))		&&
+		    (*(V + 30 + v - 1) > SIGMIN)) {
+
+			swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
+			*SIG1 = *(V + 30 + v - 1);
+		} else if ((v == vmax)				&&
+			   (*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v - 1) >= 0)		&&
+			   (*(V + 30 + v) > *(V + 30 + v - 1))	&&
+			   (*(V + 30 + v) > SIGMIN)) {
+			/* (case 2) */
+			swp_freq = fOSC * 1000 + afcex_freq;
+			*SIG1 = *(V + 30 + v);
+		} else if ((*(V + 30 + v) > 0)			&&
+			   (*(V + 30 + v - 1) > 0)		&&
+			   (*(V + 30 + v - 2) > 0)		&&
+			   (*(V + 30 + v - 3) > 0)		&&
+			   (*(V + 30 + v - 1) > *(V + 30 + v))	&&
+			   (*(V + 30 + v - 2) > *(V + 30 + v - 3)) &&
+			   ((*(V + 30 + v - 1) > SIGMIN)	||
+			   (*(V + 30 + v - 2) > SIGMIN))) {
+			/* (case 3) */
+			if (*(V + 30 + v - 1) >= *(V + 30 + v - 2)) {
+				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
+				*SIG1 = *(V + 30 + v - 1);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs * 2;
+				*SIG1 = *(V + 30 + v - 2);
+			}
+		} else if ((v == vmax)				&&
+			   (*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v - 1) >= 0)		&&
+			   (*(V + 30 + v - 2) >= 0)		&&
+			   (*(V + 30 + v) > *(V + 30 + v - 2))	&&
+			   (*(V + 30 + v - 1) > *(V + 30 + v - 2)) &&
+			   ((*(V + 30 + v) > SIGMIN)		||
+			   (*(V + 30 + v - 1) > SIGMIN))) {
+			/* (case 4) */
+			if (*(V + 30 + v) >= *(V + 30 + v - 1)) {
+				swp_freq = fOSC * 1000 + afcex_freq;
+				*SIG1 = *(V + 30 + v);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq - swp_ofs;
+				*SIG1 = *(V + 30 + v - 1);
+			}
+		} else  {
+			swp_freq = -1 ;
+		}
+	} else if ((i % 2 == 0) && (v >= vmin)) {
+		/* Negative v (case 1) */
+		if ((*(V + 30 + v) > 0)				&&
+		    (*(V + 30 + v + 1) > 0)			&&
+		    (*(V + 30 + v + 2) > 0)			&&
+		    (*(V + 30 + v + 1) > *(V + 30 + v))		&&
+		    (*(V + 30 + v + 1) > *(V + 30 + v + 2))	&&
+		    (*(V + 30 + v + 1) > SIGMIN)) {
+
+			swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+			*SIG1 = *(V + 30 + v + 1);
+		} else if ((v + 1 == vmax)			&&
+			   (*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v + 1) >= 0)		&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
+			   (*(V + 30 + v + 1) > SIGMIN)) {
+			/* (case 2) */
+			swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+			*SIG1 = *(V + 30 + v);
+		} else if ((v == vmin)				&&
+			   (*(V + 30 + v) > 0)			&&
+			   (*(V + 30 + v + 1) > 0)		&&
+			   (*(V + 30 + v + 2) > 0)		&&
+			   (*(V + 30 + v) > *(V + 30 + v + 1))	&&
+			   (*(V + 30 + v) > *(V + 30 + v + 2))	&&
+			   (*(V + 30 + v) > SIGMIN)) {
+			/* (case 3) */
+			swp_freq = fOSC * 1000 + afcex_freq;
+			*SIG1 = *(V + 30 + v);
+		} else if ((*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v + 1) >= 0)		&&
+			   (*(V + 30 + v + 2) >= 0)		&&
+			   (*(V + 30 + v + 3) >= 0)		&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
+			   (*(V + 30 + v + 2) > *(V + 30 + v + 3)) &&
+			   ((*(V + 30 + v + 1) > SIGMIN)	||
+			    (*(V + 30 + v + 2) > SIGMIN))) {
+			/* (case 4) */
+			if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+				*SIG1 = *(V + 30 + v + 1);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2;
+				*SIG1 = *(V + 30 + v + 2);
+			}
+		} else if ((*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v + 1) >= 0)		&&
+			   (*(V + 30 + v + 2) >= 0)		&&
+			   (*(V + 30 + v + 3) >= 0)		&&
+			   (*(V + 30 + v) > *(V + 30 + v + 2))	&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v + 2)) &&
+			   (*(V + 30 + v) > *(V + 30 + v + 3))	&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v + 3)) &&
+			   ((*(V + 30 + v) > SIGMIN)		||
+			    (*(V + 30 + v + 1) > SIGMIN))) {
+			/* (case 5) */
+			if (*(V + 30 + v) >= *(V + 30 + v + 1)) {
+				swp_freq = fOSC * 1000 + afcex_freq;
+				*SIG1 = *(V + 30 + v);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+				*SIG1 = *(V + 30 + v + 1);
+			}
+		} else if ((v + 2 == vmin)			&&
+			   (*(V + 30 + v) >= 0)			&&
+			   (*(V + 30 + v + 1) >= 0)		&&
+			   (*(V + 30 + v + 2) >= 0)		&&
+			   (*(V + 30 + v + 1) > *(V + 30 + v))	&&
+			   (*(V + 30 + v + 2) > *(V + 30 + v))	&&
+			   ((*(V + 30 + v + 1) > SIGMIN)	||
+			    (*(V + 30 + v + 2) > SIGMIN))) {
+			/* (case 6) */
+			if (*(V + 30 + v + 1) >= *(V + 30 + v + 2)) {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs;
+				*SIG1 = *(V + 30 + v + 1);
+			} else {
+				swp_freq = fOSC * 1000 + afcex_freq + swp_ofs * 2;
+				*SIG1 = *(V + 30 + v + 2);
+			}
+		} else if ((vmax == 0) && (vmin == 0) && (*(V + 30 + v) > SIGMIN)) {
+			swp_freq = fOSC * 1000;
+			*SIG1 = *(V + 30 + v);
+		} else
+			swp_freq = -1;
+	} else
+		swp_freq = -1;
+
+	return swp_freq;
+}
+
+static void swp_info_get2(struct mb86a16_state *state,
+			  int smrt,
+			  int R,
+			  int swp_freq,
+			  int *afcex_freq,
+			  int *fOSC,
+			  unsigned char *AFCEX_L,
+			  unsigned char *AFCEX_H)
+{
+	int AFCEX ;
+
+	if (R == 0)
+		*fOSC = (swp_freq + 1000) / 2000 * 2;
+	else
+		*fOSC = (swp_freq + 500) / 1000;
+
+	if (*fOSC >= swp_freq)
+		*afcex_freq = *fOSC * 1000 - swp_freq;
+	else
+		*afcex_freq = swp_freq - *fOSC * 1000;
+
+	AFCEX = *afcex_freq * 8192 / state->master_clk;
+	*AFCEX_L =  AFCEX & 0x00ff;
+	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
+}
+
+static void afcex_info_get(struct mb86a16_state *state,
+			   int afcex_freq,
+			   unsigned char *AFCEX_L,
+			   unsigned char *AFCEX_H)
+{
+	int AFCEX ;
+
+	AFCEX = afcex_freq * 8192 / state->master_clk;
+	*AFCEX_L =  AFCEX & 0x00ff;
+	*AFCEX_H = (AFCEX & 0x0f00) >> 8;
+}
+
+static int SEQ_set(struct mb86a16_state *state, unsigned char loop)
+{
+	/* SLOCK0 = 0 */
+	if (mb86a16_write(state, 0x32, 0x02 | (loop << 2)) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int iq_vt_set(struct mb86a16_state *state, unsigned char IQINV)
+{
+	/* Viterbi Rate, IQ Settings */
+	if (mb86a16_write(state, 0x06, 0xdf | (IQINV << 5)) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int FEC_srst(struct mb86a16_state *state)
+{
+	if (mb86a16_write(state, MB86A16_RESET, 0x02) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int S2T_set(struct mb86a16_state *state, unsigned char S2T)
+{
+	if (mb86a16_write(state, 0x34, 0x70 | S2T) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int S45T_set(struct mb86a16_state *state, unsigned char S4T, unsigned char S5T)
+{
+	if (mb86a16_write(state, 0x35, 0x00 | (S5T << 4) | S4T) < 0) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+
+static int mb86a16_set_fe(struct mb86a16_state *state)
+{
+	u8 agcval, cnmval;
+
+	int i, j;
+	int fOSC = 0;
+	int fOSC_start = 0;
+	int wait_t;
+	int fcp;
+	int swp_ofs;
+	int V[60];
+	u8 SIG1MIN;
+
+	unsigned char CREN, AFCEN, AFCEXEN;
+	unsigned char SIG1;
+	unsigned char TIMINT1, TIMINT2, TIMEXT;
+	unsigned char S0T, S1T;
+	unsigned char S2T;
+/*	unsigned char S2T, S3T; */
+	unsigned char S4T, S5T;
+	unsigned char AFCEX_L, AFCEX_H;
+	unsigned char R;
+	unsigned char VIRM;
+	unsigned char ETH, VIA;
+	unsigned char junk;
+
+	int loop;
+	int ftemp;
+	int v, vmax, vmin;
+	int vmax_his, vmin_his;
+	int swp_freq, prev_swp_freq[20];
+	int prev_freq_num;
+	int signal_dupl;
+	int afcex_freq;
+	int signal;
+	int afcerr;
+	int temp_freq, delta_freq;
+	int dagcm[4];
+	int smrt_d;
+/*	int freq_err; */
+	int n;
+	int ret = -1;
+	int sync;
+
+	dprintk(verbose, MB86A16_INFO, 1, "freq=%d Mhz, symbrt=%d Ksps", state->frequency, state->srate);
+
+	fcp = 3000;
+	swp_ofs = state->srate / 4;
+
+	for (i = 0; i < 60; i++)
+		V[i] = -1;
+
+	for (i = 0; i < 20; i++)
+		prev_swp_freq[i] = 0;
+
+	SIG1MIN = 25;
+
+	for (n = 0; ((n < 3) && (ret == -1)); n++) {
+		SEQ_set(state, 0);
+		iq_vt_set(state, 0);
+
+		CREN = 0;
+		AFCEN = 0;
+		AFCEXEN = 1;
+		TIMINT1 = 0;
+		TIMINT2 = 1;
+		TIMEXT = 2;
+		S1T = 0;
+		S0T = 0;
+
+		if (initial_set(state) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "initial set failed");
+			return -1;
+		}
+		if (DAGC_data_set(state, 3, 2) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
+			return -1;
+		}
+		if (EN_set(state, CREN, AFCEN) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
+			return -1; /* (0, 0) */
+		}
+		if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
+			return -1; /* (1, smrt) = (1, symbolrate) */
+		}
+		if (CNTM_set(state, TIMINT1, TIMINT2, TIMEXT) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "CNTM set error");
+			return -1; /* (0, 1, 2) */
+		}
+		if (S01T_set(state, S1T, S0T) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
+			return -1; /* (0, 0) */
+		}
+		smrt_info_get(state, state->srate);
+		if (smrt_set(state, state->srate) < 0) {
+			dprintk(verbose, MB86A16_ERROR, 1, "smrt info get error");
+			return -1;
+		}
+
+		R = vco_dev_get(state, state->srate);
+		if (R == 1)
+			fOSC_start = state->frequency;
+
+		else if (R == 0) {
+			if (state->frequency % 2 == 0) {
+				fOSC_start = state->frequency;
+			} else {
+				fOSC_start = state->frequency + 1;
+				if (fOSC_start > 2150)
+					fOSC_start = state->frequency - 1;
+			}
+		}
+		loop = 1;
+		ftemp = fOSC_start * 1000;
+		vmax = 0 ;
+		while (loop == 1) {
+			ftemp = ftemp + swp_ofs;
+			vmax++;
+
+			/* Upper bound */
+			if (ftemp > 2150000) {
+				loop = 0;
+				vmax--;
+			} else {
+				if ((ftemp == 2150000) ||
+				    (ftemp - state->frequency * 1000 >= fcp + state->srate / 4))
+					loop = 0;
+			}
+		}
+
+		loop = 1;
+		ftemp = fOSC_start * 1000;
+		vmin = 0 ;
+		while (loop == 1) {
+			ftemp = ftemp - swp_ofs;
+			vmin--;
+
+			/* Lower bound */
+			if (ftemp < 950000) {
+				loop = 0;
+				vmin++;
+			} else {
+				if ((ftemp == 950000) ||
+				    (state->frequency * 1000 - ftemp >= fcp + state->srate / 4))
+					loop = 0;
+			}
+		}
+
+		wait_t = (8000 + state->srate / 2) / state->srate;
+		if (wait_t == 0)
+			wait_t = 1;
+
+		i = 0;
+		j = 0;
+		prev_freq_num = 0;
+		loop = 1;
+		signal = 0;
+		vmax_his = 0;
+		vmin_his = 0;
+		v = 0;
+
+		while (loop == 1) {
+			swp_info_get(state, fOSC_start, state->srate,
+				     v, R, swp_ofs, &fOSC,
+				     &afcex_freq, &AFCEX_L, &AFCEX_H);
+
+			udelay(100);
+			if (rf_val_set(state, fOSC, state->srate, R) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+				return -1;
+			}
+			udelay(100);
+			if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
+				return -1;
+			}
+			if (srst(state) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "srst error");
+				return -1;
+			}
+			msleep_interruptible(wait_t);
+
+			if (mb86a16_read(state, 0x37, &SIG1) != 2) {
+				dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+				return -1;
+			}
+			V[30 + v] = SIG1 ;
+			swp_freq = swp_freq_calcuation(state, i, v, V, vmax, vmin,
+						      SIG1MIN, fOSC, afcex_freq,
+						      swp_ofs, &SIG1);	/* changed */
+
+			signal_dupl = 0;
+			for (j = 0; j < prev_freq_num; j++) {
+				if ((ABS(prev_swp_freq[j] - swp_freq)) < (swp_ofs * 3 / 2)) {
+					signal_dupl = 1;
+					dprintk(verbose, MB86A16_INFO, 1, "Probably Duplicate Signal, j = %d", j);
+				}
+			}
+			if ((signal_dupl == 0) && (swp_freq > 0) && (ABS(swp_freq - state->frequency * 1000) < fcp + state->srate / 6)) {
+				dprintk(verbose, MB86A16_DEBUG, 1, "------ Signal detect ------ [swp_freq=[%07d, srate=%05d]]", swp_freq, state->srate);
+				prev_swp_freq[prev_freq_num] = swp_freq;
+				prev_freq_num++;
+				swp_info_get2(state, state->srate, R, swp_freq,
+					      &afcex_freq, &fOSC,
+					      &AFCEX_L, &AFCEX_H);
+
+				if (rf_val_set(state, fOSC, state->srate, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
+					return -1;
+				}
+				signal = signal_det(state, state->srate, &SIG1);
+				if (signal == 1) {
+					dprintk(verbose, MB86A16_ERROR, 1, "***** Signal Found *****");
+					loop = 0;
+				} else {
+					dprintk(verbose, MB86A16_ERROR, 1, "!!!!! No signal !!!!!, try again...");
+					smrt_info_get(state, state->srate);
+					if (smrt_set(state, state->srate) < 0) {
+						dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
+						return -1;
+					}
+				}
+			}
+			if (v > vmax)
+				vmax_his = 1 ;
+			if (v < vmin)
+				vmin_his = 1 ;
+			i++;
+
+			if ((i % 2 == 1) && (vmax_his == 1))
+				i++;
+			if ((i % 2 == 0) && (vmin_his == 1))
+				i++;
+
+			if (i % 2 == 1)
+				v = (i + 1) / 2;
+			else
+				v = -i / 2;
+
+			if ((vmax_his == 1) && (vmin_his == 1))
+				loop = 0 ;
+		}
+
+		if (signal == 1) {
+			dprintk(verbose, MB86A16_INFO, 1, " Start Freq Error Check");
+			S1T = 7 ;
+			S0T = 1 ;
+			CREN = 0 ;
+			AFCEN = 1 ;
+			AFCEXEN = 0 ;
+
+			if (S01T_set(state, S1T, S0T) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
+				return -1;
+			}
+			smrt_info_get(state, state->srate);
+			if (smrt_set(state, state->srate) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
+				return -1;
+			}
+			if (EN_set(state, CREN, AFCEN) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
+				return -1;
+			}
+			if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
+				return -1;
+			}
+			afcex_info_get(state, afcex_freq, &AFCEX_L, &AFCEX_H);
+			if (afcofs_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "AFCOFS data set error");
+				return -1;
+			}
+			if (srst(state) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "srst error");
+				return -1;
+			}
+			/* delay 4~200 */
+			wait_t = 200000 / state->master_clk + 200000 / state->srate;
+			msleep(wait_t);
+			afcerr = afcerr_chk(state);
+			if (afcerr == -1)
+				return -1;
+
+			swp_freq = fOSC * 1000 + afcerr ;
+			AFCEXEN = 1 ;
+			if (state->srate >= 1500)
+				smrt_d = state->srate / 3;
+			else
+				smrt_d = state->srate / 2;
+			smrt_info_get(state, smrt_d);
+			if (smrt_set(state, smrt_d) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
+				return -1;
+			}
+			if (AFCEXEN_set(state, AFCEXEN, smrt_d) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
+				return -1;
+			}
+			R = vco_dev_get(state, smrt_d);
+			if (DAGC_data_set(state, 2, 0) < 0) {
+				dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
+				return -1;
+			}
+			for (i = 0; i < 3; i++) {
+				temp_freq = swp_freq + (i - 1) * state->srate / 8;
+				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
+				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
+					return -1;
+				}
+				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
+				msleep(wait_t);
+				dagcm[i] = dagcm_val_get(state);
+			}
+			if ((dagcm[0] > dagcm[1]) &&
+			    (dagcm[0] > dagcm[2]) &&
+			    (dagcm[0] - dagcm[1] > 2 * (dagcm[2] - dagcm[1]))) {
+
+				temp_freq = swp_freq - 2 * state->srate / 8;
+				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
+				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set");
+					return -1;
+				}
+				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
+				msleep(wait_t);
+				dagcm[3] = dagcm_val_get(state);
+				if (dagcm[3] > dagcm[1])
+					delta_freq = (dagcm[2] - dagcm[0] + dagcm[1] - dagcm[3]) * state->srate / 300;
+				else
+					delta_freq = 0;
+			} else if ((dagcm[2] > dagcm[1]) &&
+				   (dagcm[2] > dagcm[0]) &&
+				   (dagcm[2] - dagcm[1] > 2 * (dagcm[0] - dagcm[1]))) {
+
+				temp_freq = swp_freq + 2 * state->srate / 8;
+				swp_info_get2(state, smrt_d, R, temp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
+				if (rf_val_set(state, fOSC, smrt_d, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set");
+					return -1;
+				}
+				wait_t = 200000 / state->master_clk + 40000 / smrt_d;
+				msleep(wait_t);
+				dagcm[3] = dagcm_val_get(state);
+				if (dagcm[3] > dagcm[1])
+					delta_freq = (dagcm[2] - dagcm[0] + dagcm[3] - dagcm[1]) * state->srate / 300;
+				else
+					delta_freq = 0 ;
+
+			} else {
+				delta_freq = 0 ;
+			}
+			dprintk(verbose, MB86A16_INFO, 1, "SWEEP Frequency = %d", swp_freq);
+			swp_freq += delta_freq;
+			dprintk(verbose, MB86A16_INFO, 1, "Adjusting .., DELTA Freq = %d, SWEEP Freq=%d", delta_freq, swp_freq);
+			if (ABS(state->frequency * 1000 - swp_freq) > 3800) {
+				dprintk(verbose, MB86A16_INFO, 1, "NO  --  SIGNAL !");
+			} else {
+
+				S1T = 0;
+				S0T = 3;
+				CREN = 1;
+				AFCEN = 0;
+				AFCEXEN = 1;
+
+				if (S01T_set(state, S1T, S0T) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "S01T set error");
+					return -1;
+				}
+				if (DAGC_data_set(state, 0, 0) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "DAGC data set error");
+					return -1;
+				}
+				R = vco_dev_get(state, state->srate);
+				smrt_info_get(state, state->srate);
+				if (smrt_set(state, state->srate) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "smrt set error");
+					return -1;
+				}
+				if (EN_set(state, CREN, AFCEN) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "EN set error");
+					return -1;
+				}
+				if (AFCEXEN_set(state, AFCEXEN, state->srate) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "AFCEXEN set error");
+					return -1;
+				}
+				swp_info_get2(state, state->srate, R, swp_freq, &afcex_freq, &fOSC, &AFCEX_L, &AFCEX_H);
+				if (rf_val_set(state, fOSC, state->srate, R) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "rf val set error");
+					return -1;
+				}
+				if (afcex_data_set(state, AFCEX_L, AFCEX_H) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "afcex data set error");
+					return -1;
+				}
+				if (srst(state) < 0) {
+					dprintk(verbose, MB86A16_ERROR, 1, "srst error");
+					return -1;
+				}
+				wait_t = 7 + (10000 + state->srate / 2) / state->srate;
+				if (wait_t == 0)
+					wait_t = 1;
+				msleep_interruptible(wait_t);
+				if (mb86a16_read(state, 0x37, &SIG1) != 2) {
+					dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+					return -EREMOTEIO;
+				}
+
+				if (SIG1 > 110) {
+					S2T = 4; S4T = 1; S5T = 6; ETH = 4; VIA = 6;
+					wait_t = 7 + (917504 + state->srate / 2) / state->srate;
+				} else if (SIG1 > 105) {
+					S2T = 4; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
+					wait_t = 7 + (1048576 + state->srate / 2) / state->srate;
+				} else if (SIG1 > 85) {
+					S2T = 5; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
+					wait_t = 7 + (1310720 + state->srate / 2) / state->srate;
+				} else if (SIG1 > 65) {
+					S2T = 6; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
+					wait_t = 7 + (1572864 + state->srate / 2) / state->srate;
+				} else {
+					S2T = 7; S4T = 2; S5T = 8; ETH = 7; VIA = 2;
+					wait_t = 7 + (2097152 + state->srate / 2) / state->srate;
+				}
+				wait_t *= 2; /* FOS */
+				S2T_set(state, S2T);
+				S45T_set(state, S4T, S5T);
+				Vi_set(state, ETH, VIA);
+				srst(state);
+				msleep_interruptible(wait_t);
+				sync = sync_chk(state, &VIRM);
+				dprintk(verbose, MB86A16_INFO, 1, "-------- Viterbi=[%d] SYNC=[%d] ---------", VIRM, sync);
+				if (VIRM) {
+					if (VIRM == 4) {
+						/* 5/6 */
+						if (SIG1 > 110)
+							wait_t = (786432 + state->srate / 2) / state->srate;
+						else
+							wait_t = (1572864 + state->srate / 2) / state->srate;
+						if (state->srate < 5000)
+							/* FIXME ! , should be a long wait ! */
+							msleep_interruptible(wait_t);
+						else
+							msleep_interruptible(wait_t);
+
+						if (sync_chk(state, &junk) == 0) {
+							iq_vt_set(state, 1);
+							FEC_srst(state);
+						}
+					}
+					/* 1/2, 2/3, 3/4, 7/8 */
+					if (SIG1 > 110)
+						wait_t = (786432 + state->srate / 2) / state->srate;
+					else
+						wait_t = (1572864 + state->srate / 2) / state->srate;
+					msleep_interruptible(wait_t);
+					SEQ_set(state, 1);
+				} else {
+					dprintk(verbose, MB86A16_INFO, 1, "NO  -- SYNC");
+					SEQ_set(state, 1);
+					ret = -1;
+				}
+			}
+		} else {
+			dprintk(verbose, MB86A16_INFO, 1, "NO  -- SIGNAL");
+			ret = -1;
+		}
+
+		sync = sync_chk(state, &junk);
+		if (sync) {
+			dprintk(verbose, MB86A16_INFO, 1, "******* SYNC *******");
+			freqerr_chk(state, state->frequency, state->srate, 1);
+			ret = 0;
+			break;
+		}
+	}
+
+	mb86a16_read(state, 0x15, &agcval);
+	mb86a16_read(state, 0x26, &cnmval);
+	dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval);
+
+	return ret;
+}
+
+static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe,
+				   struct dvb_diseqc_master_cmd *cmd)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+	int i;
+	u8 regs;
+
+	if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0)
+		goto err;
+
+	regs = 0x18;
+
+	if (cmd->msg_len > 5 || cmd->msg_len < 4)
+		return -EINVAL;
+
+	for (i = 0; i < cmd->msg_len; i++) {
+		if (mb86a16_write(state, regs, cmd->msg[i]) < 0)
+			goto err;
+
+		regs++;
+	}
+	i += 0x90;
+
+	msleep_interruptible(10);
+
+	if (mb86a16_write(state, MB86A16_DCC1, i) < 0)
+		goto err;
+	if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
+		goto err;
+
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	switch (burst) {
+	case SEC_MINI_A:
+		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
+						       MB86A16_DCC1_TBEN  |
+						       MB86A16_DCC1_TBO) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
+			goto err;
+		break;
+	case SEC_MINI_B:
+		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
+						       MB86A16_DCC1_TBEN) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
+			goto err;
+		break;
+	}
+
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int mb86a16_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		if (mb86a16_write(state, MB86A16_TONEOUT2, 0x00) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA |
+						       MB86A16_DCC1_CTOE) < 0)
+
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCCOUT, MB86A16_DCCOUT_DISEN) < 0)
+			goto err;
+		break;
+	case SEC_TONE_OFF:
+		if (mb86a16_write(state, MB86A16_TONEOUT2, 0x04) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCC1, MB86A16_DCC1_DISTA) < 0)
+			goto err;
+		if (mb86a16_write(state, MB86A16_DCCOUT, 0x00) < 0)
+			goto err;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static enum dvbfe_search mb86a16_search(struct dvb_frontend *fe,
+					struct dvb_frontend_parameters *p)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	state->frequency = p->frequency / 1000;
+	state->srate = p->u.qpsk.symbol_rate / 1000;
+
+	if (!mb86a16_set_fe(state)) {
+		dprintk(verbose, MB86A16_ERROR, 1, "Succesfully acquired LOCK");
+		return DVBFE_ALGO_SEARCH_SUCCESS;
+	}
+
+	dprintk(verbose, MB86A16_ERROR, 1, "Lock acquisition failed!");
+	return DVBFE_ALGO_SEARCH_FAILED;
+}
+
+static void mb86a16_release(struct dvb_frontend *fe)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static int mb86a16_init(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int mb86a16_sleep(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int mb86a16_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	u8 ber_mon, ber_tab, ber_lsb, ber_mid, ber_msb, ber_tim, ber_rst;
+	u32 timer;
+
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	*ber = 0;
+	if (mb86a16_read(state, MB86A16_BERMON, &ber_mon) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_BERTAB, &ber_tab) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_BERLSB, &ber_lsb) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_BERMID, &ber_mid) != 2)
+		goto err;
+	if (mb86a16_read(state, MB86A16_BERMSB, &ber_msb) != 2)
+		goto err;
+	/* BER monitor invalid when BER_EN = 0	*/
+	if (ber_mon & 0x04) {
+		/* coarse, fast calculation	*/
+		*ber = ber_tab & 0x1f;
+		dprintk(verbose, MB86A16_DEBUG, 1, "BER coarse=[0x%02x]", *ber);
+		if (ber_mon & 0x01) {
+			/*
+			 * BER_SEL = 1, The monitored BER is the estimated
+			 * value with a Reed-Solomon decoder error amount at
+			 * the deinterleaver output.
+			 * monitored BER is expressed as a 20 bit output in total
+			 */
+			ber_rst = ber_mon >> 3;
+			*ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
+			if (ber_rst == 0)
+				timer =  12500000;
+			if (ber_rst == 1)
+				timer =  25000000;
+			if (ber_rst == 2)
+				timer =  50000000;
+			if (ber_rst == 3)
+				timer = 100000000;
+
+			*ber /= timer;
+			dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
+		} else {
+			/*
+			 * BER_SEL = 0, The monitored BER is the estimated
+			 * value with a Viterbi decoder error amount at the
+			 * QPSK demodulator output.
+			 * monitored BER is expressed as a 24 bit output in total
+			 */
+			ber_tim = ber_mon >> 1;
+			*ber = (((ber_msb << 8) | ber_mid) << 8) | ber_lsb;
+			if (ber_tim == 0)
+				timer = 16;
+			if (ber_tim == 1)
+				timer = 24;
+
+			*ber /= 2 ^ timer;
+			dprintk(verbose, MB86A16_DEBUG, 1, "BER fine=[0x%02x]", *ber);
+		}
+	}
+	return 0;
+err:
+	dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+	return -EREMOTEIO;
+}
+
+static int mb86a16_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	u8 agcm = 0;
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	*strength = 0;
+	if (mb86a16_read(state, MB86A16_AGCM, &agcm) != 2) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	*strength = ((0xff - agcm) * 100) / 256;
+	dprintk(verbose, MB86A16_DEBUG, 1, "Signal strength=[%d %%]", (u8) *strength);
+	*strength = (0xffff - 0xff) + agcm;
+
+	return 0;
+}
+
+struct cnr {
+	u8 cn_reg;
+	u8 cn_val;
+};
+
+static const struct cnr cnr_tab[] = {
+	{  35,  2 },
+	{  40,  3 },
+	{  50,  4 },
+	{  60,  5 },
+	{  70,  6 },
+	{  80,  7 },
+	{  92,  8 },
+	{ 103,  9 },
+	{ 115, 10 },
+	{ 138, 12 },
+	{ 162, 15 },
+	{ 180, 18 },
+	{ 185, 19 },
+	{ 189, 20 },
+	{ 195, 22 },
+	{ 199, 24 },
+	{ 201, 25 },
+	{ 202, 26 },
+	{ 203, 27 },
+	{ 205, 28 },
+	{ 208, 30 }
+};
+
+static int mb86a16_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct mb86a16_state *state = fe->demodulator_priv;
+	int i = 0;
+	int low_tide = 2, high_tide = 30, q_level;
+	u8  cn;
+
+	*snr = 0;
+	if (mb86a16_read(state, 0x26, &cn) != 2) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(cnr_tab); i++) {
+		if (cn < cnr_tab[i].cn_reg) {
+			*snr = cnr_tab[i].cn_val;
+			break;
+		}
+	}
+	q_level = (*snr * 100) / (high_tide - low_tide);
+	dprintk(verbose, MB86A16_ERROR, 1, "SNR (Quality) = [%d dB], Level=%d %%", *snr, q_level);
+	*snr = (0xffff - 0xff) + *snr;
+
+	return 0;
+}
+
+static int mb86a16_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	u8 dist;
+	struct mb86a16_state *state = fe->demodulator_priv;
+
+	if (mb86a16_read(state, MB86A16_DISTMON, &dist) != 2) {
+		dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
+		return -EREMOTEIO;
+	}
+	*ucblocks = dist;
+
+	return 0;
+}
+
+static enum dvbfe_algo mb86a16_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static struct dvb_frontend_ops mb86a16_ops = {
+	.info = {
+		.name			= "Fujitsu MB86A16 DVB-S",
+		.type			= FE_QPSK,
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 3000,
+		.frequency_tolerance	= 0,
+		.symbol_rate_min	= 1000000,
+		.symbol_rate_max	= 45000000,
+		.symbol_rate_tolerance	= 500,
+		.caps			= FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+					  FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
+					  FE_CAN_FEC_7_8 | FE_CAN_QPSK    |
+					  FE_CAN_FEC_AUTO
+	},
+	.release			= mb86a16_release,
+
+	.get_frontend_algo		= mb86a16_frontend_algo,
+	.search				= mb86a16_search,
+	.read_status			= mb86a16_read_status,
+	.init				= mb86a16_init,
+	.sleep				= mb86a16_sleep,
+	.read_status			= mb86a16_read_status,
+
+	.read_ber			= mb86a16_read_ber,
+	.read_signal_strength		= mb86a16_read_signal_strength,
+	.read_snr			= mb86a16_read_snr,
+	.read_ucblocks			= mb86a16_read_ucblocks,
+
+	.diseqc_send_master_cmd		= mb86a16_send_diseqc_msg,
+	.diseqc_send_burst		= mb86a16_send_diseqc_burst,
+	.set_tone			= mb86a16_set_tone,
+};
+
+struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
+				    struct i2c_adapter *i2c_adap)
+{
+	u8 dev_id = 0;
+	struct mb86a16_state *state = NULL;
+
+	state = kmalloc(sizeof(struct mb86a16_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->config = config;
+	state->i2c_adap = i2c_adap;
+
+	mb86a16_read(state, 0x7f, &dev_id);
+	if (dev_id != 0xfe)
+		goto error;
+
+	memcpy(&state->frontend.ops, &mb86a16_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+	state->frontend.ops.set_voltage = state->config->set_voltage;
+
+	return &state->frontend;
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(mb86a16_attach);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Manu Abraham");
diff --git a/drivers/media/dvb/frontends/mb86a16.h b/drivers/media/dvb/frontends/mb86a16.h
new file mode 100644
index 0000000..6ea8c37
--- /dev/null
+++ b/drivers/media/dvb/frontends/mb86a16.h
@@ -0,0 +1,52 @@
+/*
+	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MB86A16_H
+#define __MB86A16_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+
+struct mb86a16_config {
+	u8 demod_address;
+
+	int (*set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+};
+
+
+
+#if defined(CONFIG_DVB_MB86A16) || (defined(CONFIG_DVB_MB86A16_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
+					   struct i2c_adapter *i2c_adap);
+
+#else
+
+static inline struct dvb_frontend *mb86a16_attach(const struct mb86a16_config *config,
+					   struct i2c_adapter *i2c_adap)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif /* CONFIG_DVB_MB86A16 */
+
+#endif /* __MB86A16_H */
diff --git a/drivers/media/dvb/frontends/mb86a16_priv.h b/drivers/media/dvb/frontends/mb86a16_priv.h
new file mode 100644
index 0000000..360a35a
--- /dev/null
+++ b/drivers/media/dvb/frontends/mb86a16_priv.h
@@ -0,0 +1,151 @@
+/*
+	Fujitsu MB86A16 DVB-S/DSS DC Receiver driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MB86A16_PRIV_H
+#define __MB86A16_PRIV_H
+
+#define MB86A16_TSOUT		0x00
+#define MB86A16_TSOUT_HIZSEL	(0x01 << 5)
+#define MB86A16_TSOUT_HIZCNTI	(0x01 << 4)
+#define MB86A16_TSOUT_MODE	(0x01 << 3)
+#define MB86A16_TSOUT_ORDER	(0x01 << 2)
+#define MB86A16_TSOUT_ERROR	(0x01 << 1)
+#define Mb86A16_TSOUT_EDGE	(0x01 << 0)
+
+#define MB86A16_FEC		0x01
+#define MB86A16_FEC_FSYNC	(0x01 << 5)
+#define MB86A16_FEC_PCKB8	(0x01 << 4)
+#define MB86A16_FEC_DVDS	(0x01 << 3)
+#define MB86A16_FEC_EREN	(0x01 << 2)
+#define Mb86A16_FEC_RSEN	(0x01 << 1)
+#define MB86A16_FEC_DIEN	(0x01 << 0)
+
+#define MB86A16_AGC		0x02
+#define MB86A16_AGC_AGMD	(0x01 << 6)
+#define MB86A16_AGC_AGCW	(0x0f << 2)
+#define MB86A16_AGC_AGCP	(0x01 << 1)
+#define MB86A16_AGC_AGCR	(0x01 << 0)
+
+#define MB86A16_SRATE1		0x03
+#define MB86A16_SRATE1_DECI	(0x07 << 2)
+#define MB86A16_SRATE1_CSEL	(0x01 << 1)
+#define MB86A16_SRATE1_RSEL	(0x01 << 0)
+
+#define MB86A16_SRATE2		0x04
+#define MB86A16_SRATE2_STOFSL	(0xff << 0)
+
+#define MB86A16_SRATE3		0x05
+#define MB86A16_SRATE2_STOFSH	(0xff << 0)
+
+#define MB86A16_VITERBI		0x06
+#define MB86A16_FRAMESYNC	0x07
+#define MB86A16_CRLFILTCOEF1	0x08
+#define MB86A16_CRLFILTCOEF2	0x09
+#define MB86A16_STRFILTCOEF1	0x0a
+#define MB86A16_STRFILTCOEF2	0x0b
+#define MB86A16_RESET		0x0c
+#define MB86A16_STATUS		0x0d
+#define MB86A16_AFCML		0x0e
+#define MB86A16_AFCMH		0x0f
+#define MB86A16_BERMON		0x10
+#define MB86A16_BERTAB		0x11
+#define MB86A16_BERLSB		0x12
+#define MB86A16_BERMID		0x13
+#define MB86A16_BERMSB		0x14
+#define MB86A16_AGCM		0x15
+
+#define MB86A16_DCC1		0x16
+#define MB86A16_DCC1_DISTA	(0x01 << 7)
+#define MB86A16_DCC1_PRTY	(0x01 << 6)
+#define MB86A16_DCC1_CTOE	(0x01 << 5)
+#define MB86A16_DCC1_TBEN	(0x01 << 4)
+#define MB86A16_DCC1_TBO	(0x01 << 3)
+#define MB86A16_DCC1_NUM	(0x07 << 0)
+
+#define MB86A16_DCC2		0x17
+#define MB86A16_DCC2_DCBST	(0x01 << 0)
+
+#define MB86A16_DCC3		0x18
+#define MB86A16_DCC3_CODE0	(0xff << 0)
+
+#define MB86A16_DCC4		0x19
+#define MB86A16_DCC4_CODE1	(0xff << 0)
+
+#define MB86A16_DCC5		0x1a
+#define MB86A16_DCC5_CODE2	(0xff << 0)
+
+#define MB86A16_DCC6		0x1b
+#define MB86A16_DCC6_CODE3	(0xff << 0)
+
+#define MB86A16_DCC7		0x1c
+#define MB86A16_DCC7_CODE4	(0xff << 0)
+
+#define MB86A16_DCC8		0x1d
+#define MB86A16_DCC8_CODE5	(0xff << 0)
+
+#define MB86A16_DCCOUT		0x1e
+#define MB86A16_DCCOUT_DISEN	(0x01 << 0)
+
+#define MB86A16_TONEOUT1	0x1f
+#define MB86A16_TONE_TDIVL	(0xff << 0)
+
+#define MB86A16_TONEOUT2	0x20
+#define MB86A16_TONE_TMD	(0x03 << 2)
+#define MB86A16_TONE_TDIVH	(0x03 << 0)
+
+#define MB86A16_FREQ1		0x21
+#define MB86A16_FREQ2		0x22
+#define MB86A16_FREQ3		0x23
+#define MB86A16_FREQ4		0x24
+#define MB86A16_FREQSET		0x25
+#define MB86A16_CNM		0x26
+#define MB86A16_PORT0		0x27
+#define MB86A16_PORT1		0x28
+#define MB86A16_DRCFILT		0x29
+#define MB86A16_AFC		0x2a
+#define MB86A16_AFCEXL		0x2b
+#define MB86A16_AFCEXH		0x2c
+#define MB86A16_DAGC		0x2d
+#define MB86A16_SEQMODE		0x32
+#define MB86A16_S0S1T		0x33
+#define MB86A16_S2S3T		0x34
+#define MB86A16_S4S5T		0x35
+#define MB86A16_CNTMR		0x36
+#define MB86A16_SIG1		0x37
+#define MB86A16_SIG2		0x38
+#define MB86A16_VIMAG		0x39
+#define MB86A16_VISET1		0x3a
+#define MB86A16_VISET2		0x3b
+#define MB86A16_VISET3		0x3c
+#define MB86A16_FAGCS1		0x3d
+#define MB86A16_FAGCS2		0x3e
+#define MB86A16_FAGCS3		0x3f
+#define MB86A16_FAGCS4		0x40
+#define MB86A16_FAGCS5		0x41
+#define MB86A16_FAGCS6		0x42
+#define MB86A16_CRM		0x43
+#define MB86A16_STRM		0x44
+#define MB86A16_DAGCML		0x45
+#define MB86A16_DAGCMH		0x46
+#define MB86A16_QPSKTST		0x49
+#define MB86A16_DISTMON		0x52
+#define MB86A16_VERSION		0x7f
+
+#endif /* __MB86A16_PRIV_H */
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 6c1dbf9..6ca533e 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -426,6 +426,10 @@
 	id = tda10021_readreg(state, 0x1a);
 	if ((id & 0xf0) != 0x70) goto error;
 
+	/* Don't claim TDA10023 */
+	if (id == 0x7d)
+		goto error;
+
 	printk("TDA10021: i2c-addr = 0x%02x, id = 0x%02x\n",
 	       state->config->demod_address, id);
 
diff --git a/drivers/media/dvb/frontends/tda665x.c b/drivers/media/dvb/frontends/tda665x.c
new file mode 100644
index 0000000..87d5273
--- /dev/null
+++ b/drivers/media/dvb/frontends/tda665x.c
@@ -0,0 +1,257 @@
+/*
+	TDA665x tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+#include "tda665x.h"
+
+struct tda665x_state {
+	struct dvb_frontend		*fe;
+	struct i2c_adapter		*i2c;
+	const struct tda665x_config	*config;
+
+	u32 frequency;
+	u32 bandwidth;
+};
+
+static int tda665x_read(struct tda665x_state *state, u8 *buf)
+{
+	const struct tda665x_config *config = state->config;
+	int err = 0;
+	struct i2c_msg msg = { .addr = config->addr, .flags = I2C_M_RD, .buf = buf, .len = 2 };
+
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1)
+		goto exit;
+
+	return err;
+exit:
+	printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
+	return err;
+}
+
+static int tda665x_write(struct tda665x_state *state, u8 *buf, u8 length)
+{
+	const struct tda665x_config *config = state->config;
+	int err = 0;
+	struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = length };
+
+	err = i2c_transfer(state->i2c, &msg, 1);
+	if (err != 1)
+		goto exit;
+
+	return err;
+exit:
+	printk(KERN_ERR "%s: I/O Error err=<%d>\n", __func__, err);
+	return err;
+}
+
+static int tda665x_get_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *tstate)
+{
+	struct tda665x_state *state = fe->tuner_priv;
+	int err = 0;
+
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		tstate->frequency = state->frequency;
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		break;
+	default:
+		printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+static int tda665x_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	struct tda665x_state *state = fe->tuner_priv;
+	u8 result = 0;
+	int err = 0;
+
+	*status = 0;
+
+	err = tda665x_read(state, &result);
+	if (err < 0)
+		goto exit;
+
+	if ((result >> 6) & 0x01) {
+		printk(KERN_DEBUG "%s: Tuner Phase Locked\n", __func__);
+		*status = 1;
+	}
+
+	return err;
+exit:
+	printk(KERN_ERR "%s: I/O Error\n", __func__);
+	return err;
+}
+
+static int tda665x_set_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *tstate)
+{
+	struct tda665x_state *state = fe->tuner_priv;
+	const struct tda665x_config *config = state->config;
+	u32 frequency, status = 0;
+	u8 buf[4];
+	int err = 0;
+
+	if (param & DVBFE_TUNER_FREQUENCY) {
+
+		frequency = tstate->frequency;
+		if ((frequency < config->frequency_max) || (frequency > config->frequency_min)) {
+			printk(KERN_ERR "%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
+			return -EINVAL;
+		}
+
+		frequency += config->frequency_offst;
+		frequency *= config->ref_multiplier;
+		frequency += config->ref_divider >> 1;
+		frequency /= config->ref_divider;
+
+		buf[0] = (u8) (frequency & 0x7f00) >> 8;
+		buf[1] = (u8) (frequency & 0x00ff) >> 0;
+		buf[2] = 0x80 | 0x40 | 0x02;
+		buf[3] = 0x00;
+
+		/* restore frequency */
+		frequency = tstate->frequency;
+
+		if (frequency < 153000000) {
+			/* VHF-L */
+			buf[3] |= 0x01; /* fc, Low Band, 47 - 153 MHz */
+			if (frequency < 68000000)
+				buf[3] |= 0x40; /* 83uA */
+			if (frequency < 1040000000)
+				buf[3] |= 0x60; /* 122uA */
+			if (frequency < 1250000000)
+				buf[3] |= 0x80; /* 163uA */
+			else
+				buf[3] |= 0xa0; /* 254uA */
+		} else if (frequency < 438000000) {
+			/* VHF-H */
+			buf[3] |= 0x02; /* fc, Mid Band, 153 - 438 MHz */
+			if (frequency < 230000000)
+				buf[3] |= 0x40;
+			if (frequency < 300000000)
+				buf[3] |= 0x60;
+			else
+				buf[3] |= 0x80;
+		} else {
+			/* UHF */
+			buf[3] |= 0x04; /* fc, High Band, 438 - 862 MHz */
+			if (frequency < 470000000)
+				buf[3] |= 0x60;
+			if (frequency < 526000000)
+				buf[3] |= 0x80;
+			else
+				buf[3] |= 0xa0;
+		}
+
+		/* Set params */
+		err = tda665x_write(state, buf, 5);
+		if (err < 0)
+			goto exit;
+
+		/* sleep for some time */
+		printk(KERN_DEBUG "%s: Waiting to Phase LOCK\n", __func__);
+		msleep(20);
+		/* check status */
+		err = tda665x_get_status(fe, &status);
+		if (err < 0)
+			goto exit;
+
+		if (status == 1) {
+			printk(KERN_DEBUG "%s: Tuner Phase locked: status=%d\n", __func__, status);
+			state->frequency = frequency; /* cache successful state */
+		} else {
+			printk(KERN_ERR "%s: No Phase lock: status=%d\n", __func__, status);
+		}
+	} else {
+		printk(KERN_ERR "%s: Unknown parameter (param=%d)\n", __func__, param);
+		return -EINVAL;
+	}
+
+	return 0;
+exit:
+	printk(KERN_ERR "%s: I/O Error\n", __func__);
+	return err;
+}
+
+static int tda665x_release(struct dvb_frontend *fe)
+{
+	struct tda665x_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	kfree(state);
+	return 0;
+}
+
+static struct dvb_tuner_ops tda665x_ops = {
+
+	.set_state	= tda665x_set_state,
+	.get_state	= tda665x_get_state,
+	.get_status	= tda665x_get_status,
+	.release	= tda665x_release
+};
+
+struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+				    const struct tda665x_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct tda665x_state *state = NULL;
+	struct dvb_tuner_info *info;
+
+	state = kzalloc(sizeof(struct tda665x_state), GFP_KERNEL);
+	if (state == NULL)
+		goto exit;
+
+	state->config		= config;
+	state->i2c		= i2c;
+	state->fe		= fe;
+	fe->tuner_priv		= state;
+	fe->ops.tuner_ops	= tda665x_ops;
+	info			 = &fe->ops.tuner_ops.info;
+
+	memcpy(info->name, config->name, sizeof(config->name));
+	info->frequency_min	= config->frequency_min;
+	info->frequency_max	= config->frequency_max;
+	info->frequency_step	= config->frequency_offst;
+
+	printk(KERN_DEBUG "%s: Attaching TDA665x (%s) tuner\n", __func__, info->name);
+
+	return fe;
+
+exit:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(tda665x_attach);
+
+MODULE_DESCRIPTION("TDA665x driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/tda665x.h b/drivers/media/dvb/frontends/tda665x.h
new file mode 100644
index 0000000..ec7927a
--- /dev/null
+++ b/drivers/media/dvb/frontends/tda665x.h
@@ -0,0 +1,52 @@
+/*
+	TDA665x tuner driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __TDA665x_H
+#define __TDA665x_H
+
+struct tda665x_config {
+	char name[128];
+
+	u8	addr;
+	u32	frequency_min;
+	u32	frequency_max;
+	u32	frequency_offst;
+	u32	ref_multiplier;
+	u32	ref_divider;
+};
+
+#if defined(CONFIG_DVB_TDA665x) || (defined(CONFIG_DVB_TDA665x_MODULE) && defined(MODULE))
+
+extern struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+					   const struct tda665x_config *config,
+					   struct i2c_adapter *i2c);
+
+#else
+
+static inline struct dvb_frontend *tda665x_attach(struct dvb_frontend *fe,
+						  const struct tda665x_config *config,
+						  struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: Driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+#endif /* CONFIG_DVB_TDA665x */
+
+#endif /* __TDA665x_H */
diff --git a/drivers/media/dvb/mantis/Kconfig b/drivers/media/dvb/mantis/Kconfig
new file mode 100644
index 0000000..f7b72a3
--- /dev/null
+++ b/drivers/media/dvb/mantis/Kconfig
@@ -0,0 +1,32 @@
+config MANTIS_CORE
+	tristate "Mantis/Hopper PCI bridge based devices"
+	depends on PCI && I2C && INPUT
+
+	help
+	  Support for PCI cards based on the Mantis and Hopper PCi bridge.
+
+	  Say Y if you own such a device and want to use it.
+
+config DVB_MANTIS
+	tristate "MANTIS based cards"
+	depends on MANTIS_CORE && DVB_CORE && PCI && I2C
+	select DVB_MB86A16
+	select DVB_ZL10353
+	select DVB_STV0299
+	select DVB_PLL
+	help
+	  Support for PCI cards based on the Mantis PCI bridge.
+	  Say Y when you have a Mantis based DVB card and want to use it.
+
+	  If unsure say N.
+
+config DVB_HOPPER
+	tristate "HOPPER based cards"
+	depends on MANTIS_CORE && DVB_CORE && PCI && I2C
+	select DVB_ZL10353
+	select DVB_PLL
+	help
+	  Support for PCI cards based on the Hopper  PCI bridge.
+	  Say Y when you have a Hopper based DVB card and want to use it.
+
+	  If unsure say N
diff --git a/drivers/media/dvb/mantis/Makefile b/drivers/media/dvb/mantis/Makefile
new file mode 100644
index 0000000..98dc5cd
--- /dev/null
+++ b/drivers/media/dvb/mantis/Makefile
@@ -0,0 +1,28 @@
+mantis_core-objs :=	mantis_ioc.o	\
+			mantis_uart.o	\
+			mantis_dma.o	\
+			mantis_pci.o	\
+			mantis_i2c.o	\
+			mantis_dvb.o	\
+			mantis_evm.o	\
+			mantis_hif.o	\
+			mantis_ca.o	\
+			mantis_pcmcia.o	\
+			mantis_input.o
+
+mantis-objs	:=	mantis_cards.o	\
+			mantis_vp1033.o	\
+			mantis_vp1034.o	\
+			mantis_vp1041.o	\
+			mantis_vp2033.o	\
+			mantis_vp2040.o	\
+			mantis_vp3030.o
+
+hopper-objs	:=	hopper_cards.o	\
+			hopper_vp3028.o
+
+obj-$(CONFIG_MANTIS_CORE)	+= mantis_core.o
+obj-$(CONFIG_DVB_MANTIS)	+= mantis.o
+obj-$(CONFIG_DVB_HOPPER)	+= hopper.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/mantis/hopper_cards.c b/drivers/media/dvb/mantis/hopper_cards.c
new file mode 100644
index 0000000..d073c61
--- /dev/null
+++ b/drivers/media/dvb/mantis/hopper_cards.c
@@ -0,0 +1,275 @@
+/*
+	Hopper PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/irq.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "hopper_vp3028.h"
+#include "mantis_dma.h"
+#include "mantis_dvb.h"
+#include "mantis_uart.h"
+#include "mantis_ioc.h"
+#include "mantis_pci.h"
+#include "mantis_i2c.h"
+#include "mantis_reg.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+
+#define DRIVER_NAME	"Hopper"
+
+static char *label[10] = {
+	"DMA",
+	"IRQ-0",
+	"IRQ-1",
+	"OCERR",
+	"PABRT",
+	"RIPRR",
+	"PPERR",
+	"FTRGT",
+	"RISCI",
+	"RACK"
+};
+
+static int devs;
+
+static irqreturn_t hopper_irq_handler(int irq, void *dev_id)
+{
+	u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+	u32 rst_stat = 0, rst_mask = 0;
+
+	struct mantis_pci *mantis;
+	struct mantis_ca *ca;
+
+	mantis = (struct mantis_pci *) dev_id;
+	if (unlikely(mantis == NULL)) {
+		dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
+		return IRQ_NONE;
+	}
+	ca = mantis->mantis_ca;
+
+	stat = mmread(MANTIS_INT_STAT);
+	mask = mmread(MANTIS_INT_MASK);
+	mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+	if (!(stat & mask))
+		return IRQ_NONE;
+
+	rst_mask  = MANTIS_GPIF_WRACK  |
+		    MANTIS_GPIF_OTHERR |
+		    MANTIS_SBUF_WSTO   |
+		    MANTIS_GPIF_EXTIRQ;
+
+	rst_stat  = mmread(MANTIS_GPIF_STATUS);
+	rst_stat &= rst_mask;
+	mmwrite(rst_stat, MANTIS_GPIF_STATUS);
+
+	mantis->mantis_int_stat = stat;
+	mantis->mantis_int_mask = mask;
+	dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
+	if (stat & MANTIS_INT_RISCEN) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
+	}
+	if (stat & MANTIS_INT_IRQ0) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
+		mantis->gpif_status = rst_stat;
+		wake_up(&ca->hif_write_wq);
+		schedule_work(&ca->hif_evm_work);
+	}
+	if (stat & MANTIS_INT_IRQ1) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
+		schedule_work(&mantis->uart_work);
+	}
+	if (stat & MANTIS_INT_OCERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
+	}
+	if (stat & MANTIS_INT_PABORT) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
+	}
+	if (stat & MANTIS_INT_RIPERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
+	}
+	if (stat & MANTIS_INT_PPERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
+	}
+	if (stat & MANTIS_INT_FTRGT) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
+	}
+	if (stat & MANTIS_INT_RISCI) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
+		mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+		tasklet_schedule(&mantis->tasklet);
+	}
+	if (stat & MANTIS_INT_I2CDONE) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
+		wake_up(&mantis->i2c_wq);
+	}
+	mmwrite(stat, MANTIS_INT_STAT);
+	stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
+		  MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
+		  MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
+		  MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
+		  MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
+		  MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1	   |
+		  MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
+		  MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
+		  MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
+		  MANTIS_INT_RISCI);
+
+	if (stat)
+		dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
+
+	dprintk(MANTIS_DEBUG, 0, "\n");
+	return IRQ_HANDLED;
+}
+
+static int __devinit hopper_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	struct mantis_pci *mantis;
+	struct mantis_hwconfig *config;
+	int err = 0;
+
+	mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
+	if (mantis == NULL) {
+		printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
+		err = -ENOMEM;
+		goto fail0;
+	}
+
+	mantis->num		= devs;
+	mantis->verbose		= verbose;
+	mantis->pdev		= pdev;
+	config			= (struct mantis_hwconfig *) pci_id->driver_data;
+	config->irq_handler	= &hopper_irq_handler;
+	mantis->hwconfig	= config;
+
+	err = mantis_pci_init(mantis);
+	if (err) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
+		goto fail1;
+	}
+
+	err = mantis_stream_control(mantis, STREAM_TO_HIF);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
+		goto fail1;
+	}
+
+	err = mantis_i2c_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
+		goto fail2;
+	}
+
+	err = mantis_get_mac(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
+		goto fail2;
+	}
+
+	err = mantis_dma_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
+		goto fail3;
+	}
+
+	err = mantis_dvb_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
+		goto fail4;
+	}
+	devs++;
+
+	return err;
+
+fail4:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
+	mantis_dma_exit(mantis);
+
+fail3:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
+	mantis_i2c_exit(mantis);
+
+fail2:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
+	mantis_pci_exit(mantis);
+
+fail1:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
+	kfree(mantis);
+
+fail0:
+	return err;
+}
+
+static void __devexit hopper_pci_remove(struct pci_dev *pdev)
+{
+	struct mantis_pci *mantis = pci_get_drvdata(pdev);
+
+	if (mantis) {
+		mantis_dvb_exit(mantis);
+		mantis_dma_exit(mantis);
+		mantis_i2c_exit(mantis);
+		mantis_pci_exit(mantis);
+		kfree(mantis);
+	}
+	return;
+
+}
+
+static struct pci_device_id hopper_pci_table[] = {
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3028_DVB_T, &vp3028_config),
+	{ }
+};
+
+static struct pci_driver hopper_pci_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= hopper_pci_table,
+	.probe		= hopper_pci_probe,
+	.remove		= hopper_pci_remove,
+};
+
+static int __devinit hopper_init(void)
+{
+	return pci_register_driver(&hopper_pci_driver);
+}
+
+static void __devexit hopper_exit(void)
+{
+	return pci_unregister_driver(&hopper_pci_driver);
+}
+
+module_init(hopper_init);
+module_exit(hopper_exit);
+
+MODULE_DESCRIPTION("HOPPER driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/mantis/hopper_vp3028.c b/drivers/media/dvb/mantis/hopper_vp3028.c
new file mode 100644
index 0000000..96674c7
--- /dev/null
+++ b/drivers/media/dvb/mantis/hopper_vp3028.c
@@ -0,0 +1,88 @@
+/*
+	Hopper VP-3028 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "zl10353.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "hopper_vp3028.h"
+
+struct zl10353_config hopper_vp3028_config = {
+	.demod_address	= 0x0f,
+};
+
+#define MANTIS_MODEL_NAME	"VP-3028"
+#define MANTIS_DEV_TYPE		"DVB-T"
+
+static int vp3028_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+	struct mantis_hwconfig *config	= mantis->hwconfig;
+	int err = 0;
+
+	gpio_set_bits(mantis, config->reset, 0);
+	msleep(100);
+	err = mantis_frontend_power(mantis, POWER_ON);
+	msleep(100);
+	gpio_set_bits(mantis, config->reset, 1);
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		msleep(250);
+		dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
+		fe = zl10353_attach(&hopper_vp3028_config, adapter);
+
+		if (!fe)
+			return -1;
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp3028_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_188,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp3028_frontend_init,
+	.power		= GPIF_A00,
+	.reset		= GPIF_A03,
+};
diff --git a/drivers/media/dvb/mantis/hopper_vp3028.h b/drivers/media/dvb/mantis/hopper_vp3028.h
new file mode 100644
index 0000000..5723949
--- /dev/null
+++ b/drivers/media/dvb/mantis/hopper_vp3028.h
@@ -0,0 +1,30 @@
+/*
+	Hopper VP-3028 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP3028_H
+#define __MANTIS_VP3028_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_3028_DVB_T	0x0028
+
+extern struct mantis_hwconfig vp3028_config;
+
+#endif /* __MANTIS_VP3028_H */
diff --git a/drivers/media/dvb/mantis/mantis_ca.c b/drivers/media/dvb/mantis/mantis_ca.c
new file mode 100644
index 0000000..403ce04
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_ca.c
@@ -0,0 +1,207 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_link.h"
+#include "mantis_hif.h"
+#include "mantis_reg.h"
+
+#include "mantis_ca.h"
+
+static int mantis_ca_read_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Read", slot);
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return mantis_hif_read_mem(ca, addr);
+}
+
+static int mantis_ca_write_attr_mem(struct dvb_ca_en50221 *en50221, int slot, int addr, u8 data)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request Attribute Mem Write", slot);
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return mantis_hif_write_mem(ca, addr, data);
+}
+
+static int mantis_ca_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Read", slot);
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return mantis_hif_read_iom(ca, addr);
+}
+
+static int mantis_ca_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr, u8 data)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Request CAM control Write", slot);
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return mantis_hif_write_iom(ca, addr, data);
+}
+
+static int mantis_ca_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot RESET", slot);
+	udelay(500); /* Wait.. */
+	mmwrite(0xda, MANTIS_PCMCIA_RESET); /* Leading edge assert */
+	udelay(500);
+	mmwrite(0x00, MANTIS_PCMCIA_RESET); /* Trailing edge deassert */
+	msleep(1000);
+	dvb_ca_en50221_camready_irq(&ca->en50221, 0);
+
+	return 0;
+}
+
+static int mantis_ca_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Slot shutdown", slot);
+
+	return 0;
+}
+
+static int mantis_ts_control(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): TS control", slot);
+/*	mantis_set_direction(mantis, 1); */ /* Enable TS through CAM */
+
+	return 0;
+}
+
+static int mantis_slot_status(struct dvb_ca_en50221 *en50221, int slot, int open)
+{
+	struct mantis_ca *ca = en50221->data;
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Slot(%d): Poll Slot status", slot);
+
+	if (ca->slot_state == MODULE_INSERTED) {
+		dprintk(MANTIS_DEBUG, 1, "CA Module present and ready");
+		return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+	} else {
+		dprintk(MANTIS_DEBUG, 1, "CA Module not present or not ready");
+	}
+
+	return 0;
+}
+
+int mantis_ca_init(struct mantis_pci *mantis)
+{
+	struct dvb_adapter *dvb_adapter	= &mantis->dvb_adapter;
+	struct mantis_ca *ca;
+	int ca_flags = 0, result;
+
+	dprintk(MANTIS_DEBUG, 1, "Initializing Mantis CA");
+	ca = kzalloc(sizeof(struct mantis_ca), GFP_KERNEL);
+	if (!ca) {
+		dprintk(MANTIS_ERROR, 1, "Out of memory!, exiting ..");
+		result = -ENOMEM;
+		goto err;
+	}
+
+	ca->ca_priv		= mantis;
+	mantis->mantis_ca	= ca;
+	ca_flags		= DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE;
+	/* register CA interface */
+	ca->en50221.owner		= THIS_MODULE;
+	ca->en50221.read_attribute_mem	= mantis_ca_read_attr_mem;
+	ca->en50221.write_attribute_mem	= mantis_ca_write_attr_mem;
+	ca->en50221.read_cam_control	= mantis_ca_read_cam_ctl;
+	ca->en50221.write_cam_control	= mantis_ca_write_cam_ctl;
+	ca->en50221.slot_reset		= mantis_ca_slot_reset;
+	ca->en50221.slot_shutdown	= mantis_ca_slot_shutdown;
+	ca->en50221.slot_ts_enable	= mantis_ts_control;
+	ca->en50221.poll_slot_status	= mantis_slot_status;
+	ca->en50221.data		= ca;
+
+	mutex_init(&ca->ca_lock);
+
+	init_waitqueue_head(&ca->hif_data_wq);
+	init_waitqueue_head(&ca->hif_opdone_wq);
+	init_waitqueue_head(&ca->hif_write_wq);
+
+	dprintk(MANTIS_ERROR, 1, "Registering EN50221 device");
+	result = dvb_ca_en50221_init(dvb_adapter, &ca->en50221, ca_flags, 1);
+	if (result != 0) {
+		dprintk(MANTIS_ERROR, 1, "EN50221: Initialization failed <%d>", result);
+		goto err;
+	}
+	dprintk(MANTIS_ERROR, 1, "Registered EN50221 device");
+	mantis_evmgr_init(ca);
+	return 0;
+err:
+	kfree(ca);
+	return result;
+}
+EXPORT_SYMBOL_GPL(mantis_ca_init);
+
+void mantis_ca_exit(struct mantis_pci *mantis)
+{
+	struct mantis_ca *ca = mantis->mantis_ca;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis CA exit");
+
+	mantis_evmgr_exit(ca);
+	dprintk(MANTIS_ERROR, 1, "Unregistering EN50221 device");
+	if (ca)
+		dvb_ca_en50221_release(&ca->en50221);
+
+	kfree(ca);
+}
+EXPORT_SYMBOL_GPL(mantis_ca_exit);
diff --git a/drivers/media/dvb/mantis/mantis_ca.h b/drivers/media/dvb/mantis/mantis_ca.h
new file mode 100644
index 0000000..dc63e55
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_ca.h
@@ -0,0 +1,27 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_CA_H
+#define __MANTIS_CA_H
+
+extern int mantis_ca_init(struct mantis_pci *mantis);
+extern void mantis_ca_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_CA_H */
diff --git a/drivers/media/dvb/mantis/mantis_cards.c b/drivers/media/dvb/mantis/mantis_cards.c
new file mode 100644
index 0000000..16f1708
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_cards.c
@@ -0,0 +1,305 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/irq.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+
+#include "mantis_vp1033.h"
+#include "mantis_vp1034.h"
+#include "mantis_vp1041.h"
+#include "mantis_vp2033.h"
+#include "mantis_vp2040.h"
+#include "mantis_vp3030.h"
+
+#include "mantis_dma.h"
+#include "mantis_ca.h"
+#include "mantis_dvb.h"
+#include "mantis_uart.h"
+#include "mantis_ioc.h"
+#include "mantis_pci.h"
+#include "mantis_i2c.h"
+#include "mantis_reg.h"
+
+static unsigned int verbose;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+
+static int devs;
+
+#define DRIVER_NAME	"Mantis"
+
+static char *label[10] = {
+	"DMA",
+	"IRQ-0",
+	"IRQ-1",
+	"OCERR",
+	"PABRT",
+	"RIPRR",
+	"PPERR",
+	"FTRGT",
+	"RISCI",
+	"RACK"
+};
+
+static irqreturn_t mantis_irq_handler(int irq, void *dev_id)
+{
+	u32 stat = 0, mask = 0, lstat = 0, mstat = 0;
+	u32 rst_stat = 0, rst_mask = 0;
+
+	struct mantis_pci *mantis;
+	struct mantis_ca *ca;
+
+	mantis = (struct mantis_pci *) dev_id;
+	if (unlikely(mantis == NULL)) {
+		dprintk(MANTIS_ERROR, 1, "Mantis == NULL");
+		return IRQ_NONE;
+	}
+	ca = mantis->mantis_ca;
+
+	stat = mmread(MANTIS_INT_STAT);
+	mask = mmread(MANTIS_INT_MASK);
+	mstat = lstat = stat & ~MANTIS_INT_RISCSTAT;
+	if (!(stat & mask))
+		return IRQ_NONE;
+
+	rst_mask  = MANTIS_GPIF_WRACK  |
+		    MANTIS_GPIF_OTHERR |
+		    MANTIS_SBUF_WSTO   |
+		    MANTIS_GPIF_EXTIRQ;
+
+	rst_stat  = mmread(MANTIS_GPIF_STATUS);
+	rst_stat &= rst_mask;
+	mmwrite(rst_stat, MANTIS_GPIF_STATUS);
+
+	mantis->mantis_int_stat = stat;
+	mantis->mantis_int_mask = mask;
+	dprintk(MANTIS_DEBUG, 0, "\n-- Stat=<%02x> Mask=<%02x> --", stat, mask);
+	if (stat & MANTIS_INT_RISCEN) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[0]);
+	}
+	if (stat & MANTIS_INT_IRQ0) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[1]);
+		mantis->gpif_status = rst_stat;
+		wake_up(&ca->hif_write_wq);
+		schedule_work(&ca->hif_evm_work);
+	}
+	if (stat & MANTIS_INT_IRQ1) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[2]);
+		schedule_work(&mantis->uart_work);
+	}
+	if (stat & MANTIS_INT_OCERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[3]);
+	}
+	if (stat & MANTIS_INT_PABORT) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[4]);
+	}
+	if (stat & MANTIS_INT_RIPERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[5]);
+	}
+	if (stat & MANTIS_INT_PPERR) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[6]);
+	}
+	if (stat & MANTIS_INT_FTRGT) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[7]);
+	}
+	if (stat & MANTIS_INT_RISCI) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[8]);
+		mantis->finished_block = (stat & MANTIS_INT_RISCSTAT) >> 28;
+		tasklet_schedule(&mantis->tasklet);
+	}
+	if (stat & MANTIS_INT_I2CDONE) {
+		dprintk(MANTIS_DEBUG, 0, "<%s>", label[9]);
+		wake_up(&mantis->i2c_wq);
+	}
+	mmwrite(stat, MANTIS_INT_STAT);
+	stat &= ~(MANTIS_INT_RISCEN   | MANTIS_INT_I2CDONE |
+		  MANTIS_INT_I2CRACK  | MANTIS_INT_PCMCIA7 |
+		  MANTIS_INT_PCMCIA6  | MANTIS_INT_PCMCIA5 |
+		  MANTIS_INT_PCMCIA4  | MANTIS_INT_PCMCIA3 |
+		  MANTIS_INT_PCMCIA2  | MANTIS_INT_PCMCIA1 |
+		  MANTIS_INT_PCMCIA0  | MANTIS_INT_IRQ1	   |
+		  MANTIS_INT_IRQ0     | MANTIS_INT_OCERR   |
+		  MANTIS_INT_PABORT   | MANTIS_INT_RIPERR  |
+		  MANTIS_INT_PPERR    | MANTIS_INT_FTRGT   |
+		  MANTIS_INT_RISCI);
+
+	if (stat)
+		dprintk(MANTIS_DEBUG, 0, "<Unknown> Stat=<%02x> Mask=<%02x>", stat, mask);
+
+	dprintk(MANTIS_DEBUG, 0, "\n");
+	return IRQ_HANDLED;
+}
+
+static int __devinit mantis_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	struct mantis_pci *mantis;
+	struct mantis_hwconfig *config;
+	int err = 0;
+
+	mantis = kzalloc(sizeof(struct mantis_pci), GFP_KERNEL);
+	if (mantis == NULL) {
+		printk(KERN_ERR "%s ERROR: Out of memory\n", __func__);
+		err = -ENOMEM;
+		goto fail0;
+	}
+
+	mantis->num		= devs;
+	mantis->verbose		= verbose;
+	mantis->pdev		= pdev;
+	config			= (struct mantis_hwconfig *) pci_id->driver_data;
+	config->irq_handler	= &mantis_irq_handler;
+	mantis->hwconfig	= config;
+
+	err = mantis_pci_init(mantis);
+	if (err) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI initialization failed <%d>", err);
+		goto fail1;
+	}
+
+	err = mantis_stream_control(mantis, STREAM_TO_HIF);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis stream control failed <%d>", err);
+		goto fail1;
+	}
+
+	err = mantis_i2c_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C initialization failed <%d>", err);
+		goto fail2;
+	}
+
+	err = mantis_get_mac(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis MAC address read failed <%d>", err);
+		goto fail2;
+	}
+
+	err = mantis_dma_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA initialization failed <%d>", err);
+		goto fail3;
+	}
+
+	err = mantis_dvb_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DVB initialization failed <%d>", err);
+		goto fail4;
+	}
+	err = mantis_uart_init(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART initialization failed <%d>", err);
+		goto fail6;
+	}
+
+	devs++;
+
+	return err;
+
+
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis UART exit! <%d>", err);
+	mantis_uart_exit(mantis);
+
+fail6:
+fail4:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis DMA exit! <%d>", err);
+	mantis_dma_exit(mantis);
+
+fail3:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis I2C exit! <%d>", err);
+	mantis_i2c_exit(mantis);
+
+fail2:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis PCI exit! <%d>", err);
+	mantis_pci_exit(mantis);
+
+fail1:
+	dprintk(MANTIS_ERROR, 1, "ERROR: Mantis free! <%d>", err);
+	kfree(mantis);
+
+fail0:
+	return err;
+}
+
+static void __devexit mantis_pci_remove(struct pci_dev *pdev)
+{
+	struct mantis_pci *mantis = pci_get_drvdata(pdev);
+
+	if (mantis) {
+
+		mantis_uart_exit(mantis);
+		mantis_dvb_exit(mantis);
+		mantis_dma_exit(mantis);
+		mantis_i2c_exit(mantis);
+		mantis_pci_exit(mantis);
+		kfree(mantis);
+	}
+	return;
+}
+
+static struct pci_device_id mantis_pci_table[] = {
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1033_DVB_S, &vp1033_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1034_DVB_S, &vp1034_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_1041_DVB_S2, &vp1041_config),
+	MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_10, &vp1041_config),
+	MAKE_ENTRY(TECHNISAT, SKYSTAR_HD2_20, &vp1041_config),
+	MAKE_ENTRY(TERRATEC, CINERGY_S2_PCI_HD, &vp1041_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config),
+	MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config),
+	MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2033_config),
+	MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config),
+	{ }
+};
+
+static struct pci_driver mantis_pci_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= mantis_pci_table,
+	.probe		= mantis_pci_probe,
+	.remove		= mantis_pci_remove,
+};
+
+static int __devinit mantis_init(void)
+{
+	return pci_register_driver(&mantis_pci_driver);
+}
+
+static void __devexit mantis_exit(void)
+{
+	return pci_unregister_driver(&mantis_pci_driver);
+}
+
+module_init(mantis_init);
+module_exit(mantis_exit);
+
+MODULE_DESCRIPTION("MANTIS driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/mantis/mantis_common.h b/drivers/media/dvb/mantis/mantis_common.h
new file mode 100644
index 0000000..d0b645a
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_common.h
@@ -0,0 +1,179 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_COMMON_H
+#define __MANTIS_COMMON_H
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#include "mantis_uart.h"
+
+#include "mantis_link.h"
+
+#define MANTIS_ERROR		0
+#define MANTIS_NOTICE		1
+#define MANTIS_INFO		2
+#define MANTIS_DEBUG		3
+#define MANTIS_TMG		9
+
+#define dprintk(y, z, format, arg...) do {								\
+	if (z) {											\
+		if	((mantis->verbose > MANTIS_ERROR) && (mantis->verbose > y))			\
+			printk(KERN_ERR "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+		else if	((mantis->verbose > MANTIS_NOTICE) && (mantis->verbose > y))			\
+			printk(KERN_NOTICE "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+		else if ((mantis->verbose > MANTIS_INFO) && (mantis->verbose > y))			\
+			printk(KERN_INFO "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+		else if ((mantis->verbose > MANTIS_DEBUG) && (mantis->verbose > y))			\
+			printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+		else if ((mantis->verbose > MANTIS_TMG) && (mantis->verbose > y))			\
+			printk(KERN_DEBUG "%s (%d): " format "\n" , __func__ , mantis->num , ##arg);	\
+	} else {											\
+		if (mantis->verbose > y)								\
+			printk(format , ##arg);								\
+	}												\
+} while(0)
+
+#define mwrite(dat, addr)	writel((dat), addr)
+#define mread(addr)		readl(addr)
+
+#define mmwrite(dat, addr)	mwrite((dat), (mantis->mmio + (addr)))
+#define mmread(addr)		mread(mantis->mmio + (addr))
+
+#define MANTIS_TS_188		0
+#define MANTIS_TS_204		1
+
+#define TWINHAN_TECHNOLOGIES	0x1822
+#define MANTIS			0x4e35
+
+#define TECHNISAT		0x1ae4
+#define TERRATEC		0x153b
+
+#define MAKE_ENTRY(__subven, __subdev, __configptr) {			\
+		.vendor		= TWINHAN_TECHNOLOGIES,			\
+		.device		= MANTIS,				\
+		.subvendor	= (__subven),				\
+		.subdevice	= (__subdev),				\
+		.driver_data	= (unsigned long) (__configptr)		\
+}
+
+enum mantis_i2c_mode {
+	MANTIS_PAGE_MODE = 0,
+	MANTIS_BYTE_MODE,
+};
+
+struct mantis_pci;
+
+struct mantis_hwconfig {
+	char			*model_name;
+	char			*dev_type;
+	u32			ts_size;
+
+	enum mantis_baud	baud_rate;
+	enum mantis_parity	parity;
+	u32			bytes;
+
+	irqreturn_t (*irq_handler)(int irq, void *dev_id);
+	int (*frontend_init)(struct mantis_pci *mantis, struct dvb_frontend *fe);
+
+	u8			power;
+	u8			reset;
+
+	enum mantis_i2c_mode	i2c_mode;
+};
+
+struct mantis_pci {
+	unsigned int		verbose;
+
+	/*	PCI stuff		*/
+	u16			vendor_id;
+	u16			device_id;
+	u16			subsystem_vendor;
+	u16			subsystem_device;
+
+	u8			latency;
+
+	struct pci_dev		*pdev;
+
+	unsigned long		mantis_addr;
+	void __iomem		*mmio;
+
+	u8			irq;
+	u8			revision;
+
+	unsigned int		num;
+
+	/*	RISC Core		*/
+	u32			finished_block;
+	u32			last_block;
+	u32			line_bytes;
+	u32			line_count;
+	u32			risc_pos;
+	u8			*buf_cpu;
+	dma_addr_t		buf_dma;
+	u32			*risc_cpu;
+	dma_addr_t		risc_dma;
+
+	struct tasklet_struct	tasklet;
+
+	struct i2c_adapter	adapter;
+	int			i2c_rc;
+	wait_queue_head_t	i2c_wq;
+	struct mutex		i2c_lock;
+
+	/*	DVB stuff		*/
+	struct dvb_adapter	dvb_adapter;
+	struct dvb_frontend	*fe;
+	struct dvb_demux	demux;
+	struct dmxdev		dmxdev;
+	struct dmx_frontend	fe_hw;
+	struct dmx_frontend	fe_mem;
+	struct dvb_net		dvbnet;
+
+	u8			feeds;
+
+	struct mantis_hwconfig	*hwconfig;
+
+	u32			mantis_int_stat;
+	u32			mantis_int_mask;
+
+	/*	board specific		*/
+	u8			mac_address[8];
+	u32			sub_vendor_id;
+	u32			sub_device_id;
+
+	 /*	A12 A13 A14		*/
+	u32			gpio_status;
+
+	u32			gpif_status;
+
+	struct mantis_ca	*mantis_ca;
+
+	wait_queue_head_t	uart_wq;
+	struct work_struct	uart_work;
+	spinlock_t		uart_lock;
+
+	struct input_dev	*rc;
+};
+
+#define MANTIS_HIF_STATUS	(mantis->gpio_status)
+
+#endif /* __MANTIS_COMMON_H */
diff --git a/drivers/media/dvb/mantis/mantis_core.c b/drivers/media/dvb/mantis/mantis_core.c
new file mode 100644
index 0000000..8113b23
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_core.c
@@ -0,0 +1,238 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "mantis_common.h"
+#include "mantis_core.h"
+#include "mantis_vp1033.h"
+#include "mantis_vp1034.h"
+#include "mantis_vp1041.h"
+#include "mantis_vp2033.h"
+#include "mantis_vp2040.h"
+#include "mantis_vp3030.h"
+
+static int read_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
+{
+	int err;
+	struct i2c_msg msg[] = {
+		{
+			.addr = 0x50,
+			.flags = 0,
+			.buf = data,
+			.len = 1
+		}, {
+			.addr = 0x50,
+			.flags = I2C_M_RD,
+			.buf = data,
+			.len = length
+		},
+	};
+
+	err = i2c_transfer(&mantis->adapter, msg, 2);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1,
+			"ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >",
+			err, data[0], data[1]);
+
+		return err;
+	}
+
+	return 0;
+}
+
+static int write_eeprom_byte(struct mantis_pci *mantis, u8 *data, u8 length)
+{
+	int err;
+
+	struct i2c_msg msg = {
+		.addr = 0x50,
+		.flags = 0,
+		.buf = data,
+		.len = length
+	};
+
+	err = i2c_transfer(&mantis->adapter, &msg, 1);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1,
+			"ERROR: i2c write: < err=%i length=0x%02x d0=0x%02x, d1=0x%02x >",
+			err, length, data[0], data[1]);
+
+		return err;
+	}
+
+	return 0;
+}
+
+static int get_mac_address(struct mantis_pci *mantis)
+{
+	int err;
+
+	mantis->mac_address[0] = 0x08;
+	err = read_eeprom_byte(mantis, &mantis->mac_address[0], 6);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1, "Mantis EEPROM read error");
+
+		return err;
+	}
+	dprintk(verbose, MANTIS_ERROR, 0,
+		"    MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n",
+		mantis->mac_address[0], mantis->mac_address[1],
+		mantis->mac_address[2],	mantis->mac_address[3],
+		mantis->mac_address[4], mantis->mac_address[5]);
+
+	return 0;
+}
+
+#define MANTIS_MODEL_UNKNOWN	"UNKNOWN"
+#define MANTIS_DEV_UNKNOWN	"UNKNOWN"
+
+struct mantis_hwconfig unknown_device = {
+	.model_name	= MANTIS_MODEL_UNKNOWN,
+	.dev_type	= MANTIS_DEV_UNKNOWN,
+};
+
+static void mantis_load_config(struct mantis_pci *mantis)
+{
+	switch (mantis->subsystem_device) {
+	case MANTIS_VP_1033_DVB_S:	/* VP-1033 */
+		mantis->hwconfig = &vp1033_mantis_config;
+		break;
+	case MANTIS_VP_1034_DVB_S:	/* VP-1034 */
+		mantis->hwconfig = &vp1034_mantis_config;
+		break;
+	case MANTIS_VP_1041_DVB_S2:	/* VP-1041 */
+	case TECHNISAT_SKYSTAR_HD2:
+		mantis->hwconfig = &vp1041_mantis_config;
+		break;
+	case MANTIS_VP_2033_DVB_C:	/* VP-2033 */
+		mantis->hwconfig = &vp2033_mantis_config;
+		break;
+	case MANTIS_VP_2040_DVB_C:	/* VP-2040 */
+	case TERRATEC_CINERGY_C_PCI:	/* VP-2040 clone */
+	case TECHNISAT_CABLESTAR_HD2:
+		mantis->hwconfig = &vp2040_mantis_config;
+		break;
+	case MANTIS_VP_3030_DVB_T:	/* VP-3030 */
+		mantis->hwconfig = &vp3030_mantis_config;
+		break;
+	default:
+		mantis->hwconfig = &unknown_device;
+		break;
+	}
+}
+
+int mantis_core_init(struct mantis_pci *mantis)
+{
+	int err = 0;
+
+	mantis_load_config(mantis);
+	dprintk(verbose, MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n",
+		mantis->hwconfig->model_name, mantis->hwconfig->dev_type,
+		mantis->pdev->bus->number, PCI_SLOT(mantis->pdev->devfn), PCI_FUNC(mantis->pdev->devfn));
+	dprintk(verbose, MANTIS_ERROR, 0, "    Mantis Rev %d [%04x:%04x], ",
+		mantis->revision,
+		mantis->subsystem_vendor, mantis->subsystem_device);
+	dprintk(verbose, MANTIS_ERROR, 0,
+		"irq: %d, latency: %d\n    memory: 0x%lx, mmio: 0x%p\n",
+		mantis->pdev->irq, mantis->latency,
+		mantis->mantis_addr, mantis->mantis_mmio);
+
+	err = mantis_i2c_init(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1, "Mantis I2C init failed");
+		return err;
+	}
+	err = get_mac_address(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1, "get MAC address failed");
+		return err;
+	}
+	err = mantis_dma_init(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_ERROR, 1, "Mantis DMA init failed");
+		return err;
+	}
+	err = mantis_dvb_init(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_DEBUG, 1, "Mantis DVB init failed");
+		return err;
+	}
+	err = mantis_uart_init(mantis);
+	if (err < 0) {
+		dprintk(verbose, MANTIS_DEBUG, 1, "Mantis UART init failed");
+		return err;
+	}
+
+	return 0;
+}
+
+int mantis_core_exit(struct mantis_pci *mantis)
+{
+	mantis_dma_stop(mantis);
+	dprintk(verbose, MANTIS_ERROR, 1, "DMA engine stopping");
+
+	mantis_uart_exit(mantis);
+	dprintk(verbose, MANTIS_ERROR, 1, "UART exit failed");
+
+	if (mantis_dma_exit(mantis) < 0)
+		dprintk(verbose, MANTIS_ERROR, 1, "DMA exit failed");
+	if (mantis_dvb_exit(mantis) < 0)
+		dprintk(verbose, MANTIS_ERROR, 1, "DVB exit failed");
+	if (mantis_i2c_exit(mantis) < 0)
+		dprintk(verbose, MANTIS_ERROR, 1, "I2C adapter delete.. failed");
+
+	return 0;
+}
+
+/* Turn the given bit on or off. */
+void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
+{
+	u32 cur;
+
+	cur = mmread(MANTIS_GPIF_ADDR);
+	if (value)
+		mantis->gpio_status = cur | (1 << bitpos);
+	else
+		mantis->gpio_status = cur & (~(1 << bitpos));
+
+	mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
+	mmwrite(0x00, MANTIS_GPIF_DOUT);
+	udelay(100);
+}
+
+/* direction = 0 , no CI passthrough ; 1 , CI passthrough */
+void mantis_set_direction(struct mantis_pci *mantis, int direction)
+{
+	u32 reg;
+
+	reg = mmread(0x28);
+	dprintk(verbose, MANTIS_DEBUG, 1, "TS direction setup");
+	if (direction == 0x01) {
+		/* to CI */
+		reg |= 0x04;
+		mmwrite(reg, 0x28);
+		reg &= 0xff - 0x04;
+		mmwrite(reg, 0x28);
+	} else {
+		reg &= 0xff - 0x04;
+		mmwrite(reg, 0x28);
+		reg |= 0x04;
+		mmwrite(reg, 0x28);
+	}
+}
diff --git a/drivers/media/dvb/mantis/mantis_core.h b/drivers/media/dvb/mantis/mantis_core.h
new file mode 100644
index 0000000..833ee42
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_core.h
@@ -0,0 +1,57 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_CORE_H
+#define __MANTIS_CORE_H
+
+#include "mantis_common.h"
+
+
+#define FE_TYPE_SAT	0
+#define FE_TYPE_CAB	1
+#define FE_TYPE_TER	2
+
+#define FE_TYPE_TS204	0
+#define FE_TYPE_TS188	1
+
+
+struct vendorname {
+	u8  *sub_vendor_name;
+	u32 sub_vendor_id;
+};
+
+struct devicetype {
+	u8  *sub_device_name;
+	u32 sub_device_id;
+	u8  device_type;
+	u32 type_flags;
+};
+
+
+extern int mantis_dma_init(struct mantis_pci *mantis);
+extern int mantis_dma_exit(struct mantis_pci *mantis);
+extern void mantis_dma_start(struct mantis_pci *mantis);
+extern void mantis_dma_stop(struct mantis_pci *mantis);
+extern int mantis_i2c_init(struct mantis_pci *mantis);
+extern int mantis_i2c_exit(struct mantis_pci *mantis);
+extern int mantis_core_init(struct mantis_pci *mantis);
+extern int mantis_core_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_CORE_H */
diff --git a/drivers/media/dvb/mantis/mantis_dma.c b/drivers/media/dvb/mantis/mantis_dma.c
new file mode 100644
index 0000000..46202a4
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_dma.c
@@ -0,0 +1,256 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <asm/page.h>
+#include <linux/vmalloc.h>
+#include <linux/pci.h>
+
+#include <asm/irq.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_dma.h"
+
+#define RISC_WRITE		(0x01 << 28)
+#define RISC_JUMP		(0x07 << 28)
+#define RISC_IRQ		(0x01 << 24)
+
+#define RISC_STATUS(status)	((((~status) & 0x0f) << 20) | ((status & 0x0f) << 16))
+#define RISC_FLUSH()		(mantis->risc_pos = 0)
+#define RISC_INSTR(opcode)	(mantis->risc_cpu[mantis->risc_pos++] = cpu_to_le32(opcode))
+
+#define MANTIS_BUF_SIZE		(64 * 1024)
+#define MANTIS_BLOCK_BYTES	(MANTIS_BUF_SIZE >> 4)
+#define MANTIS_BLOCK_COUNT	(1 << 4)
+#define MANTIS_RISC_SIZE	PAGE_SIZE
+
+int mantis_dma_exit(struct mantis_pci *mantis)
+{
+	if (mantis->buf_cpu) {
+		dprintk(MANTIS_ERROR, 1,
+			"DMA=0x%lx cpu=0x%p size=%d",
+			(unsigned long) mantis->buf_dma,
+			 mantis->buf_cpu,
+			 MANTIS_BUF_SIZE);
+
+		pci_free_consistent(mantis->pdev, MANTIS_BUF_SIZE,
+				    mantis->buf_cpu, mantis->buf_dma);
+
+		mantis->buf_cpu = NULL;
+	}
+	if (mantis->risc_cpu) {
+		dprintk(MANTIS_ERROR, 1,
+			"RISC=0x%lx cpu=0x%p size=%lx",
+			(unsigned long) mantis->risc_dma,
+			mantis->risc_cpu,
+			MANTIS_RISC_SIZE);
+
+		pci_free_consistent(mantis->pdev, MANTIS_RISC_SIZE,
+				    mantis->risc_cpu, mantis->risc_dma);
+
+		mantis->risc_cpu = NULL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_dma_exit);
+
+static inline int mantis_alloc_buffers(struct mantis_pci *mantis)
+{
+	if (!mantis->buf_cpu) {
+		mantis->buf_cpu = pci_alloc_consistent(mantis->pdev,
+						       MANTIS_BUF_SIZE,
+						       &mantis->buf_dma);
+		if (!mantis->buf_cpu) {
+			dprintk(MANTIS_ERROR, 1,
+				"DMA buffer allocation failed");
+
+			goto err;
+		}
+		dprintk(MANTIS_ERROR, 1,
+			"DMA=0x%lx cpu=0x%p size=%d",
+			(unsigned long) mantis->buf_dma,
+			mantis->buf_cpu, MANTIS_BUF_SIZE);
+	}
+	if (!mantis->risc_cpu) {
+		mantis->risc_cpu = pci_alloc_consistent(mantis->pdev,
+							MANTIS_RISC_SIZE,
+							&mantis->risc_dma);
+
+		if (!mantis->risc_cpu) {
+			dprintk(MANTIS_ERROR, 1,
+				"RISC program allocation failed");
+
+			mantis_dma_exit(mantis);
+
+			goto err;
+		}
+		dprintk(MANTIS_ERROR, 1,
+			"RISC=0x%lx cpu=0x%p size=%lx",
+			(unsigned long) mantis->risc_dma,
+			mantis->risc_cpu, MANTIS_RISC_SIZE);
+	}
+
+	return 0;
+err:
+	dprintk(MANTIS_ERROR, 1, "Out of memory (?) .....");
+	return -ENOMEM;
+}
+
+static inline int mantis_calc_lines(struct mantis_pci *mantis)
+{
+	mantis->line_bytes = MANTIS_BLOCK_BYTES;
+	mantis->line_count = MANTIS_BLOCK_COUNT;
+
+	while (mantis->line_bytes > 4095) {
+		mantis->line_bytes >>= 1;
+		mantis->line_count <<= 1;
+	}
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis RISC block bytes=[%d], line bytes=[%d], line count=[%d]",
+		MANTIS_BLOCK_BYTES, mantis->line_bytes, mantis->line_count);
+
+	if (mantis->line_count > 255) {
+		dprintk(MANTIS_ERROR, 1, "Buffer size error");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int mantis_dma_init(struct mantis_pci *mantis)
+{
+	int err = 0;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");
+	if (mantis_alloc_buffers(mantis) < 0) {
+		dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
+
+		/* Stop RISC Engine */
+		mmwrite(0, MANTIS_DMA_CTL);
+
+		goto err;
+	}
+	err = mantis_calc_lines(mantis);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "Mantis calc lines failed");
+
+		goto err;
+	}
+
+	return 0;
+err:
+	return err;
+}
+EXPORT_SYMBOL_GPL(mantis_dma_init);
+
+static inline void mantis_risc_program(struct mantis_pci *mantis)
+{
+	u32 buf_pos = 0;
+	u32 line;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis create RISC program");
+	RISC_FLUSH();
+
+	dprintk(MANTIS_DEBUG, 1, "risc len lines %u, bytes per line %u",
+		mantis->line_count, mantis->line_bytes);
+
+	for (line = 0; line < mantis->line_count; line++) {
+		dprintk(MANTIS_DEBUG, 1, "RISC PROG line=[%d]", line);
+		if (!(buf_pos % MANTIS_BLOCK_BYTES)) {
+			RISC_INSTR(RISC_WRITE	|
+				   RISC_IRQ	|
+				   RISC_STATUS(((buf_pos / MANTIS_BLOCK_BYTES) +
+				   (MANTIS_BLOCK_COUNT - 1)) %
+				    MANTIS_BLOCK_COUNT) |
+				    mantis->line_bytes);
+		} else {
+			RISC_INSTR(RISC_WRITE	| mantis->line_bytes);
+		}
+		RISC_INSTR(mantis->buf_dma + buf_pos);
+		buf_pos += mantis->line_bytes;
+	}
+	RISC_INSTR(RISC_JUMP);
+	RISC_INSTR(mantis->risc_dma);
+}
+
+void mantis_dma_start(struct mantis_pci *mantis)
+{
+	dprintk(MANTIS_DEBUG, 1, "Mantis Start DMA engine");
+
+	mantis_risc_program(mantis);
+	mmwrite(mantis->risc_dma, MANTIS_RISC_START);
+	mmwrite(mmread(MANTIS_GPIF_ADDR) | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
+
+	mmwrite(0, MANTIS_DMA_CTL);
+	mantis->last_block = mantis->finished_block = 0;
+
+	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_RISCI, MANTIS_INT_MASK);
+
+	mmwrite(MANTIS_FIFO_EN | MANTIS_DCAP_EN
+			       | MANTIS_RISC_EN, MANTIS_DMA_CTL);
+
+}
+
+void mantis_dma_stop(struct mantis_pci *mantis)
+{
+	u32 stat = 0, mask = 0;
+
+	stat = mmread(MANTIS_INT_STAT);
+	mask = mmread(MANTIS_INT_MASK);
+	dprintk(MANTIS_DEBUG, 1, "Mantis Stop DMA engine");
+
+	mmwrite((mmread(MANTIS_GPIF_ADDR) & (~(MANTIS_GPIF_HIFRDWRN))), MANTIS_GPIF_ADDR);
+
+	mmwrite((mmread(MANTIS_DMA_CTL) & ~(MANTIS_FIFO_EN |
+					    MANTIS_DCAP_EN |
+					    MANTIS_RISC_EN)), MANTIS_DMA_CTL);
+
+	mmwrite(mmread(MANTIS_INT_STAT), MANTIS_INT_STAT);
+
+	mmwrite(mmread(MANTIS_INT_MASK) & ~(MANTIS_INT_RISCI |
+					    MANTIS_INT_RISCEN), MANTIS_INT_MASK);
+}
+
+
+void mantis_dma_xfer(unsigned long data)
+{
+	struct mantis_pci *mantis = (struct mantis_pci *) data;
+	struct mantis_hwconfig *config = mantis->hwconfig;
+
+	while (mantis->last_block != mantis->finished_block) {
+		dprintk(MANTIS_DEBUG, 1, "last block=[%d] finished block=[%d]",
+			mantis->last_block, mantis->finished_block);
+
+		(config->ts_size ? dvb_dmx_swfilter_204 : dvb_dmx_swfilter)
+		(&mantis->demux, &mantis->buf_cpu[mantis->last_block * MANTIS_BLOCK_BYTES], MANTIS_BLOCK_BYTES);
+		mantis->last_block = (mantis->last_block + 1) % MANTIS_BLOCK_COUNT;
+	}
+}
diff --git a/drivers/media/dvb/mantis/mantis_dma.h b/drivers/media/dvb/mantis/mantis_dma.h
new file mode 100644
index 0000000..6be00fa
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_dma.h
@@ -0,0 +1,30 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_DMA_H
+#define __MANTIS_DMA_H
+
+extern int mantis_dma_init(struct mantis_pci *mantis);
+extern int mantis_dma_exit(struct mantis_pci *mantis);
+extern void mantis_dma_start(struct mantis_pci *mantis);
+extern void mantis_dma_stop(struct mantis_pci *mantis);
+extern void mantis_dma_xfer(unsigned long data);
+
+#endif /* __MANTIS_DMA_H */
diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c
new file mode 100644
index 0000000..99d82ee
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_dvb.c
@@ -0,0 +1,296 @@
+/*
+	Mantis PCI bridge driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_dma.h"
+#include "mantis_ca.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+
+	switch (power) {
+	case POWER_ON:
+		dprintk(MANTIS_DEBUG, 1, "Power ON");
+		gpio_set_bits(mantis, config->power, POWER_ON);
+		msleep(100);
+		gpio_set_bits(mantis, config->power, POWER_ON);
+		msleep(100);
+		break;
+
+	case POWER_OFF:
+		dprintk(MANTIS_DEBUG, 1, "Power OFF");
+		gpio_set_bits(mantis, config->power, POWER_OFF);
+		msleep(100);
+		break;
+
+	default:
+		dprintk(MANTIS_DEBUG, 1, "Unknown state <%02x>", power);
+		return -1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_frontend_power);
+
+void mantis_frontend_soft_reset(struct mantis_pci *mantis)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+
+	dprintk(MANTIS_DEBUG, 1, "Frontend RESET");
+	gpio_set_bits(mantis, config->reset, 0);
+	msleep(100);
+	gpio_set_bits(mantis, config->reset, 0);
+	msleep(100);
+	gpio_set_bits(mantis, config->reset, 1);
+	msleep(100);
+	gpio_set_bits(mantis, config->reset, 1);
+	msleep(100);
+
+	return;
+}
+EXPORT_SYMBOL_GPL(mantis_frontend_soft_reset);
+
+static int mantis_frontend_shutdown(struct mantis_pci *mantis)
+{
+	int err;
+
+	mantis_frontend_soft_reset(mantis);
+	err = mantis_frontend_power(mantis, POWER_OFF);
+	if (err != 0) {
+		dprintk(MANTIS_ERROR, 1, "Frontend POWER OFF failed! <%d>", err);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int mantis_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct mantis_pci *mantis = dvbdmx->priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Start feed");
+	if (!dvbdmx->dmx.frontend) {
+		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
+		return -EINVAL;
+	}
+
+	mantis->feeds++;
+	dprintk(MANTIS_DEBUG, 1, "mantis start feed, feeds=%d",	mantis->feeds);
+
+	if (mantis->feeds == 1)	 {
+		dprintk(MANTIS_DEBUG, 1, "mantis start feed & dma");
+		mantis_dma_start(mantis);
+	}
+
+	return mantis->feeds;
+}
+
+static int mantis_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct mantis_pci *mantis = dvbdmx->priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis DVB Stop feed");
+	if (!dvbdmx->dmx.frontend) {
+		dprintk(MANTIS_DEBUG, 1, "no frontend ?");
+		return -EINVAL;
+	}
+
+	mantis->feeds--;
+	if (mantis->feeds == 0) {
+		dprintk(MANTIS_DEBUG, 1, "mantis stop feed and dma");
+		mantis_dma_stop(mantis);
+	}
+
+	return 0;
+}
+
+int __devinit mantis_dvb_init(struct mantis_pci *mantis)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+	int result = -1;
+
+	dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");
+
+	result = dvb_register_adapter(&mantis->dvb_adapter,
+				      "Mantis DVB adapter",
+				      THIS_MODULE,
+				      &mantis->pdev->dev,
+				      adapter_nr);
+
+	if (result < 0) {
+
+		dprintk(MANTIS_ERROR, 1, "Error registering adapter");
+		return -ENODEV;
+	}
+
+	mantis->dvb_adapter.priv	= mantis;
+	mantis->demux.dmx.capabilities	= DMX_TS_FILTERING	|
+					 DMX_SECTION_FILTERING	|
+					 DMX_MEMORY_BASED_FILTERING;
+
+	mantis->demux.priv		= mantis;
+	mantis->demux.filternum		= 256;
+	mantis->demux.feednum		= 256;
+	mantis->demux.start_feed	= mantis_dvb_start_feed;
+	mantis->demux.stop_feed		= mantis_dvb_stop_feed;
+	mantis->demux.write_to_decoder	= NULL;
+
+	dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
+	result = dvb_dmx_init(&mantis->demux);
+	if (result < 0) {
+		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
+
+		goto err0;
+	}
+
+	mantis->dmxdev.filternum	= 256;
+	mantis->dmxdev.demux		= &mantis->demux.dmx;
+	mantis->dmxdev.capabilities	= 0;
+	dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");
+
+	result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
+	if (result < 0) {
+
+		dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
+		goto err1;
+	}
+
+	mantis->fe_hw.source		= DMX_FRONTEND_0;
+	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+	if (result < 0) {
+
+		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
+		goto err2;
+	}
+
+	mantis->fe_mem.source		= DMX_MEMORY_FE;
+	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
+	if (result < 0) {
+		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
+		goto err3;
+	}
+
+	result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+	if (result < 0) {
+		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
+		goto err4;
+	}
+
+	dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
+	tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
+	if (mantis->hwconfig) {
+		result = config->frontend_init(mantis, mantis->fe);
+		if (result < 0) {
+			dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
+			goto err5;
+		} else {
+			if (mantis->fe == NULL) {
+				dprintk(MANTIS_ERROR, 1, "FE <NULL>");
+				goto err5;
+			}
+
+			if (dvb_register_frontend(&mantis->dvb_adapter, mantis->fe)) {
+				dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");
+
+				if (mantis->fe->ops.release)
+					mantis->fe->ops.release(mantis->fe);
+
+				mantis->fe = NULL;
+				goto err5;
+			}
+		}
+	}
+
+	return 0;
+
+	/* Error conditions ..	*/
+err5:
+	tasklet_kill(&mantis->tasklet);
+	dvb_net_release(&mantis->dvbnet);
+	dvb_unregister_frontend(mantis->fe);
+	dvb_frontend_detach(mantis->fe);
+err4:
+	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
+
+err3:
+	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+
+err2:
+	dvb_dmxdev_release(&mantis->dmxdev);
+
+err1:
+	dvb_dmx_release(&mantis->demux);
+
+err0:
+	dvb_unregister_adapter(&mantis->dvb_adapter);
+
+	return result;
+}
+EXPORT_SYMBOL_GPL(mantis_dvb_init);
+
+int __devexit mantis_dvb_exit(struct mantis_pci *mantis)
+{
+	int err;
+
+	if (mantis->fe) {
+		/* mantis_ca_exit(mantis); */
+		err = mantis_frontend_shutdown(mantis);
+		if (err != 0)
+			dprintk(MANTIS_ERROR, 1, "Frontend exit while POWER ON! <%d>", err);
+		dvb_unregister_frontend(mantis->fe);
+		dvb_frontend_detach(mantis->fe);
+	}
+
+	tasklet_kill(&mantis->tasklet);
+	dvb_net_release(&mantis->dvbnet);
+
+	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
+	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);
+
+	dvb_dmxdev_release(&mantis->dmxdev);
+	dvb_dmx_release(&mantis->demux);
+
+	dprintk(MANTIS_DEBUG, 1, "dvb_unregister_adapter");
+	dvb_unregister_adapter(&mantis->dvb_adapter);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_dvb_exit);
diff --git a/drivers/media/dvb/mantis/mantis_dvb.h b/drivers/media/dvb/mantis/mantis_dvb.h
new file mode 100644
index 0000000..464199d
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_dvb.h
@@ -0,0 +1,35 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_DVB_H
+#define __MANTIS_DVB_H
+
+enum mantis_power {
+	POWER_OFF	= 0,
+	POWER_ON	= 1
+};
+
+extern int mantis_frontend_power(struct mantis_pci *mantis, enum mantis_power power);
+extern void mantis_frontend_soft_reset(struct mantis_pci *mantis);
+
+extern int mantis_dvb_init(struct mantis_pci *mantis);
+extern int mantis_dvb_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_DVB_H */
diff --git a/drivers/media/dvb/mantis/mantis_evm.c b/drivers/media/dvb/mantis/mantis_evm.c
new file mode 100644
index 0000000..a7b369a
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_evm.c
@@ -0,0 +1,117 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_link.h"
+#include "mantis_hif.h"
+#include "mantis_reg.h"
+
+static void mantis_hifevm_work(struct work_struct *work)
+{
+	struct mantis_ca *ca = container_of(work, struct mantis_ca, hif_evm_work);
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	u32 gpif_stat, gpif_mask;
+
+	gpif_stat = mmread(MANTIS_GPIF_STATUS);
+	gpif_mask = mmread(MANTIS_GPIF_IRQCFG);
+
+	if (gpif_stat & MANTIS_GPIF_DETSTAT) {
+		if (gpif_stat & MANTIS_CARD_PLUGIN) {
+			dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Plugin", mantis->num);
+			mmwrite(0xdada0000, MANTIS_CARD_RESET);
+			mantis_event_cam_plugin(ca);
+			dvb_ca_en50221_camchange_irq(&ca->en50221,
+						     0,
+						     DVB_CA_EN50221_CAMCHANGE_INSERTED);
+		}
+	} else {
+		if (gpif_stat & MANTIS_CARD_PLUGOUT) {
+			dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): CAM Unplug", mantis->num);
+			mmwrite(0xdada0000, MANTIS_CARD_RESET);
+			mantis_event_cam_unplug(ca);
+			dvb_ca_en50221_camchange_irq(&ca->en50221,
+						     0,
+						     DVB_CA_EN50221_CAMCHANGE_REMOVED);
+		}
+	}
+
+	if (mantis->gpif_status & MANTIS_GPIF_EXTIRQ)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Ext IRQ", mantis->num);
+
+	if (mantis->gpif_status & MANTIS_SBUF_WSTO)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Timeout", mantis->num);
+
+	if (mantis->gpif_status & MANTIS_GPIF_OTHERR)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Alignment Error", mantis->num);
+
+	if (gpif_stat & MANTIS_SBUF_OVFLW)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Overflow", mantis->num);
+
+	if (gpif_stat & MANTIS_GPIF_BRRDY)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Read Ready", mantis->num);
+
+	if (gpif_stat & MANTIS_GPIF_INTSTAT)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): GPIF IRQ", mantis->num);
+
+	if (gpif_stat & MANTIS_SBUF_EMPTY)
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer Empty", mantis->num);
+
+	if (gpif_stat & MANTIS_SBUF_OPDONE) {
+		dprintk(MANTIS_DEBUG, 1, "Event Mgr: Adapter(%d) Slot(0): Smart Buffer operation complete", mantis->num);
+		ca->sbuf_status = MANTIS_SBUF_DATA_AVAIL;
+		ca->hif_event = MANTIS_SBUF_OPDONE;
+		wake_up(&ca->hif_opdone_wq);
+	}
+}
+
+int mantis_evmgr_init(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Initializing Mantis Host I/F Event manager");
+	INIT_WORK(&ca->hif_evm_work, mantis_hifevm_work);
+	mantis_pcmcia_init(ca);
+	schedule_work(&ca->hif_evm_work);
+	mantis_hif_init(ca);
+	return 0;
+}
+
+void mantis_evmgr_exit(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	dprintk(MANTIS_DEBUG, 1, "Mantis Host I/F Event manager exiting");
+	flush_scheduled_work();
+	mantis_hif_exit(ca);
+	mantis_pcmcia_exit(ca);
+}
diff --git a/drivers/media/dvb/mantis/mantis_hif.c b/drivers/media/dvb/mantis/mantis_hif.c
new file mode 100644
index 0000000..7477dac
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_hif.c
@@ -0,0 +1,240 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+
+#include "mantis_hif.h"
+#include "mantis_link.h" /* temporary due to physical layer stuff */
+
+#include "mantis_reg.h"
+
+
+static int mantis_hif_sbuf_opdone_wait(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	int rc = 0;
+
+	if (wait_event_timeout(ca->hif_opdone_wq,
+			       ca->hif_event & MANTIS_SBUF_OPDONE,
+			       msecs_to_jiffies(500)) == -ERESTARTSYS) {
+
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Smart buffer operation timeout !", mantis->num);
+		rc = -EREMOTEIO;
+	}
+	dprintk(MANTIS_DEBUG, 1, "Smart Buffer Operation complete");
+	ca->hif_event &= ~MANTIS_SBUF_OPDONE;
+	return rc;
+}
+
+static int mantis_hif_write_wait(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 opdone = 0, timeout = 0;
+	int rc = 0;
+
+	if (wait_event_timeout(ca->hif_write_wq,
+			       mantis->gpif_status & MANTIS_GPIF_WRACK,
+			       msecs_to_jiffies(500)) == -ERESTARTSYS) {
+
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): Write ACK timed out !", mantis->num);
+		rc = -EREMOTEIO;
+	}
+	dprintk(MANTIS_DEBUG, 1, "Write Acknowledged");
+	mantis->gpif_status &= ~MANTIS_GPIF_WRACK;
+	while (!opdone) {
+		opdone = (mmread(MANTIS_GPIF_STATUS) & MANTIS_SBUF_OPDONE);
+		udelay(500);
+		timeout++;
+		if (timeout > 100) {
+			dprintk(MANTIS_ERROR, 1, "Adater(%d) Slot(0): Write operation timed out!", mantis->num);
+			rc = -ETIMEDOUT;
+			break;
+		}
+	}
+	dprintk(MANTIS_DEBUG, 1, "HIF Write success");
+	return rc;
+}
+
+
+int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 hif_addr = 0, data, count = 4;
+
+	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Read", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
+	hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
+	hif_addr |=  MANTIS_HIF_STATUS;
+	hif_addr |=  addr;
+
+	mmwrite(hif_addr, MANTIS_GPIF_BRADDR);
+	mmwrite(count, MANTIS_GPIF_BRBYTES);
+	udelay(20);
+	mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
+
+	if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): GPIF Smart Buffer operation failed", mantis->num);
+		mutex_unlock(&ca->ca_lock);
+		return -EREMOTEIO;
+	}
+	data = mmread(MANTIS_GPIF_DIN);
+	mutex_unlock(&ca->ca_lock);
+	dprintk(MANTIS_DEBUG, 1, "Mem Read: 0x%02x", data);
+	return (data >> 24) & 0xff;
+}
+
+int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data)
+{
+	struct mantis_slot *slot = ca->slot;
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 hif_addr = 0;
+
+	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF Mem Write", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
+	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
+	hif_addr &= ~MANTIS_GPIF_PCMCIAIOM;
+	hif_addr |=  MANTIS_HIF_STATUS;
+	hif_addr |=  addr;
+
+	mmwrite(slot->slave_cfg, MANTIS_GPIF_CFGSLA); /* Slot0 alone for now */
+	mmwrite(hif_addr, MANTIS_GPIF_ADDR);
+	mmwrite(data, MANTIS_GPIF_DOUT);
+
+	if (mantis_hif_write_wait(ca) != 0) {
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
+		mutex_unlock(&ca->ca_lock);
+		return -EREMOTEIO;
+	}
+	dprintk(MANTIS_DEBUG, 1, "Mem Write: (0x%02x to 0x%02x)", data, addr);
+	mutex_unlock(&ca->ca_lock);
+
+	return 0;
+}
+
+int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 data, hif_addr = 0;
+
+	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Read", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
+	hif_addr |=  MANTIS_GPIF_PCMCIAIOM;
+	hif_addr |=  MANTIS_HIF_STATUS;
+	hif_addr |=  addr;
+
+	mmwrite(hif_addr, MANTIS_GPIF_BRADDR);
+	mmwrite(1, MANTIS_GPIF_BRBYTES);
+	udelay(20);
+	mmwrite(hif_addr | MANTIS_GPIF_HIFRDWRN, MANTIS_GPIF_ADDR);
+
+	if (mantis_hif_sbuf_opdone_wait(ca) != 0) {
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
+		mutex_unlock(&ca->ca_lock);
+		return -EREMOTEIO;
+	}
+	data = mmread(MANTIS_GPIF_DIN);
+	dprintk(MANTIS_DEBUG, 1, "I/O Read: 0x%02x", data);
+	udelay(50);
+	mutex_unlock(&ca->ca_lock);
+
+	return (u8) data;
+}
+
+int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 hif_addr = 0;
+
+	dprintk(MANTIS_DEBUG, 1, "Adapter(%d) Slot(0): Request HIF I/O Write", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	hif_addr &= ~MANTIS_GPIF_PCMCIAREG;
+	hif_addr &= ~MANTIS_GPIF_HIFRDWRN;
+	hif_addr |=  MANTIS_GPIF_PCMCIAIOM;
+	hif_addr |=  MANTIS_HIF_STATUS;
+	hif_addr |=  addr;
+
+	mmwrite(hif_addr, MANTIS_GPIF_ADDR);
+	mmwrite(data, MANTIS_GPIF_DOUT);
+
+	if (mantis_hif_write_wait(ca) != 0) {
+		dprintk(MANTIS_ERROR, 1, "Adapter(%d) Slot(0): HIF Smart Buffer operation failed", mantis->num);
+		mutex_unlock(&ca->ca_lock);
+		return -EREMOTEIO;
+	}
+	dprintk(MANTIS_DEBUG, 1, "I/O Write: (0x%02x to 0x%02x)", data, addr);
+	mutex_unlock(&ca->ca_lock);
+	udelay(50);
+
+	return 0;
+}
+
+int mantis_hif_init(struct mantis_ca *ca)
+{
+	struct mantis_slot *slot = ca->slot;
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 irqcfg;
+
+	slot[0].slave_cfg = 0x70773028;
+	dprintk(MANTIS_ERROR, 1, "Adapter(%d) Initializing Mantis Host Interface", mantis->num);
+
+	mutex_lock(&ca->ca_lock);
+	irqcfg = mmread(MANTIS_GPIF_IRQCFG);
+	irqcfg = MANTIS_MASK_BRRDY	|
+		 MANTIS_MASK_WRACK	|
+		 MANTIS_MASK_EXTIRQ	|
+		 MANTIS_MASK_WSTO	|
+		 MANTIS_MASK_OTHERR	|
+		 MANTIS_MASK_OVFLW;
+
+	mmwrite(irqcfg, MANTIS_GPIF_IRQCFG);
+	mutex_unlock(&ca->ca_lock);
+
+	return 0;
+}
+
+void mantis_hif_exit(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+	u32 irqcfg;
+
+	dprintk(MANTIS_ERROR, 1, "Adapter(%d) Exiting Mantis Host Interface", mantis->num);
+	mutex_lock(&ca->ca_lock);
+	irqcfg = mmread(MANTIS_GPIF_IRQCFG);
+	irqcfg &= ~MANTIS_MASK_BRRDY;
+	mmwrite(irqcfg, MANTIS_GPIF_IRQCFG);
+	mutex_unlock(&ca->ca_lock);
+}
diff --git a/drivers/media/dvb/mantis/mantis_hif.h b/drivers/media/dvb/mantis/mantis_hif.h
new file mode 100644
index 0000000..9094f9e
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_hif.h
@@ -0,0 +1,29 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_HIF_H
+#define __MANTIS_HIF_H
+
+#define MANTIS_HIF_MEMRD		1
+#define MANTIS_HIF_MEMWR		2
+#define MANTIS_HIF_IOMRD		3
+#define MANTIS_HIF_IOMWR		4
+
+#endif /* __MANTIS_HIF_H */
diff --git a/drivers/media/dvb/mantis/mantis_i2c.c b/drivers/media/dvb/mantis/mantis_i2c.c
new file mode 100644
index 0000000..7870bcf
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_i2c.c
@@ -0,0 +1,267 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <asm/io.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_i2c.h"
+
+#define TRIALS			10000
+
+static int mantis_i2c_read(struct mantis_pci *mantis, const struct i2c_msg *msg)
+{
+	u32 rxd, i, stat, trials;
+
+	dprintk(MANTIS_INFO, 0, "        %s:  Address=[0x%02x] <R>[ ",
+		__func__, msg->addr);
+
+	for (i = 0; i < msg->len; i++) {
+		rxd = (msg->addr << 25) | (1 << 24)
+					| MANTIS_I2C_RATE_3
+					| MANTIS_I2C_STOP
+					| MANTIS_I2C_PGMODE;
+
+		if (i == (msg->len - 1))
+			rxd &= ~MANTIS_I2C_STOP;
+
+		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
+		mmwrite(rxd, MANTIS_I2CDATA_CTL);
+
+		/* wait for xfer completion */
+		for (trials = 0; trials < TRIALS; trials++) {
+			stat = mmread(MANTIS_INT_STAT);
+			if (stat & MANTIS_INT_I2CDONE)
+				break;
+		}
+
+		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
+
+		/* wait for xfer completion */
+		for (trials = 0; trials < TRIALS; trials++) {
+			stat = mmread(MANTIS_INT_STAT);
+			if (stat & MANTIS_INT_I2CRACK)
+				break;
+		}
+
+		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
+
+		rxd = mmread(MANTIS_I2CDATA_CTL);
+		msg->buf[i] = (u8)((rxd >> 8) & 0xFF);
+		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
+	}
+	dprintk(MANTIS_INFO, 0, "]\n");
+
+	return 0;
+}
+
+static int mantis_i2c_write(struct mantis_pci *mantis, const struct i2c_msg *msg)
+{
+	int i;
+	u32 txd = 0, stat, trials;
+
+	dprintk(MANTIS_INFO, 0, "        %s: Address=[0x%02x] <W>[ ",
+		__func__, msg->addr);
+
+	for (i = 0; i < msg->len; i++) {
+		dprintk(MANTIS_INFO, 0, "%02x ", msg->buf[i]);
+		txd = (msg->addr << 25) | (msg->buf[i] << 8)
+					| MANTIS_I2C_RATE_3
+					| MANTIS_I2C_STOP
+					| MANTIS_I2C_PGMODE;
+
+		if (i == (msg->len - 1))
+			txd &= ~MANTIS_I2C_STOP;
+
+		mmwrite(MANTIS_INT_I2CDONE, MANTIS_INT_STAT);
+		mmwrite(txd, MANTIS_I2CDATA_CTL);
+
+		/* wait for xfer completion */
+		for (trials = 0; trials < TRIALS; trials++) {
+			stat = mmread(MANTIS_INT_STAT);
+			if (stat & MANTIS_INT_I2CDONE)
+				break;
+		}
+
+		dprintk(MANTIS_TMG, 0, "I2CDONE: trials=%d\n", trials);
+
+		/* wait for xfer completion */
+		for (trials = 0; trials < TRIALS; trials++) {
+			stat = mmread(MANTIS_INT_STAT);
+			if (stat & MANTIS_INT_I2CRACK)
+				break;
+		}
+
+		dprintk(MANTIS_TMG, 0, "I2CRACK: trials=%d\n", trials);
+	}
+	dprintk(MANTIS_INFO, 0, "]\n");
+
+	return 0;
+}
+
+static int mantis_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
+{
+	int ret = 0, i = 0, trials;
+	u32 stat, data, txd;
+	struct mantis_pci *mantis;
+	struct mantis_hwconfig *config;
+
+	mantis = i2c_get_adapdata(adapter);
+	BUG_ON(!mantis);
+	config = mantis->hwconfig;
+	BUG_ON(!config);
+
+	dprintk(MANTIS_DEBUG, 1, "Messages:%d", num);
+	mutex_lock(&mantis->i2c_lock);
+
+	while (i < num) {
+		/* Byte MODE */
+		if ((config->i2c_mode & MANTIS_BYTE_MODE) &&
+		    ((i + 1) < num)			&&
+		    (msgs[i].len < 2)			&&
+		    (msgs[i + 1].len < 2)		&&
+		    (msgs[i + 1].flags & I2C_M_RD)) {
+
+			dprintk(MANTIS_DEBUG, 0, "        Byte MODE:\n");
+
+			/* Read operation */
+			txd = msgs[i].addr << 25 | (0x1 << 24)
+						 | (msgs[i].buf[0] << 16)
+						 | MANTIS_I2C_RATE_3;
+
+			mmwrite(txd, MANTIS_I2CDATA_CTL);
+			/* wait for xfer completion */
+			for (trials = 0; trials < TRIALS; trials++) {
+				stat = mmread(MANTIS_INT_STAT);
+				if (stat & MANTIS_INT_I2CDONE)
+					break;
+			}
+
+			/* check for xfer completion */
+			if (stat & MANTIS_INT_I2CDONE) {
+				/* check xfer was acknowledged */
+				if (stat & MANTIS_INT_I2CRACK) {
+					data = mmread(MANTIS_I2CDATA_CTL);
+					msgs[i + 1].buf[0] = (data >> 8) & 0xff;
+					dprintk(MANTIS_DEBUG, 0, "        Byte <%d> RXD=0x%02x  [%02x]\n", 0x0, data, msgs[i + 1].buf[0]);
+				} else {
+					/* I/O error */
+					dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
+					ret = -EIO;
+					break;
+				}
+			} else {
+				/* I/O error */
+				dprintk(MANTIS_ERROR, 1, "        I/O error, LINE:%d", __LINE__);
+				ret = -EIO;
+				break;
+			}
+			i += 2; /* Write/Read operation in one go */
+		}
+
+		if (i < num) {
+			if (msgs[i].flags & I2C_M_RD)
+				ret = mantis_i2c_read(mantis, &msgs[i]);
+			else
+				ret = mantis_i2c_write(mantis, &msgs[i]);
+
+			i++;
+			if (ret < 0)
+				goto bail_out;
+		}
+
+	}
+
+	mutex_unlock(&mantis->i2c_lock);
+
+	return num;
+
+bail_out:
+	mutex_unlock(&mantis->i2c_lock);
+	return ret;
+}
+
+static u32 mantis_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm mantis_algo = {
+	.master_xfer		= mantis_i2c_xfer,
+	.functionality		= mantis_i2c_func,
+};
+
+int __devinit mantis_i2c_init(struct mantis_pci *mantis)
+{
+	u32 intstat, intmask;
+	struct i2c_adapter *i2c_adapter = &mantis->adapter;
+	struct pci_dev *pdev		= mantis->pdev;
+
+	init_waitqueue_head(&mantis->i2c_wq);
+	mutex_init(&mantis->i2c_lock);
+	strncpy(i2c_adapter->name, "Mantis I2C", sizeof(i2c_adapter->name));
+	i2c_set_adapdata(i2c_adapter, mantis);
+
+	i2c_adapter->owner	= THIS_MODULE;
+	i2c_adapter->class	= I2C_CLASS_TV_DIGITAL;
+	i2c_adapter->algo	= &mantis_algo;
+	i2c_adapter->algo_data	= NULL;
+	i2c_adapter->timeout	= 500;
+	i2c_adapter->retries	= 3;
+	i2c_adapter->dev.parent	= &pdev->dev;
+
+	mantis->i2c_rc		= i2c_add_adapter(i2c_adapter);
+	if (mantis->i2c_rc < 0)
+		return mantis->i2c_rc;
+
+	dprintk(MANTIS_DEBUG, 1, "Initializing I2C ..");
+
+	intstat = mmread(MANTIS_INT_STAT);
+	intmask = mmread(MANTIS_INT_MASK);
+	mmwrite(intstat, MANTIS_INT_STAT);
+	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
+	intmask = mmread(MANTIS_INT_MASK);
+	mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_i2c_init);
+
+int mantis_i2c_exit(struct mantis_pci *mantis)
+{
+	u32 intmask;
+
+	dprintk(MANTIS_DEBUG, 1, "Disabling I2C interrupt");
+	intmask = mmread(MANTIS_INT_MASK);
+	mmwrite((intmask & ~MANTIS_INT_I2CDONE), MANTIS_INT_MASK);
+
+	dprintk(MANTIS_DEBUG, 1, "Removing I2C adapter");
+	return i2c_del_adapter(&mantis->adapter);
+}
+EXPORT_SYMBOL_GPL(mantis_i2c_exit);
diff --git a/drivers/media/dvb/mantis/mantis_i2c.h b/drivers/media/dvb/mantis/mantis_i2c.h
new file mode 100644
index 0000000..1342df2
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_i2c.h
@@ -0,0 +1,30 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_I2C_H
+#define __MANTIS_I2C_H
+
+#define I2C_STOP		(1 <<  0)
+#define I2C_READ		(1 <<  1)
+
+extern int mantis_i2c_init(struct mantis_pci *mantis);
+extern int mantis_i2c_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_I2C_H */
diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c
new file mode 100644
index 0000000..6a9df77
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_input.c
@@ -0,0 +1,148 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/input.h>
+#include <media/ir-common.h>
+#include <linux/pci.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_uart.h"
+
+static struct ir_scancode mantis_ir_table[] = {
+	{ 0x29, KEY_POWER	},
+	{ 0x28, KEY_FAVORITES	},
+	{ 0x30, KEY_TEXT	},
+	{ 0x17, KEY_INFO	}, /* Preview */
+	{ 0x23, KEY_EPG		},
+	{ 0x3b, KEY_F22		}, /* Record List */
+	{ 0x3c, KEY_1		},
+	{ 0x3e, KEY_2		},
+	{ 0x39, KEY_3		},
+	{ 0x36, KEY_4		},
+	{ 0x22, KEY_5		},
+	{ 0x20, KEY_6		},
+	{ 0x32, KEY_7		},
+	{ 0x26, KEY_8		},
+	{ 0x24, KEY_9		},
+	{ 0x2a, KEY_0		},
+
+	{ 0x33, KEY_CANCEL	},
+	{ 0x2c, KEY_BACK	},
+	{ 0x15, KEY_CLEAR	},
+	{ 0x3f, KEY_TAB		},
+	{ 0x10, KEY_ENTER	},
+	{ 0x14, KEY_UP		},
+	{ 0x0d, KEY_RIGHT	},
+	{ 0x0e, KEY_DOWN	},
+	{ 0x11, KEY_LEFT	},
+
+	{ 0x21, KEY_VOLUMEUP	},
+	{ 0x35, KEY_VOLUMEDOWN	},
+	{ 0x3d, KEY_CHANNELDOWN	},
+	{ 0x3a, KEY_CHANNELUP	},
+	{ 0x2e, KEY_RECORD	},
+	{ 0x2b, KEY_PLAY	},
+	{ 0x13, KEY_PAUSE	},
+	{ 0x25, KEY_STOP	},
+
+	{ 0x1f, KEY_REWIND	},
+	{ 0x2d, KEY_FASTFORWARD	},
+	{ 0x1e, KEY_PREVIOUS	}, /* Replay |< */
+	{ 0x1d, KEY_NEXT	}, /* Skip   >| */
+
+	{ 0x0b, KEY_CAMERA	}, /* Capture */
+	{ 0x0f, KEY_LANGUAGE	}, /* SAP */
+	{ 0x18, KEY_MODE	}, /* PIP */
+	{ 0x12, KEY_ZOOM	}, /* Full screen */
+	{ 0x1c, KEY_SUBTITLE	},
+	{ 0x2f, KEY_MUTE	},
+	{ 0x16, KEY_F20		}, /* L/R */
+	{ 0x38, KEY_F21		}, /* Hibernate */
+
+	{ 0x37, KEY_SWITCHVIDEOMODE }, /* A/V */
+	{ 0x31, KEY_AGAIN	}, /* Recall */
+	{ 0x1a, KEY_KPPLUS	}, /* Zoom+ */
+	{ 0x19, KEY_KPMINUS	}, /* Zoom- */
+	{ 0x27, KEY_RED		},
+	{ 0x0C, KEY_GREEN	},
+	{ 0x01, KEY_YELLOW	},
+	{ 0x00, KEY_BLUE	},
+};
+
+struct ir_scancode_table ir_mantis = {
+	.scan = mantis_ir_table,
+	.size = ARRAY_SIZE(mantis_ir_table),
+};
+EXPORT_SYMBOL_GPL(ir_mantis);
+
+int mantis_input_init(struct mantis_pci *mantis)
+{
+	struct input_dev *rc;
+	struct ir_input_state rc_state;
+	char name[80], dev[80];
+	int err;
+
+	rc = input_allocate_device();
+	if (!rc) {
+		dprintk(MANTIS_ERROR, 1, "Input device allocate failed");
+		return -ENOMEM;
+	}
+
+	sprintf(name, "Mantis %s IR receiver", mantis->hwconfig->model_name);
+	sprintf(dev, "pci-%s/ir0", pci_name(mantis->pdev));
+
+	rc->name = name;
+	rc->phys = dev;
+
+	ir_input_init(rc, &rc_state, IR_TYPE_OTHER);
+
+	rc->id.bustype	= BUS_PCI;
+	rc->id.vendor	= mantis->vendor_id;
+	rc->id.product	= mantis->device_id;
+	rc->id.version	= 1;
+	rc->dev		= mantis->pdev->dev;
+
+	err = ir_input_register(rc, &ir_mantis);
+	if (err) {
+		dprintk(MANTIS_ERROR, 1, "IR device registration failed, ret = %d", err);
+		input_free_device(rc);
+		return -ENODEV;
+	}
+
+	mantis->rc = rc;
+
+	return 0;
+}
+
+int mantis_exit(struct mantis_pci *mantis)
+{
+	struct input_dev *rc = mantis->rc;
+
+	ir_input_unregister(rc);
+
+	return 0;
+}
diff --git a/drivers/media/dvb/mantis/mantis_ioc.c b/drivers/media/dvb/mantis/mantis_ioc.c
new file mode 100644
index 0000000..de148de
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_ioc.c
@@ -0,0 +1,130 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_ioc.h"
+
+static int read_eeprom_bytes(struct mantis_pci *mantis, u8 reg, u8 *data, u8 length)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+	int err;
+	u8 buf = reg;
+
+	struct i2c_msg msg[] = {
+		{ .addr = 0x50, .flags = 0, .buf = &buf, .len = 1 },
+		{ .addr = 0x50, .flags = I2C_M_RD, .buf = data, .len = length },
+	};
+
+	err = i2c_transfer(adapter, msg, 2);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: i2c read: < err=%i d0=0x%02x d1=0x%02x >",
+			err, data[0], data[1]);
+
+		return err;
+	}
+
+	return 0;
+}
+int mantis_get_mac(struct mantis_pci *mantis)
+{
+	int err;
+	u8 mac_addr[6] = {0};
+
+	err = read_eeprom_bytes(mantis, 0x08, mac_addr, 6);
+	if (err < 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Mantis EEPROM read error <%d>", err);
+
+		return err;
+	}
+
+	dprintk(MANTIS_ERROR, 0,
+		"    MAC Address=[%02x:%02x:%02x:%02x:%02x:%02x]\n",
+		mac_addr[0],
+		mac_addr[1],
+		mac_addr[2],
+		mac_addr[3],
+		mac_addr[4],
+		mac_addr[5]);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_get_mac);
+
+/* Turn the given bit on or off. */
+void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value)
+{
+	u32 cur;
+
+	dprintk(MANTIS_DEBUG, 1, "Set Bit <%d> to <%d>", bitpos, value);
+	cur = mmread(MANTIS_GPIF_ADDR);
+	if (value)
+		mantis->gpio_status = cur | (1 << bitpos);
+	else
+		mantis->gpio_status = cur & (~(1 << bitpos));
+
+	dprintk(MANTIS_DEBUG, 1, "GPIO Value <%02x>", mantis->gpio_status);
+	mmwrite(mantis->gpio_status, MANTIS_GPIF_ADDR);
+	mmwrite(0x00, MANTIS_GPIF_DOUT);
+}
+EXPORT_SYMBOL_GPL(gpio_set_bits);
+
+int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl)
+{
+	u32 reg;
+
+	reg = mmread(MANTIS_CONTROL);
+	switch (stream_ctl) {
+	case STREAM_TO_HIF:
+		dprintk(MANTIS_DEBUG, 1, "Set stream to HIF");
+		reg &= 0xff - MANTIS_BYPASS;
+		mmwrite(reg, MANTIS_CONTROL);
+		reg |= MANTIS_BYPASS;
+		mmwrite(reg, MANTIS_CONTROL);
+		break;
+
+	case STREAM_TO_CAM:
+		dprintk(MANTIS_DEBUG, 1, "Set stream to CAM");
+		reg |= MANTIS_BYPASS;
+		mmwrite(reg, MANTIS_CONTROL);
+		reg &= 0xff - MANTIS_BYPASS;
+		mmwrite(reg, MANTIS_CONTROL);
+		break;
+	default:
+		dprintk(MANTIS_ERROR, 1, "Unknown MODE <%02x>", stream_ctl);
+		return -1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_stream_control);
diff --git a/drivers/media/dvb/mantis/mantis_ioc.h b/drivers/media/dvb/mantis/mantis_ioc.h
new file mode 100644
index 0000000..188fe5a
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_ioc.h
@@ -0,0 +1,51 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_IOC_H
+#define __MANTIS_IOC_H
+
+#define GPIF_A00		0x00
+#define GPIF_A01		0x01
+#define GPIF_A02		0x02
+#define GPIF_A03		0x03
+#define GPIF_A04		0x04
+#define GPIF_A05		0x05
+#define GPIF_A06		0x06
+#define GPIF_A07		0x07
+#define GPIF_A08		0x08
+#define GPIF_A09		0x09
+#define GPIF_A10		0x0a
+#define GPIF_A11		0x0b
+
+#define GPIF_A12		0x0c
+#define GPIF_A13		0x0d
+#define GPIF_A14		0x0e
+
+enum mantis_stream_control {
+	STREAM_TO_HIF = 0,
+	STREAM_TO_CAM
+};
+
+extern int mantis_get_mac(struct mantis_pci *mantis);
+extern void gpio_set_bits(struct mantis_pci *mantis, u32 bitpos, u8 value);
+
+extern int mantis_stream_control(struct mantis_pci *mantis, enum mantis_stream_control stream_ctl);
+
+#endif /* __MANTIS_IOC_H */
diff --git a/drivers/media/dvb/mantis/mantis_link.h b/drivers/media/dvb/mantis/mantis_link.h
new file mode 100644
index 0000000..2a81477
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_link.h
@@ -0,0 +1,83 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_LINK_H
+#define __MANTIS_LINK_H
+
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include "dvb_ca_en50221.h"
+
+enum mantis_sbuf_status {
+	MANTIS_SBUF_DATA_AVAIL		= 1,
+	MANTIS_SBUF_DATA_EMPTY		= 2,
+	MANTIS_SBUF_DATA_OVFLW		= 3
+};
+
+struct mantis_slot {
+	u32				timeout;
+	u32				slave_cfg;
+	u32				bar;
+};
+
+/* Physical layer */
+enum mantis_slot_state {
+	MODULE_INSERTED			= 3,
+	MODULE_XTRACTED			= 4
+};
+
+struct mantis_ca {
+	struct mantis_slot		slot[4];
+
+	struct work_struct		hif_evm_work;
+
+	u32				hif_event;
+	wait_queue_head_t		hif_opdone_wq;
+	wait_queue_head_t		hif_brrdyw_wq;
+	wait_queue_head_t		hif_data_wq;
+	wait_queue_head_t		hif_write_wq; /* HIF Write op */
+
+	enum mantis_sbuf_status		sbuf_status;
+
+	enum mantis_slot_state		slot_state;
+
+	void				*ca_priv;
+
+	struct dvb_ca_en50221		en50221;
+	struct mutex			ca_lock;
+};
+
+/* CA */
+extern void mantis_event_cam_plugin(struct mantis_ca *ca);
+extern void mantis_event_cam_unplug(struct mantis_ca *ca);
+extern int mantis_pcmcia_init(struct mantis_ca *ca);
+extern void mantis_pcmcia_exit(struct mantis_ca *ca);
+extern int mantis_evmgr_init(struct mantis_ca *ca);
+extern void mantis_evmgr_exit(struct mantis_ca *ca);
+
+/* HIF */
+extern int mantis_hif_init(struct mantis_ca *ca);
+extern void mantis_hif_exit(struct mantis_ca *ca);
+extern int mantis_hif_read_mem(struct mantis_ca *ca, u32 addr);
+extern int mantis_hif_write_mem(struct mantis_ca *ca, u32 addr, u8 data);
+extern int mantis_hif_read_iom(struct mantis_ca *ca, u32 addr);
+extern int mantis_hif_write_iom(struct mantis_ca *ca, u32 addr, u8 data);
+
+#endif /* __MANTIS_LINK_H */
diff --git a/drivers/media/dvb/mantis/mantis_pci.c b/drivers/media/dvb/mantis/mantis_pci.c
new file mode 100644
index 0000000..6c7534a
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_pci.c
@@ -0,0 +1,177 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/pci.h>
+
+#include <asm/irq.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include <asm/irq.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_pci.h"
+
+#define DRIVER_NAME		"Mantis Core"
+
+int __devinit mantis_pci_init(struct mantis_pci *mantis)
+{
+	u8 revision, latency;
+	struct mantis_hwconfig *config	= mantis->hwconfig;
+	struct pci_dev *pdev		= mantis->pdev;
+	int err, ret = 0;
+
+	dprintk(MANTIS_ERROR, 0, "found a %s PCI %s device on (%02x:%02x.%x),\n",
+		config->model_name,
+		config->dev_type,
+		mantis->pdev->bus->number,
+		PCI_SLOT(mantis->pdev->devfn),
+		PCI_FUNC(mantis->pdev->devfn));
+
+	err = pci_enable_device(pdev);
+	if (err != 0) {
+		ret = -ENODEV;
+		dprintk(MANTIS_ERROR, 1, "ERROR: PCI enable failed <%i>", err);
+		goto fail0;
+	}
+
+	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err != 0) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: Unable to obtain 32 bit DMA <%i>", err);
+		ret = -ENOMEM;
+		goto fail1;
+	}
+
+	pci_set_master(pdev);
+
+	if (!request_mem_region(pci_resource_start(pdev, 0),
+				pci_resource_len(pdev, 0),
+				DRIVER_NAME)) {
+
+		dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 Request failed !");
+		ret = -ENODEV;
+		goto fail1;
+	}
+
+	mantis->mmio = ioremap(pci_resource_start(pdev, 0),
+			       pci_resource_len(pdev, 0));
+
+	if (!mantis->mmio) {
+		dprintk(MANTIS_ERROR, 1, "ERROR: BAR0 remap failed !");
+		ret = -ENODEV;
+		goto fail2;
+	}
+
+	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency);
+	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
+	mantis->latency = latency;
+	mantis->revision = revision;
+
+	dprintk(MANTIS_ERROR, 0, "    Mantis Rev %d [%04x:%04x], ",
+		mantis->revision,
+		mantis->pdev->subsystem_vendor,
+		mantis->pdev->subsystem_device);
+
+	dprintk(MANTIS_ERROR, 0,
+		"irq: %d, latency: %d\n    memory: 0x%lx, mmio: 0x%p\n",
+		mantis->pdev->irq,
+		mantis->latency,
+		mantis->mantis_addr,
+		mantis->mmio);
+
+	err = request_irq(pdev->irq,
+			  config->irq_handler,
+			  IRQF_SHARED,
+			  DRIVER_NAME,
+			  mantis);
+
+	if (err != 0) {
+
+		dprintk(MANTIS_ERROR, 1, "ERROR: IRQ registration failed ! <%d>", err);
+		ret = -ENODEV;
+		goto fail3;
+	}
+
+	pci_set_drvdata(pdev, mantis);
+	return ret;
+
+	/* Error conditions */
+fail3:
+	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> I/O unmap", ret);
+	if (mantis->mmio)
+		iounmap(mantis->mmio);
+
+fail2:
+	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> releasing regions", ret);
+	release_mem_region(pci_resource_start(pdev, 0),
+			   pci_resource_len(pdev, 0));
+
+fail1:
+	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> disabling device", ret);
+	pci_disable_device(pdev);
+
+fail0:
+	dprintk(MANTIS_ERROR, 1, "ERROR: <%d> exiting", ret);
+	pci_set_drvdata(pdev, NULL);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mantis_pci_init);
+
+void mantis_pci_exit(struct mantis_pci *mantis)
+{
+	struct pci_dev *pdev = mantis->pdev;
+
+	dprintk(MANTIS_NOTICE, 1, " mem: 0x%p", mantis->mmio);
+	free_irq(pdev->irq, mantis);
+	if (mantis->mmio) {
+		iounmap(mantis->mmio);
+		release_mem_region(pci_resource_start(pdev, 0),
+				   pci_resource_len(pdev, 0));
+	}
+
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+EXPORT_SYMBOL_GPL(mantis_pci_exit);
+
+MODULE_DESCRIPTION("Mantis PCI DTV bridge driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/mantis/mantis_pci.h b/drivers/media/dvb/mantis/mantis_pci.h
new file mode 100644
index 0000000..65f0045
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_pci.h
@@ -0,0 +1,27 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_PCI_H
+#define __MANTIS_PCI_H
+
+extern int mantis_pci_init(struct mantis_pci *mantis);
+extern void mantis_pci_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_PCI_H */
diff --git a/drivers/media/dvb/mantis/mantis_pcmcia.c b/drivers/media/dvb/mantis/mantis_pcmcia.c
new file mode 100644
index 0000000..5cb545b
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_pcmcia.c
@@ -0,0 +1,120 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_link.h" /* temporary due to physical layer stuff */
+#include "mantis_reg.h"
+
+/*
+ * If Slot state is already PLUG_IN event and we are called
+ * again, definitely it is jitter alone
+ */
+void mantis_event_cam_plugin(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	u32 gpif_irqcfg;
+
+	if (ca->slot_state == MODULE_XTRACTED) {
+		dprintk(MANTIS_DEBUG, 1, "Event: CAM Plugged IN: Adapter(%d) Slot(0)", mantis->num);
+		udelay(50);
+		mmwrite(0xda000000, MANTIS_CARD_RESET);
+		gpif_irqcfg  = mmread(MANTIS_GPIF_IRQCFG);
+		gpif_irqcfg |= MANTIS_MASK_PLUGOUT;
+		gpif_irqcfg &= ~MANTIS_MASK_PLUGIN;
+		mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG);
+		udelay(500);
+		ca->slot_state = MODULE_INSERTED;
+	}
+	udelay(100);
+}
+
+/*
+ * If Slot state is already UN_PLUG event and we are called
+ * again, definitely it is jitter alone
+ */
+void mantis_event_cam_unplug(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	u32 gpif_irqcfg;
+
+	if (ca->slot_state == MODULE_INSERTED) {
+		dprintk(MANTIS_DEBUG, 1, "Event: CAM Unplugged: Adapter(%d) Slot(0)", mantis->num);
+		udelay(50);
+		mmwrite(0x00da0000, MANTIS_CARD_RESET);
+		gpif_irqcfg  = mmread(MANTIS_GPIF_IRQCFG);
+		gpif_irqcfg |= MANTIS_MASK_PLUGIN;
+		gpif_irqcfg &= ~MANTIS_MASK_PLUGOUT;
+		mmwrite(gpif_irqcfg, MANTIS_GPIF_IRQCFG);
+		udelay(500);
+		ca->slot_state = MODULE_XTRACTED;
+	}
+	udelay(100);
+}
+
+int mantis_pcmcia_init(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	u32 gpif_stat, card_stat;
+
+	mmwrite(mmread(MANTIS_INT_MASK) | MANTIS_INT_IRQ0, MANTIS_INT_MASK);
+	gpif_stat = mmread(MANTIS_GPIF_STATUS);
+	card_stat = mmread(MANTIS_GPIF_IRQCFG);
+
+	if (gpif_stat & MANTIS_GPIF_DETSTAT) {
+		dprintk(MANTIS_DEBUG, 1, "CAM found on Adapter(%d) Slot(0)", mantis->num);
+		mmwrite(card_stat | MANTIS_MASK_PLUGOUT, MANTIS_GPIF_IRQCFG);
+		ca->slot_state = MODULE_INSERTED;
+		dvb_ca_en50221_camchange_irq(&ca->en50221,
+					     0,
+					     DVB_CA_EN50221_CAMCHANGE_INSERTED);
+	} else {
+		dprintk(MANTIS_DEBUG, 1, "Empty Slot on Adapter(%d) Slot(0)", mantis->num);
+		mmwrite(card_stat | MANTIS_MASK_PLUGIN, MANTIS_GPIF_IRQCFG);
+		ca->slot_state = MODULE_XTRACTED;
+		dvb_ca_en50221_camchange_irq(&ca->en50221,
+					     0,
+					     DVB_CA_EN50221_CAMCHANGE_REMOVED);
+	}
+
+	return 0;
+}
+
+void mantis_pcmcia_exit(struct mantis_ca *ca)
+{
+	struct mantis_pci *mantis = ca->ca_priv;
+
+	mmwrite(mmread(MANTIS_GPIF_STATUS) & (~MANTIS_CARD_PLUGOUT | ~MANTIS_CARD_PLUGIN), MANTIS_GPIF_STATUS);
+	mmwrite(mmread(MANTIS_INT_MASK) & ~MANTIS_INT_IRQ0, MANTIS_INT_MASK);
+}
diff --git a/drivers/media/dvb/mantis/mantis_reg.h b/drivers/media/dvb/mantis/mantis_reg.h
new file mode 100644
index 0000000..7761f9d
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_reg.h
@@ -0,0 +1,197 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_REG_H
+#define __MANTIS_REG_H
+
+/* Interrupts */
+#define MANTIS_INT_STAT			0x00
+#define MANTIS_INT_MASK			0x04
+
+#define MANTIS_INT_RISCSTAT		(0x0f << 28)
+#define MANTIS_INT_RISCEN		(0x01 << 27)
+#define MANTIS_INT_I2CRACK		(0x01 << 26)
+
+/* #define MANTIS_INT_GPIF			(0xff << 12) */
+
+#define MANTIS_INT_PCMCIA7		(0x01 << 19)
+#define MANTIS_INT_PCMCIA6		(0x01 << 18)
+#define MANTIS_INT_PCMCIA5		(0x01 << 17)
+#define MANTIS_INT_PCMCIA4		(0x01 << 16)
+#define MANTIS_INT_PCMCIA3		(0x01 << 15)
+#define MANTIS_INT_PCMCIA2		(0x01 << 14)
+#define MANTIS_INT_PCMCIA1		(0x01 << 13)
+#define MANTIS_INT_PCMCIA0		(0x01 << 12)
+#define MANTIS_INT_IRQ1			(0x01 << 11)
+#define MANTIS_INT_IRQ0			(0x01 << 10)
+#define MANTIS_INT_OCERR		(0x01 <<  8)
+#define MANTIS_INT_PABORT		(0x01 <<  7)
+#define MANTIS_INT_RIPERR		(0x01 <<  6)
+#define MANTIS_INT_PPERR		(0x01 <<  5)
+#define MANTIS_INT_FTRGT		(0x01 <<  3)
+#define MANTIS_INT_RISCI		(0x01 <<  1)
+#define MANTIS_INT_I2CDONE		(0x01 <<  0)
+
+/* DMA */
+#define MANTIS_DMA_CTL			0x08
+#define MANTIS_GPIF_RD			(0xff << 24)
+#define MANTIS_GPIF_WR			(0xff << 16)
+#define MANTIS_CPU_DO			(0x01 << 10)
+#define MANTIS_DRV_DO			(0x01 <<  9)
+#define	MANTIS_I2C_RD			(0x01 <<  7)
+#define MANTIS_I2C_WR			(0x01 <<  6)
+#define MANTIS_DCAP_MODE		(0x01 <<  5)
+#define MANTIS_FIFO_TP_4		(0x00 <<  3)
+#define MANTIS_FIFO_TP_8		(0x01 <<  3)
+#define MANTIS_FIFO_TP_16		(0x02 <<  3)
+#define MANTIS_FIFO_EN			(0x01 <<  2)
+#define MANTIS_DCAP_EN			(0x01 <<  1)
+#define MANTIS_RISC_EN			(0x01 <<  0)
+
+/* DEBUG */
+#define MANTIS_DEBUGREG			0x0c
+#define MANTIS_DATINV			(0x0e <<  7)
+#define MANTIS_TOP_DEBUGSEL		(0x07 <<  4)
+#define MANTIS_PCMCIA_DEBUGSEL		(0x0f <<  0)
+
+#define MANTIS_RISC_START		0x10
+#define MANTIS_RISC_PC			0x14
+
+/* I2C */
+#define MANTIS_I2CDATA_CTL		0x18
+#define MANTIS_I2C_RATE_1		(0x00 <<  6)
+#define MANTIS_I2C_RATE_2		(0x01 <<  6)
+#define MANTIS_I2C_RATE_3		(0x02 <<  6)
+#define MANTIS_I2C_RATE_4		(0x03 <<  6)
+#define MANTIS_I2C_STOP			(0x01 <<  5)
+#define MANTIS_I2C_PGMODE		(0x01 <<  3)
+
+/* DATA */
+#define MANTIS_CMD_DATA_R1		0x20
+#define MANTIS_CMD_DATA_3		(0xff << 24)
+#define MANTIS_CMD_DATA_2		(0xff << 16)
+#define MANTIS_CMD_DATA_1		(0xff <<  8)
+#define MANTIS_CMD_DATA_0		(0xff <<  0)
+
+#define MANTIS_CMD_DATA_R2		0x24
+#define MANTIS_CMD_DATA_7		(0xff << 24)
+#define MANTIS_CMD_DATA_6		(0xff << 16)
+#define MANTIS_CMD_DATA_5		(0xff <<  8)
+#define MANTIS_CMD_DATA_4		(0xff <<  0)
+
+#define MANTIS_CONTROL			0x28
+#define MANTIS_DET			(0x01 <<  7)
+#define MANTIS_DAT_CF_EN		(0x01 <<  6)
+#define MANTIS_ACS			(0x03 <<  4)
+#define MANTIS_VCCEN			(0x01 <<  3)
+#define MANTIS_BYPASS			(0x01 <<  2)
+#define MANTIS_MRST			(0x01 <<  1)
+#define MANTIS_CRST_INT			(0x01 <<  0)
+
+#define MANTIS_GPIF_CFGSLA		0x84
+#define MANTIS_GPIF_WAITSMPL		(0x07 << 28)
+#define MANTIS_GPIF_BYTEADDRSUB		(0x01 << 25)
+#define MANTIS_GPIF_WAITPOL		(0x01 << 24)
+#define MANTIS_GPIF_NCDELAY		(0x07 << 20)
+#define MANTIS_GPIF_RW2CSDELAY		(0x07 << 16)
+#define MANTIS_GPIF_SLFTIMEDMODE	(0x01 << 15)
+#define MANTIS_GPIF_SLFTIMEDDELY	(0x7f <<  8)
+#define MANTIS_GPIF_DEVTYPE		(0x07 <<  4)
+#define MANTIS_GPIF_BIGENDIAN		(0x01 <<  3)
+#define MANTIS_GPIF_FETCHCMD		(0x03 <<  1)
+#define MANTIS_GPIF_HWORDDEV		(0x01 <<  0)
+
+#define MANTIS_GPIF_WSTOPER		0x90
+#define MANTIS_GPIF_WSTOPERWREN3	(0x01 << 31)
+#define MANTIS_GPIF_PARBOOTN		(0x01 << 29)
+#define MANTIS_GPIF_WSTOPERSLID3	(0x1f << 24)
+#define MANTIS_GPIF_WSTOPERWREN2	(0x01 << 23)
+#define MANTIS_GPIF_WSTOPERSLID2	(0x1f << 16)
+#define MANTIS_GPIF_WSTOPERWREN1	(0x01 << 15)
+#define MANTIS_GPIF_WSTOPERSLID1	(0x1f <<  8)
+#define MANTIS_GPIF_WSTOPERWREN0	(0x01 <<  7)
+#define MANTIS_GPIF_WSTOPERSLID0	(0x1f <<  0)
+
+#define MANTIS_GPIF_CS2RW		0x94
+#define MANTIS_GPIF_CS2RWWREN3		(0x01 << 31)
+#define MANTIS_GPIF_CS2RWDELY3		(0x3f << 24)
+#define MANTIS_GPIF_CS2RWWREN2		(0x01 << 23)
+#define MANTIS_GPIF_CS2RWDELY2		(0x3f << 16)
+#define MANTIS_GPIF_CS2RWWREN1		(0x01 << 15)
+#define MANTIS_GPIF_CS2RWDELY1		(0x3f <<  8)
+#define MANTIS_GPIF_CS2RWWREN0		(0x01 <<  7)
+#define MANTIS_GPIF_CS2RWDELY0		(0x3f <<  0)
+
+#define MANTIS_GPIF_IRQCFG		0x98
+#define MANTIS_GPIF_IRQPOL		(0x01 <<  8)
+#define MANTIS_MASK_WRACK		(0x01 <<  7)
+#define MANTIS_MASK_BRRDY		(0x01 <<  6)
+#define MANTIS_MASK_OVFLW		(0x01 <<  5)
+#define MANTIS_MASK_OTHERR		(0x01 <<  4)
+#define MANTIS_MASK_WSTO		(0x01 <<  3)
+#define MANTIS_MASK_EXTIRQ		(0x01 <<  2)
+#define MANTIS_MASK_PLUGIN		(0x01 <<  1)
+#define MANTIS_MASK_PLUGOUT		(0x01 <<  0)
+
+#define MANTIS_GPIF_STATUS		0x9c
+#define MANTIS_SBUF_KILLOP		(0x01 << 15)
+#define MANTIS_SBUF_OPDONE		(0x01 << 14)
+#define MANTIS_SBUF_EMPTY		(0x01 << 13)
+#define MANTIS_GPIF_DETSTAT		(0x01 <<  9)
+#define MANTIS_GPIF_INTSTAT		(0x01 <<  8)
+#define MANTIS_GPIF_WRACK		(0x01 <<  7)
+#define MANTIS_GPIF_BRRDY		(0x01 <<  6)
+#define MANTIS_SBUF_OVFLW		(0x01 <<  5)
+#define MANTIS_GPIF_OTHERR		(0x01 <<  4)
+#define MANTIS_SBUF_WSTO		(0x01 <<  3)
+#define MANTIS_GPIF_EXTIRQ		(0x01 <<  2)
+#define MANTIS_CARD_PLUGIN		(0x01 <<  1)
+#define MANTIS_CARD_PLUGOUT		(0x01 <<  0)
+
+#define MANTIS_GPIF_BRADDR		0xa0
+#define MANTIS_GPIF_PCMCIAREG		(0x01 		<< 27)
+#define MANTIS_GPIF_PCMCIAIOM		(0x01 		<< 26)
+#define MANTIS_GPIF_BR_ADDR		(0xfffffff	<<  0)
+
+#define MANTIS_GPIF_BRBYTES		0xa4
+#define MANTIS_GPIF_BRCNT		(0xfff 		<<  0)
+
+#define MANTIS_PCMCIA_RESET		0xa8
+#define MANTIS_PCMCIA_RSTVAL		(0xff << 0)
+
+#define MANTIS_CARD_RESET		0xac
+
+#define MANTIS_GPIF_ADDR		0xb0
+#define MANTIS_GPIF_HIFRDWRN		(0x01		<< 31)
+#define MANTIS_GPIF_PCMCIAREG		(0x01		<< 27)
+#define MANTIS_GPIF_PCMCIAIOM		(0x01		<< 26)
+#define MANTIS_GPIF_HIFADDR		(0xfffffff	<<  0)
+
+#define MANTIS_GPIF_DOUT		0xb4
+#define MANTIS_GPIF_HIFDOUT		(0xfffffff	<<  0)
+
+#define MANTIS_GPIF_DIN			0xb8
+#define MANTIS_GPIF_HIFDIN		(0xfffffff	<<  0)
+
+#define MANTIS_GPIF_SPARE		0xbc
+#define MANTIS_GPIF_LOGICRD		(0xffff		<< 16)
+#define MANTIS_GPIF_LOGICRW		(0xffff		<<  0)
+
+#endif /* __MANTIS_REG_H */
diff --git a/drivers/media/dvb/mantis/mantis_uart.c b/drivers/media/dvb/mantis/mantis_uart.c
new file mode 100644
index 0000000..7d2f239
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_uart.c
@@ -0,0 +1,186 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_reg.h"
+#include "mantis_uart.h"
+
+struct mantis_uart_params {
+	enum mantis_baud	baud_rate;
+	enum mantis_parity	parity;
+};
+
+static struct {
+	char string[7];
+} rates[5] = {
+	{ "9600" },
+	{ "19200" },
+	{ "38400" },
+	{ "57600" },
+	{ "115200" }
+};
+
+static struct {
+	char string[5];
+} parity[3] = {
+	{ "NONE" },
+	{ "ODD" },
+	{ "EVEN" }
+};
+
+#define UART_MAX_BUF			16
+
+int mantis_uart_read(struct mantis_pci *mantis, u8 *data)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+	u32 stat = 0, i;
+
+	/* get data */
+	for (i = 0; i < (config->bytes + 1); i++) {
+
+		stat = mmread(MANTIS_UART_STAT);
+
+		if (stat & MANTIS_UART_RXFIFO_FULL) {
+			dprintk(MANTIS_ERROR, 1, "RX Fifo FULL");
+		}
+		data[i] = mmread(MANTIS_UART_RXD) & 0x3f;
+
+		dprintk(MANTIS_DEBUG, 1, "Reading ... <%02x>", data[i] & 0x3f);
+
+		if (data[i] & (1 << 7)) {
+			dprintk(MANTIS_ERROR, 1, "UART framing error");
+			return -EINVAL;
+		}
+		if (data[i] & (1 << 6)) {
+			dprintk(MANTIS_ERROR, 1, "UART parity error");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static void mantis_uart_work(struct work_struct *work)
+{
+	struct mantis_pci *mantis = container_of(work, struct mantis_pci, uart_work);
+	struct mantis_hwconfig *config = mantis->hwconfig;
+	u8 buf[16];
+	int i;
+
+	mantis_uart_read(mantis, buf);
+
+	for (i = 0; i < (config->bytes + 1); i++)
+		dprintk(MANTIS_INFO, 1, "UART BUF:%d <%02x> ", i, buf[i]);
+
+	dprintk(MANTIS_DEBUG, 0, "\n");
+}
+
+static int mantis_uart_setup(struct mantis_pci *mantis,
+			     struct mantis_uart_params *params)
+{
+	u32 reg;
+
+	mmwrite((mmread(MANTIS_UART_CTL) | (params->parity & 0x3)), MANTIS_UART_CTL);
+
+	reg = mmread(MANTIS_UART_BAUD);
+
+	switch (params->baud_rate) {
+	case MANTIS_BAUD_9600:
+		reg |= 0xd8;
+		break;
+	case MANTIS_BAUD_19200:
+		reg |= 0x6c;
+		break;
+	case MANTIS_BAUD_38400:
+		reg |= 0x36;
+		break;
+	case MANTIS_BAUD_57600:
+		reg |= 0x23;
+		break;
+	case MANTIS_BAUD_115200:
+		reg |= 0x11;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mmwrite(reg, MANTIS_UART_BAUD);
+
+	return 0;
+}
+
+int mantis_uart_init(struct mantis_pci *mantis)
+{
+	struct mantis_hwconfig *config = mantis->hwconfig;
+	struct mantis_uart_params params;
+
+	/* default parity: */
+	params.baud_rate = config->baud_rate;
+	params.parity = config->parity;
+	dprintk(MANTIS_INFO, 1, "Initializing UART @ %sbps parity:%s",
+		rates[params.baud_rate].string,
+		parity[params.parity].string);
+
+	init_waitqueue_head(&mantis->uart_wq);
+	spin_lock_init(&mantis->uart_lock);
+
+	INIT_WORK(&mantis->uart_work, mantis_uart_work);
+
+	/* disable interrupt */
+	mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
+
+	mantis_uart_setup(mantis, &params);
+
+	/* default 1 byte */
+	mmwrite((mmread(MANTIS_UART_BAUD) | (config->bytes << 8)), MANTIS_UART_BAUD);
+
+	/* flush buffer */
+	mmwrite((mmread(MANTIS_UART_CTL) | MANTIS_UART_RXFLUSH), MANTIS_UART_CTL);
+
+	/* enable interrupt */
+	mmwrite(mmread(MANTIS_INT_MASK) | 0x800, MANTIS_INT_MASK);
+	mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL);
+
+	schedule_work(&mantis->uart_work);
+	dprintk(MANTIS_DEBUG, 1, "UART succesfully initialized");
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mantis_uart_init);
+
+void mantis_uart_exit(struct mantis_pci *mantis)
+{
+	/* disable interrupt */
+	mmwrite(mmread(MANTIS_UART_CTL) & 0xffef, MANTIS_UART_CTL);
+}
+EXPORT_SYMBOL_GPL(mantis_uart_exit);
diff --git a/drivers/media/dvb/mantis/mantis_uart.h b/drivers/media/dvb/mantis/mantis_uart.h
new file mode 100644
index 0000000..ffb62a0
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_uart.h
@@ -0,0 +1,58 @@
+/*
+	Mantis PCI bridge driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_UART_H
+#define __MANTIS_UART_H
+
+#define MANTIS_UART_CTL			0xe0
+#define MANTIS_UART_RXINT		(1 << 4)
+#define MANTIS_UART_RXFLUSH		(1 << 2)
+
+#define MANTIS_UART_RXD			0xe8
+#define MANTIS_UART_BAUD		0xec
+
+#define MANTIS_UART_STAT		0xf0
+#define MANTIS_UART_RXFIFO_DATA		(1 << 7)
+#define MANTIS_UART_RXFIFO_EMPTY	(1 << 6)
+#define MANTIS_UART_RXFIFO_FULL		(1 << 3)
+#define MANTIS_UART_FRAME_ERR		(1 << 2)
+#define MANTIS_UART_PARITY_ERR		(1 << 1)
+#define MANTIS_UART_RXTHRESH_INT	(1 << 0)
+
+enum mantis_baud {
+	MANTIS_BAUD_9600	= 0,
+	MANTIS_BAUD_19200,
+	MANTIS_BAUD_38400,
+	MANTIS_BAUD_57600,
+	MANTIS_BAUD_115200
+};
+
+enum mantis_parity {
+	MANTIS_PARITY_NONE	= 0,
+	MANTIS_PARITY_EVEN,
+	MANTIS_PARITY_ODD,
+};
+
+struct mantis_pci;
+
+extern int mantis_uart_init(struct mantis_pci *mantis);
+extern void mantis_uart_exit(struct mantis_pci *mantis);
+
+#endif /* __MANTIS_UART_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.c b/drivers/media/dvb/mantis/mantis_vp1033.c
new file mode 100644
index 0000000..4a723bd
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp1033.c
@@ -0,0 +1,212 @@
+/*
+	Mantis VP-1033 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "stv0299.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp1033.h"
+#include "mantis_reg.h"
+
+u8 lgtdqcs001f_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x00,
+	0x03, 0x00,
+	0x04, 0x2a,
+	0x05, 0x85,
+	0x06, 0x02,
+	0x07, 0x00,
+	0x08, 0x00,
+	0x0c, 0x01,
+	0x0d, 0x81,
+	0x0e, 0x44,
+	0x0f, 0x94,
+	0x10, 0x3c,
+	0x11, 0x84,
+	0x12, 0xb9,
+	0x13, 0xb5,
+	0x14, 0x4f,
+	0x15, 0xc9,
+	0x16, 0x80,
+	0x17, 0x36,
+	0x18, 0xfb,
+	0x19, 0xcf,
+	0x1a, 0xbc,
+	0x1c, 0x2b,
+	0x1d, 0x27,
+	0x1e, 0x00,
+	0x1f, 0x0b,
+	0x20, 0xa1,
+	0x21, 0x60,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x28, 0x00,
+	0x29, 0x28,
+	0x2a, 0x14,
+	0x2b, 0x0f,
+	0x2c, 0x09,
+	0x2d, 0x05,
+	0x31, 0x1f,
+	0x32, 0x19,
+	0x33, 0xfc,
+	0x34, 0x13,
+	0xff, 0xff,
+};
+
+#define MANTIS_MODEL_NAME	"VP-1033"
+#define MANTIS_DEV_TYPE		"DVB-S/DSS"
+
+int lgtdqcs001f_tuner_set(struct dvb_frontend *fe,
+			  struct dvb_frontend_parameters *params)
+{
+	struct mantis_pci *mantis	= fe->dvb->priv;
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	u8 buf[4];
+	u32 div;
+
+
+	struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf)};
+
+	div = params->frequency / 250;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] =  div & 0xff;
+	buf[2] =  0x83;
+	buf[3] =  0xc0;
+
+	if (params->frequency < 1531000)
+		buf[3] |= 0x04;
+	else
+		buf[3] &= ~0x04;
+	if (i2c_transfer(adapter, &msg, 1) < 0) {
+		dprintk(MANTIS_ERROR, 1, "Write: I2C Transfer failed");
+		return -EIO;
+	}
+	msleep_interruptible(100);
+
+	return 0;
+}
+
+int lgtdqcs001f_set_symbol_rate(struct dvb_frontend *fe,
+				u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+
+	if (srate < 1500000) {
+		aclk = 0xb7;
+		bclk = 0x47;
+	} else if (srate < 3000000) {
+		aclk = 0xb7;
+		bclk = 0x4b;
+	} else if (srate < 7000000) {
+		aclk = 0xb7;
+		bclk = 0x4f;
+	} else if (srate < 14000000) {
+		aclk = 0xb7;
+		bclk = 0x53;
+	} else if (srate < 30000000) {
+		aclk = 0xb6;
+		bclk = 0x53;
+	} else if (srate < 45000000) {
+		aclk = 0xb4;
+		bclk = 0x51;
+	}
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >>  8) & 0xff);
+	stv0299_writereg(fe, 0x21,  ratio & 0xf0);
+
+	return 0;
+}
+
+struct stv0299_config lgtdqcs001f_config = {
+	.demod_address		= 0x68,
+	.inittab		= lgtdqcs001f_inittab,
+	.mclk			= 88000000UL,
+	.invert			= 0,
+	.skip_reinit		= 0,
+	.volt13_op0_op1		= STV0299_VOLT13_OP0,
+	.min_delay_ms		= 100,
+	.set_symbol_rate	= lgtdqcs001f_set_symbol_rate,
+};
+
+static int vp1033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+
+		dprintk(MANTIS_ERROR, 1, "Probing for STV0299 (DVB-S)");
+		fe = stv0299_attach(&lgtdqcs001f_config, adapter);
+
+		if (fe) {
+			fe->ops.tuner_ops.set_params = lgtdqcs001f_tuner_set;
+			dprintk(MANTIS_ERROR, 1, "found STV0299 DVB-S frontend @ 0x%02x",
+				lgtdqcs001f_config.demod_address);
+
+			dprintk(MANTIS_ERROR, 1, "Mantis DVB-S STV0299 frontend attach success");
+		} else {
+			return -1;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+	mantis->fe = fe;
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp1033_config = {
+	.model_name		= MANTIS_MODEL_NAME,
+	.dev_type		= MANTIS_DEV_TYPE,
+	.ts_size		= MANTIS_TS_204,
+
+	.baud_rate		= MANTIS_BAUD_9600,
+	.parity			= MANTIS_PARITY_NONE,
+	.bytes			= 0,
+
+	.frontend_init		= vp1033_frontend_init,
+	.power			= GPIF_A12,
+	.reset			= GPIF_A13,
+};
diff --git a/drivers/media/dvb/mantis/mantis_vp1033.h b/drivers/media/dvb/mantis/mantis_vp1033.h
new file mode 100644
index 0000000..7daaa1b
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp1033.h
@@ -0,0 +1,30 @@
+/*
+	Mantis VP-1033 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP1033_H
+#define __MANTIS_VP1033_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_1033_DVB_S	0x0016
+
+extern struct mantis_hwconfig vp1033_config;
+
+#endif /* __MANTIS_VP1033_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.c b/drivers/media/dvb/mantis/mantis_vp1034.c
new file mode 100644
index 0000000..8e6ae55
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp1034.c
@@ -0,0 +1,119 @@
+/*
+	Mantis VP-1034 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mb86a16.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp1034.h"
+#include "mantis_reg.h"
+
+struct mb86a16_config vp1034_mb86a16_config = {
+	.demod_address	= 0x08,
+	.set_voltage	= vp1034_set_voltage,
+};
+
+#define MANTIS_MODEL_NAME	"VP-1034"
+#define MANTIS_DEV_TYPE		"DVB-S/DSS"
+
+int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct mantis_pci *mantis = fe->dvb->priv;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		dprintk(MANTIS_ERROR, 1, "Polarization=[13V]");
+		gpio_set_bits(mantis, 13, 1);
+		gpio_set_bits(mantis, 14, 0);
+		break;
+	case SEC_VOLTAGE_18:
+		dprintk(MANTIS_ERROR, 1, "Polarization=[18V]");
+		gpio_set_bits(mantis, 13, 1);
+		gpio_set_bits(mantis, 14, 1);
+		break;
+	case SEC_VOLTAGE_OFF:
+		dprintk(MANTIS_ERROR, 1, "Frontend (dummy) POWERDOWN");
+		break;
+	default:
+		dprintk(MANTIS_ERROR, 1, "Invalid = (%d)", (u32) voltage);
+		return -EINVAL;
+	}
+	mmwrite(0x00, MANTIS_GPIF_DOUT);
+
+	return 0;
+}
+
+static int vp1034_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+
+		dprintk(MANTIS_ERROR, 1, "Probing for MB86A16 (DVB-S/DSS)");
+		fe = mb86a16_attach(&vp1034_mb86a16_config, adapter);
+		if (fe) {
+			dprintk(MANTIS_ERROR, 1,
+			"found MB86A16 DVB-S/DSS frontend @0x%02x",
+			vp1034_mb86a16_config.demod_address);
+
+		} else {
+			return -1;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+	mantis->fe = fe;
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp1034_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_204,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp1034_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+};
diff --git a/drivers/media/dvb/mantis/mantis_vp1034.h b/drivers/media/dvb/mantis/mantis_vp1034.h
new file mode 100644
index 0000000..323f38e
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp1034.h
@@ -0,0 +1,33 @@
+/*
+	Mantis VP-1034 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP1034_H
+#define __MANTIS_VP1034_H
+
+#include "dvb_frontend.h"
+#include "mantis_common.h"
+
+
+#define MANTIS_VP_1034_DVB_S	0x0014
+
+extern struct mantis_hwconfig vp1034_config;
+extern int vp1034_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage);
+
+#endif /* __MANTIS_VP1034_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.c b/drivers/media/dvb/mantis/mantis_vp1041.c
new file mode 100644
index 0000000..515346d
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp1041.c
@@ -0,0 +1,358 @@
+/*
+	Mantis VP-1041 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp1041.h"
+#include "stb0899_reg.h"
+#include "stb0899_drv.h"
+#include "stb0899_cfg.h"
+#include "stb6100_cfg.h"
+#include "stb6100.h"
+#include "lnbp21.h"
+
+#define MANTIS_MODEL_NAME	"VP-1041"
+#define MANTIS_DEV_TYPE		"DSS/DVB-S/DVB-S2"
+
+static const struct stb0899_s1_reg vp1041_stb0899_s1_init_1[] = {
+
+	/* 0x0000000b, *//* SYSREG */
+	{ STB0899_DEV_ID		, 0x30 },
+	{ STB0899_DISCNTRL1		, 0x32 },
+	{ STB0899_DISCNTRL2     	, 0x80 },
+	{ STB0899_DISRX_ST0     	, 0x04 },
+	{ STB0899_DISRX_ST1     	, 0x00 },
+	{ STB0899_DISPARITY     	, 0x00 },
+	{ STB0899_DISFIFO       	, 0x00 },
+	{ STB0899_DISSTATUS		, 0x20 },
+	{ STB0899_DISF22        	, 0x99 },
+	{ STB0899_DISF22RX      	, 0xa8 },
+	/* SYSREG ? */
+	{ STB0899_ACRPRESC      	, 0x11 },
+	{ STB0899_ACRDIV1       	, 0x0a },
+	{ STB0899_ACRDIV2       	, 0x05 },
+	{ STB0899_DACR1         	, 0x00 },
+	{ STB0899_DACR2         	, 0x00 },
+	{ STB0899_OUTCFG        	, 0x00 },
+	{ STB0899_MODECFG       	, 0x00 },
+	{ STB0899_IRQSTATUS_3		, 0xfe },
+	{ STB0899_IRQSTATUS_2		, 0x03 },
+	{ STB0899_IRQSTATUS_1		, 0x7c },
+	{ STB0899_IRQSTATUS_0		, 0xf4 },
+	{ STB0899_IRQMSK_3      	, 0xf3 },
+	{ STB0899_IRQMSK_2      	, 0xfc },
+	{ STB0899_IRQMSK_1      	, 0xff },
+	{ STB0899_IRQMSK_0		, 0xff },
+	{ STB0899_IRQCFG		, 0x00 },
+	{ STB0899_I2CCFG        	, 0x88 },
+	{ STB0899_I2CRPT        	, 0x58 },
+	{ STB0899_IOPVALUE5		, 0x00 },
+	{ STB0899_IOPVALUE4		, 0x33 },
+	{ STB0899_IOPVALUE3		, 0x6d },
+	{ STB0899_IOPVALUE2		, 0x90 },
+	{ STB0899_IOPVALUE1		, 0x60 },
+	{ STB0899_IOPVALUE0		, 0x00 },
+	{ STB0899_GPIO00CFG     	, 0x82 },
+	{ STB0899_GPIO01CFG     	, 0x82 },
+	{ STB0899_GPIO02CFG     	, 0x82 },
+	{ STB0899_GPIO03CFG     	, 0x82 },
+	{ STB0899_GPIO04CFG     	, 0x82 },
+	{ STB0899_GPIO05CFG     	, 0x82 },
+	{ STB0899_GPIO06CFG     	, 0x82 },
+	{ STB0899_GPIO07CFG     	, 0x82 },
+	{ STB0899_GPIO08CFG     	, 0x82 },
+	{ STB0899_GPIO09CFG     	, 0x82 },
+	{ STB0899_GPIO10CFG     	, 0x82 },
+	{ STB0899_GPIO11CFG     	, 0x82 },
+	{ STB0899_GPIO12CFG     	, 0x82 },
+	{ STB0899_GPIO13CFG     	, 0x82 },
+	{ STB0899_GPIO14CFG     	, 0x82 },
+	{ STB0899_GPIO15CFG     	, 0x82 },
+	{ STB0899_GPIO16CFG     	, 0x82 },
+	{ STB0899_GPIO17CFG     	, 0x82 },
+	{ STB0899_GPIO18CFG     	, 0x82 },
+	{ STB0899_GPIO19CFG     	, 0x82 },
+	{ STB0899_GPIO20CFG     	, 0x82 },
+	{ STB0899_SDATCFG       	, 0xb8 },
+	{ STB0899_SCLTCFG       	, 0xba },
+	{ STB0899_AGCRFCFG      	, 0x1c }, /* 0x11 */
+	{ STB0899_GPIO22        	, 0x82 }, /* AGCBB2CFG */
+	{ STB0899_GPIO21        	, 0x91 }, /* AGCBB1CFG */
+	{ STB0899_DIRCLKCFG     	, 0x82 },
+	{ STB0899_CLKOUT27CFG   	, 0x7e },
+	{ STB0899_STDBYCFG      	, 0x82 },
+	{ STB0899_CS0CFG        	, 0x82 },
+	{ STB0899_CS1CFG        	, 0x82 },
+	{ STB0899_DISEQCOCFG    	, 0x20 },
+	{ STB0899_GPIO32CFG		, 0x82 },
+	{ STB0899_GPIO33CFG		, 0x82 },
+	{ STB0899_GPIO34CFG		, 0x82 },
+	{ STB0899_GPIO35CFG		, 0x82 },
+	{ STB0899_GPIO36CFG		, 0x82 },
+	{ STB0899_GPIO37CFG		, 0x82 },
+	{ STB0899_GPIO38CFG		, 0x82 },
+	{ STB0899_GPIO39CFG		, 0x82 },
+	{ STB0899_NCOARSE       	, 0x17 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */
+	{ STB0899_SYNTCTRL      	, 0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */
+	{ STB0899_FILTCTRL      	, 0x00 },
+	{ STB0899_SYSCTRL       	, 0x01 },
+	{ STB0899_STOPCLK1      	, 0x20 },
+	{ STB0899_STOPCLK2      	, 0x00 },
+	{ STB0899_INTBUFSTATUS		, 0x00 },
+	{ STB0899_INTBUFCTRL    	, 0x0a },
+	{ 0xffff			, 0xff },
+};
+
+static const struct stb0899_s1_reg vp1041_stb0899_s1_init_3[] = {
+	{ STB0899_DEMOD         	, 0x00 },
+	{ STB0899_RCOMPC        	, 0xc9 },
+	{ STB0899_AGC1CN        	, 0x01 },
+	{ STB0899_AGC1REF       	, 0x10 },
+	{ STB0899_RTC	        	, 0x23 },
+	{ STB0899_TMGCFG        	, 0x4e },
+	{ STB0899_AGC2REF       	, 0x34 },
+	{ STB0899_TLSR          	, 0x84 },
+	{ STB0899_CFD           	, 0xf7 },
+	{ STB0899_ACLC	        	, 0x87 },
+	{ STB0899_BCLC          	, 0x94 },
+	{ STB0899_EQON          	, 0x41 },
+	{ STB0899_LDT           	, 0xf1 },
+	{ STB0899_LDT2          	, 0xe3 },
+	{ STB0899_EQUALREF      	, 0xb4 },
+	{ STB0899_TMGRAMP       	, 0x10 },
+	{ STB0899_TMGTHD        	, 0x30 },
+	{ STB0899_IDCCOMP		, 0xfd },
+	{ STB0899_QDCCOMP		, 0xff },
+	{ STB0899_POWERI		, 0x0c },
+	{ STB0899_POWERQ		, 0x0f },
+	{ STB0899_RCOMP			, 0x6c },
+	{ STB0899_AGCIQIN		, 0x80 },
+	{ STB0899_AGC2I1		, 0x06 },
+	{ STB0899_AGC2I2		, 0x00 },
+	{ STB0899_TLIR			, 0x30 },
+	{ STB0899_RTF			, 0x7f },
+	{ STB0899_DSTATUS		, 0x00 },
+	{ STB0899_LDI			, 0xbc },
+	{ STB0899_CFRM			, 0xea },
+	{ STB0899_CFRL			, 0x31 },
+	{ STB0899_NIRM			, 0x2b },
+	{ STB0899_NIRL			, 0x80 },
+	{ STB0899_ISYMB			, 0x1d },
+	{ STB0899_QSYMB			, 0xa6 },
+	{ STB0899_SFRH          	, 0x2f },
+	{ STB0899_SFRM          	, 0x68 },
+	{ STB0899_SFRL          	, 0x40 },
+	{ STB0899_SFRUPH        	, 0x2f },
+	{ STB0899_SFRUPM        	, 0x68 },
+	{ STB0899_SFRUPL        	, 0x40 },
+	{ STB0899_EQUAI1		, 0x02 },
+	{ STB0899_EQUAQ1		, 0xff },
+	{ STB0899_EQUAI2		, 0x04 },
+	{ STB0899_EQUAQ2		, 0x05 },
+	{ STB0899_EQUAI3		, 0x02 },
+	{ STB0899_EQUAQ3		, 0xfd },
+	{ STB0899_EQUAI4		, 0x03 },
+	{ STB0899_EQUAQ4		, 0x07 },
+	{ STB0899_EQUAI5		, 0x08 },
+	{ STB0899_EQUAQ5		, 0xf5 },
+	{ STB0899_DSTATUS2		, 0x00 },
+	{ STB0899_VSTATUS       	, 0x00 },
+	{ STB0899_VERROR		, 0x86 },
+	{ STB0899_IQSWAP		, 0x2a },
+	{ STB0899_ECNT1M		, 0x00 },
+	{ STB0899_ECNT1L		, 0x00 },
+	{ STB0899_ECNT2M		, 0x00 },
+	{ STB0899_ECNT2L		, 0x00 },
+	{ STB0899_ECNT3M		, 0x0a },
+	{ STB0899_ECNT3L		, 0xad },
+	{ STB0899_FECAUTO1      	, 0x06 },
+	{ STB0899_FECM	        	, 0x01 },
+	{ STB0899_VTH12         	, 0xb0 },
+	{ STB0899_VTH23         	, 0x7a },
+	{ STB0899_VTH34	        	, 0x58 },
+	{ STB0899_VTH56         	, 0x38 },
+	{ STB0899_VTH67         	, 0x34 },
+	{ STB0899_VTH78         	, 0x24 },
+	{ STB0899_PRVIT         	, 0xff },
+	{ STB0899_VITSYNC       	, 0x19 },
+	{ STB0899_RSULC         	, 0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */
+	{ STB0899_TSULC         	, 0x42 },
+	{ STB0899_RSLLC         	, 0x41 },
+	{ STB0899_TSLPL	        	, 0x12 },
+	{ STB0899_TSCFGH        	, 0x0c },
+	{ STB0899_TSCFGM        	, 0x00 },
+	{ STB0899_TSCFGL        	, 0x00 },
+	{ STB0899_TSOUT			, 0x69 }, /* 0x0d for CAM */
+	{ STB0899_RSSYNCDEL     	, 0x00 },
+	{ STB0899_TSINHDELH     	, 0x02 },
+	{ STB0899_TSINHDELM		, 0x00 },
+	{ STB0899_TSINHDELL		, 0x00 },
+	{ STB0899_TSLLSTKM		, 0x1b },
+	{ STB0899_TSLLSTKL		, 0xb3 },
+	{ STB0899_TSULSTKM		, 0x00 },
+	{ STB0899_TSULSTKL		, 0x00 },
+	{ STB0899_PCKLENUL		, 0xbc },
+	{ STB0899_PCKLENLL		, 0xcc },
+	{ STB0899_RSPCKLEN		, 0xbd },
+	{ STB0899_TSSTATUS		, 0x90 },
+	{ STB0899_ERRCTRL1      	, 0xb6 },
+	{ STB0899_ERRCTRL2      	, 0x95 },
+	{ STB0899_ERRCTRL3      	, 0x8d },
+	{ STB0899_DMONMSK1		, 0x27 },
+	{ STB0899_DMONMSK0		, 0x03 },
+	{ STB0899_DEMAPVIT      	, 0x5c },
+	{ STB0899_PLPARM		, 0x19 },
+	{ STB0899_PDELCTRL      	, 0x48 },
+	{ STB0899_PDELCTRL2     	, 0x00 },
+	{ STB0899_BBHCTRL1      	, 0x00 },
+	{ STB0899_BBHCTRL2      	, 0x00 },
+	{ STB0899_HYSTTHRESH    	, 0x77 },
+	{ STB0899_MATCSTM		, 0x00 },
+	{ STB0899_MATCSTL		, 0x00 },
+	{ STB0899_UPLCSTM		, 0x00 },
+	{ STB0899_UPLCSTL		, 0x00 },
+	{ STB0899_DFLCSTM		, 0x00 },
+	{ STB0899_DFLCSTL		, 0x00 },
+	{ STB0899_SYNCCST		, 0x00 },
+	{ STB0899_SYNCDCSTM		, 0x00 },
+	{ STB0899_SYNCDCSTL		, 0x00 },
+	{ STB0899_ISI_ENTRY		, 0x00 },
+	{ STB0899_ISI_BIT_EN		, 0x00 },
+	{ STB0899_MATSTRM		, 0xf0 },
+	{ STB0899_MATSTRL		, 0x02 },
+	{ STB0899_UPLSTRM		, 0x45 },
+	{ STB0899_UPLSTRL		, 0x60 },
+	{ STB0899_DFLSTRM		, 0xe3 },
+	{ STB0899_DFLSTRL		, 0x00 },
+	{ STB0899_SYNCSTR		, 0x47 },
+	{ STB0899_SYNCDSTRM		, 0x05 },
+	{ STB0899_SYNCDSTRL		, 0x18 },
+	{ STB0899_CFGPDELSTATUS1	, 0x19 },
+	{ STB0899_CFGPDELSTATUS2	, 0x2b },
+	{ STB0899_BBFERRORM		, 0x00 },
+	{ STB0899_BBFERRORL		, 0x01 },
+	{ STB0899_UPKTERRORM		, 0x00 },
+	{ STB0899_UPKTERRORL		, 0x00 },
+	{ 0xffff			, 0xff },
+};
+
+struct stb0899_config vp1041_stb0899_config = {
+	.init_dev		= vp1041_stb0899_s1_init_1,
+	.init_s2_demod		= stb0899_s2_init_2,
+	.init_s1_demod		= vp1041_stb0899_s1_init_3,
+	.init_s2_fec		= stb0899_s2_init_4,
+	.init_tst		= stb0899_s1_init_5,
+
+	.demod_address 		= 0x68, /*  0xd0 >> 1 */
+
+	.xtal_freq		= 27000000,
+	.inversion		= IQ_SWAP_ON, /* 1 */
+
+	.lo_clk			= 76500000,
+	.hi_clk			= 99000000,
+
+	.esno_ave		= STB0899_DVBS2_ESNO_AVE,
+	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,
+	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,
+	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,
+	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,
+	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,
+	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,
+	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,
+	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,
+
+	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,
+	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,
+	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,
+
+	.tuner_get_frequency	= stb6100_get_frequency,
+	.tuner_set_frequency	= stb6100_set_frequency,
+	.tuner_set_bandwidth	= stb6100_set_bandwidth,
+	.tuner_get_bandwidth	= stb6100_get_bandwidth,
+	.tuner_set_rfsiggain	= NULL,
+};
+
+struct stb6100_config vp1041_stb6100_config = {
+	.tuner_address	= 0x60,
+	.refclock	= 27000000,
+};
+
+static int vp1041_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+		mantis->fe = stb0899_attach(&vp1041_stb0899_config, adapter);
+		if (mantis->fe) {
+			dprintk(MANTIS_ERROR, 1,
+				"found STB0899 DVB-S/DVB-S2 frontend @0x%02x",
+				vp1041_stb0899_config.demod_address);
+
+			if (stb6100_attach(mantis->fe, &vp1041_stb6100_config, adapter)) {
+				if (!lnbp21_attach(mantis->fe, adapter, 0, 0))
+					dprintk(MANTIS_ERROR, 1, "No LNBP21 found!");
+			}
+		} else {
+			return -EREMOTEIO;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+
+
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp1041_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_188,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp1041_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+};
diff --git a/drivers/media/dvb/mantis/mantis_vp1041.h b/drivers/media/dvb/mantis/mantis_vp1041.h
new file mode 100644
index 0000000..1ae5b3d
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp1041.h
@@ -0,0 +1,33 @@
+/*
+	Mantis VP-1041 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP1041_H
+#define __MANTIS_VP1041_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_1041_DVB_S2	0x0031
+#define SKYSTAR_HD2_10		0x0001
+#define SKYSTAR_HD2_20		0x0003
+#define CINERGY_S2_PCI_HD	0x1179
+
+extern struct mantis_hwconfig vp1041_config;
+
+#endif /* __MANTIS_VP1041_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp2033.c b/drivers/media/dvb/mantis/mantis_vp2033.c
new file mode 100644
index 0000000..10ce817
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp2033.c
@@ -0,0 +1,187 @@
+/*
+	Mantis VP-2033 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "tda1002x.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp2033.h"
+
+#define MANTIS_MODEL_NAME	"VP-2033"
+#define MANTIS_DEV_TYPE		"DVB-C"
+
+struct tda1002x_config vp2033_tda1002x_cu1216_config = {
+	.demod_address = 0x18 >> 1,
+	.invert = 1,
+};
+
+struct tda10023_config vp2033_tda10023_cu1216_config = {
+	.demod_address = 0x18 >> 1,
+	.invert = 1,
+};
+
+static u8 read_pwm(struct mantis_pci *mantis)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	u8 b = 0xff;
+	u8 pwm;
+	struct i2c_msg msg[] = {
+		{.addr = 0x50, .flags = 0, .buf = &b, .len = 1},
+		{.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1}
+	};
+
+	if ((i2c_transfer(adapter, msg, 2) != 2)
+	    || (pwm == 0xff))
+		pwm = 0x48;
+
+	return pwm;
+}
+
+static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct mantis_pci *mantis = fe->dvb->priv;
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	u8 buf[6];
+	struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)};
+	int i;
+
+#define CU1216_IF 36125000
+#define TUNER_MUL 62500
+
+	u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0xce;
+	buf[3] = (params->frequency < 150000000 ? 0x01 :
+		  params->frequency < 445000000 ? 0x02 : 0x04);
+	buf[4] = 0xde;
+	buf[5] = 0x20;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(adapter, &msg, 1) != 1)
+		return -EIO;
+
+	/* wait for the pll lock */
+	msg.flags = I2C_M_RD;
+	msg.len = 1;
+	for (i = 0; i < 20; i++) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40))
+			break;
+
+		msleep(10);
+	}
+
+	/* switch the charge pump to the lower current */
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = &buf[2];
+	buf[2] &= ~0x40;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(adapter, &msg, 1) != 1)
+		return -EIO;
+
+	return 0;
+}
+
+static int vp2033_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+
+		dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
+		fe = tda10021_attach(&vp2033_tda1002x_cu1216_config,
+				     adapter,
+				     read_pwm(mantis));
+
+		if (fe) {
+			dprintk(MANTIS_ERROR, 1,
+				"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
+				vp2033_tda1002x_cu1216_config.demod_address);
+		} else {
+			fe = tda10023_attach(&vp2033_tda10023_cu1216_config,
+					     adapter,
+					     read_pwm(mantis));
+
+			if (fe) {
+				dprintk(MANTIS_ERROR, 1,
+					"found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x",
+					vp2033_tda1002x_cu1216_config.demod_address);
+			}
+		}
+
+		if (fe) {
+			fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set;
+			dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success");
+		} else {
+			return -1;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+
+	mantis->fe = fe;
+	dprintk(MANTIS_DEBUG, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp2033_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_204,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp2033_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+};
diff --git a/drivers/media/dvb/mantis/mantis_vp2033.h b/drivers/media/dvb/mantis/mantis_vp2033.h
new file mode 100644
index 0000000..c55242b
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp2033.h
@@ -0,0 +1,30 @@
+/*
+	Mantis VP-2033 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP2033_H
+#define __MANTIS_VP2033_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_2033_DVB_C	0x0008
+
+extern struct mantis_hwconfig vp2033_config;
+
+#endif /* __MANTIS_VP2033_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp2040.c b/drivers/media/dvb/mantis/mantis_vp2040.c
new file mode 100644
index 0000000..a7ca233e8
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp2040.c
@@ -0,0 +1,186 @@
+/*
+	Mantis VP-2040 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "tda1002x.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp2040.h"
+
+#define MANTIS_MODEL_NAME	"VP-2040"
+#define MANTIS_DEV_TYPE		"DVB-C"
+
+struct tda1002x_config vp2040_tda1002x_cu1216_config = {
+	.demod_address	= 0x18 >> 1,
+	.invert		= 1,
+};
+
+struct tda10023_config vp2040_tda10023_cu1216_config = {
+	.demod_address	= 0x18 >> 1,
+	.invert		= 1,
+};
+
+static int tda1002x_cu1216_tuner_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct mantis_pci *mantis	= fe->dvb->priv;
+	struct i2c_adapter *adapter	= &mantis->adapter;
+
+	u8 buf[6];
+	struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf)};
+	int i;
+
+#define CU1216_IF 36125000
+#define TUNER_MUL 62500
+
+	u32 div = (params->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;
+
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0xce;
+	buf[3] = (params->frequency < 150000000 ? 0x01 :
+		  params->frequency < 445000000 ? 0x02 : 0x04);
+	buf[4] = 0xde;
+	buf[5] = 0x20;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(adapter, &msg, 1) != 1)
+		return -EIO;
+
+	/* wait for the pll lock */
+	msg.flags = I2C_M_RD;
+	msg.len = 1;
+	for (i = 0; i < 20; i++) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+
+		if (i2c_transfer(adapter, &msg, 1) == 1 && (buf[0] & 0x40))
+			break;
+
+		msleep(10);
+	}
+
+	/* switch the charge pump to the lower current */
+	msg.flags = 0;
+	msg.len = 2;
+	msg.buf = &buf[2];
+	buf[2] &= ~0x40;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	if (i2c_transfer(adapter, &msg, 1) != 1)
+		return -EIO;
+
+	return 0;
+}
+
+static u8 read_pwm(struct mantis_pci *mantis)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	u8 b = 0xff;
+	u8 pwm;
+	struct i2c_msg msg[] = {
+		{.addr = 0x50, .flags = 0, .buf = &b, .len = 1},
+		{.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1}
+	};
+
+	if ((i2c_transfer(adapter, msg, 2) != 2)
+	    || (pwm == 0xff))
+		pwm = 0x48;
+
+	return pwm;
+}
+
+static int vp2040_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter = &mantis->adapter;
+
+	int err = 0;
+
+	err = mantis_frontend_power(mantis, POWER_ON);
+	if (err == 0) {
+		mantis_frontend_soft_reset(mantis);
+		msleep(250);
+
+		dprintk(MANTIS_ERROR, 1, "Probing for CU1216 (DVB-C)");
+		fe = tda10021_attach(&vp2040_tda1002x_cu1216_config,
+				     adapter,
+				     read_pwm(mantis));
+
+		if (fe) {
+			dprintk(MANTIS_ERROR, 1,
+				"found Philips CU1216 DVB-C frontend (TDA10021) @ 0x%02x",
+				vp2040_tda1002x_cu1216_config.demod_address);
+		} else {
+			fe = tda10023_attach(&vp2040_tda10023_cu1216_config,
+					     adapter,
+					     read_pwm(mantis));
+
+			if (fe) {
+				dprintk(MANTIS_ERROR, 1,
+					"found Philips CU1216 DVB-C frontend (TDA10023) @ 0x%02x",
+					vp2040_tda1002x_cu1216_config.demod_address);
+			}
+		}
+
+		if (fe) {
+			fe->ops.tuner_ops.set_params = tda1002x_cu1216_tuner_set;
+			dprintk(MANTIS_ERROR, 1, "Mantis DVB-C Philips CU1216 frontend attach success");
+		} else {
+			return -1;
+		}
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+	}
+	mantis->fe = fe;
+	dprintk(MANTIS_DEBUG, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp2040_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_204,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp2040_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+};
diff --git a/drivers/media/dvb/mantis/mantis_vp2040.h b/drivers/media/dvb/mantis/mantis_vp2040.h
new file mode 100644
index 0000000..d125e21
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp2040.h
@@ -0,0 +1,32 @@
+/*
+	Mantis VP-2040 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP2040_H
+#define __MANTIS_VP2040_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_2040_DVB_C	0x0043
+#define CINERGY_C		0x1178
+#define CABLESTAR_HD2		0x0002
+
+extern struct mantis_hwconfig vp2040_config;
+
+#endif /* __MANTIS_VP2040_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp3028.c b/drivers/media/dvb/mantis/mantis_vp3028.c
new file mode 100644
index 0000000..4155c83
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp3028.c
@@ -0,0 +1,38 @@
+/*
+	Mantis VP-3028 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "mantis_common.h"
+#include "mantis_vp3028.h"
+
+struct zl10353_config mantis_vp3028_config = {
+	.demod_address	= 0x0f,
+};
+
+#define MANTIS_MODEL_NAME	"VP-3028"
+#define MANTIS_DEV_TYPE		"DVB-T"
+
+struct mantis_hwconfig vp3028_mantis_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_188,
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+};
diff --git a/drivers/media/dvb/mantis/mantis_vp3028.h b/drivers/media/dvb/mantis/mantis_vp3028.h
new file mode 100644
index 0000000..b07be6a
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp3028.h
@@ -0,0 +1,33 @@
+/*
+	Mantis VP-3028 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP3028_H
+#define __MANTIS_VP3028_H
+
+#include "dvb_frontend.h"
+#include "mantis_common.h"
+#include "zl10353.h"
+
+#define MANTIS_VP_3028_DVB_T	0x0028
+
+extern struct zl10353_config mantis_vp3028_config;
+extern struct mantis_hwconfig vp3028_mantis_config;
+
+#endif /* __MANTIS_VP3028_H */
diff --git a/drivers/media/dvb/mantis/mantis_vp3030.c b/drivers/media/dvb/mantis/mantis_vp3030.c
new file mode 100644
index 0000000..1f43342
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp3030.c
@@ -0,0 +1,105 @@
+/*
+	Mantis VP-3030 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+
+#include "zl10353.h"
+#include "tda665x.h"
+#include "mantis_common.h"
+#include "mantis_ioc.h"
+#include "mantis_dvb.h"
+#include "mantis_vp3030.h"
+
+struct zl10353_config mantis_vp3030_config = {
+	.demod_address		= 0x0f,
+};
+
+struct tda665x_config env57h12d5_config = {
+	.name			= "ENV57H12D5 (ET-50DT)",
+	.addr			= 0x60,
+	.frequency_min		=  47000000,
+	.frequency_max		= 862000000,
+	.frequency_offst	=   3616667,
+	.ref_multiplier		= 6, /* 1/6 MHz */
+	.ref_divider		= 100000, /* 1/6 MHz */
+};
+
+#define MANTIS_MODEL_NAME	"VP-3030"
+#define MANTIS_DEV_TYPE		"DVB-T"
+
+
+static int vp3030_frontend_init(struct mantis_pci *mantis, struct dvb_frontend *fe)
+{
+	struct i2c_adapter *adapter	= &mantis->adapter;
+	struct mantis_hwconfig *config	= mantis->hwconfig;
+	int err = 0;
+
+	gpio_set_bits(mantis, config->reset, 0);
+	msleep(100);
+	err = mantis_frontend_power(mantis, POWER_ON);
+	msleep(100);
+	gpio_set_bits(mantis, config->reset, 1);
+
+	if (err == 0) {
+		msleep(250);
+		dprintk(MANTIS_ERROR, 1, "Probing for 10353 (DVB-T)");
+		fe = zl10353_attach(&mantis_vp3030_config, adapter);
+
+		if (!fe)
+			return -1;
+
+		tda665x_attach(fe, &env57h12d5_config, adapter);
+	} else {
+		dprintk(MANTIS_ERROR, 1, "Frontend on <%s> POWER ON failed! <%d>",
+			adapter->name,
+			err);
+
+		return -EIO;
+
+	}
+	mantis->fe = fe;
+	dprintk(MANTIS_ERROR, 1, "Done!");
+
+	return 0;
+}
+
+struct mantis_hwconfig vp3030_config = {
+	.model_name	= MANTIS_MODEL_NAME,
+	.dev_type	= MANTIS_DEV_TYPE,
+	.ts_size	= MANTIS_TS_188,
+
+	.baud_rate	= MANTIS_BAUD_9600,
+	.parity		= MANTIS_PARITY_NONE,
+	.bytes		= 0,
+
+	.frontend_init	= vp3030_frontend_init,
+	.power		= GPIF_A12,
+	.reset		= GPIF_A13,
+
+	.i2c_mode	= MANTIS_BYTE_MODE
+};
diff --git a/drivers/media/dvb/mantis/mantis_vp3030.h b/drivers/media/dvb/mantis/mantis_vp3030.h
new file mode 100644
index 0000000..5f12c42
--- /dev/null
+++ b/drivers/media/dvb/mantis/mantis_vp3030.h
@@ -0,0 +1,30 @@
+/*
+	Mantis VP-3030 driver
+
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __MANTIS_VP3030_H
+#define __MANTIS_VP3030_H
+
+#include "mantis_common.h"
+
+#define MANTIS_VP_3030_DVB_T	0x0024
+
+extern struct mantis_hwconfig vp3030_config;
+
+#endif /* __MANTIS_VP3030_H */