diff -urNp linux-2.6.22.1/drivers/media/dvb/dvb-core/dvbdev.c linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvbdev.c
--- linux-2.6.22.1/drivers/media/dvb/dvb-core/dvbdev.c	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvbdev.c	2007-07-28 01:17:12.000000000 +0200
@@ -203,7 +203,8 @@ int dvb_register_device(struct dvb_adapt
 	struct class_device *clsdev;
 	int id;
 
-	mutex_lock(&dvbdev_register_lock);
+	if (mutex_lock_interruptible(&dvbdev_register_lock))
+		return -ERESTARTSYS;
 
 	if ((id = dvbdev_get_free_id (adap, type)) < 0){
 		mutex_unlock(&dvbdev_register_lock);
@@ -301,7 +302,8 @@ int dvb_register_adapter(struct dvb_adap
 {
 	int num;
 
-	mutex_lock(&dvbdev_register_lock);
+	if (mutex_lock_interruptible(&dvbdev_register_lock))
+		return -ERESTARTSYS;
 
 	if ((num = dvbdev_get_free_adapter_num ()) < 0) {
 		mutex_unlock(&dvbdev_register_lock);
@@ -329,7 +331,8 @@ EXPORT_SYMBOL(dvb_register_adapter);
 
 int dvb_unregister_adapter(struct dvb_adapter *adap)
 {
-	mutex_lock(&dvbdev_register_lock);
+	if (mutex_lock_interruptible(&dvbdev_register_lock))
+		return -ERESTARTSYS;
 	list_del (&adap->list_head);
 	mutex_unlock(&dvbdev_register_lock);
 	return 0;
diff -urNp linux-2.6.22.1/drivers/media/dvb/dvb-core/dvbdev.c.orig linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvbdev.c.orig
--- linux-2.6.22.1/drivers/media/dvb/dvb-core/dvbdev.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvbdev.c.orig	2007-07-10 20:56:30.000000000 +0200
@@ -0,0 +1,446 @@
+/*
+ * dvbdev.c
+ *
+ * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
+ *                  & Marcus Metzler <marcus@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include "dvbdev.h"
+
+static int dvbdev_debug;
+
+module_param(dvbdev_debug, int, 0644);
+MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
+
+#define dprintk if (dvbdev_debug) printk
+
+static LIST_HEAD(dvb_adapter_list);
+static DEFINE_MUTEX(dvbdev_register_lock);
+
+static const char * const dnames[] = {
+	"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
+	"net", "osd"
+};
+
+#define DVB_MAX_ADAPTERS	8
+#define DVB_MAX_IDS		4
+#define nums2minor(num,type,id)	((num << 6) | (id << 4) | type)
+#define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
+
+static struct class *dvb_class;
+
+static struct dvb_device* dvbdev_find_device (int minor)
+{
+	struct list_head *entry;
+
+	list_for_each (entry, &dvb_adapter_list) {
+		struct list_head *entry0;
+		struct dvb_adapter *adap;
+		adap = list_entry (entry, struct dvb_adapter, list_head);
+		list_for_each (entry0, &adap->device_list) {
+			struct dvb_device *dev;
+			dev = list_entry (entry0, struct dvb_device, list_head);
+			if (nums2minor(adap->num, dev->type, dev->id) == minor)
+				return dev;
+		}
+	}
+
+	return NULL;
+}
+
+
+static int dvb_device_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev;
+
+	dvbdev = dvbdev_find_device (iminor(inode));
+
+	if (dvbdev && dvbdev->fops) {
+		int err = 0;
+		const struct file_operations *old_fops;
+
+		file->private_data = dvbdev;
+		old_fops = file->f_op;
+		file->f_op = fops_get(dvbdev->fops);
+		if(file->f_op->open)
+			err = file->f_op->open(inode,file);
+		if (err) {
+			fops_put(file->f_op);
+			file->f_op = fops_get(old_fops);
+		}
+		fops_put(old_fops);
+		return err;
+	}
+	return -ENODEV;
+}
+
+
+static struct file_operations dvb_device_fops =
+{
+	.owner =	THIS_MODULE,
+	.open =		dvb_device_open,
+};
+
+static struct cdev dvb_device_cdev = {
+	.kobj   = {.name = "dvb", },
+	.owner  =       THIS_MODULE,
+};
+
+int dvb_generic_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+
+	if (!dvbdev)
+		return -ENODEV;
+
+	if (!dvbdev->users)
+		return -EBUSY;
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		if (!dvbdev->readers)
+			return -EBUSY;
+		dvbdev->readers--;
+	} else {
+		if (!dvbdev->writers)
+			return -EBUSY;
+		dvbdev->writers--;
+	}
+
+	dvbdev->users--;
+	return 0;
+}
+EXPORT_SYMBOL(dvb_generic_open);
+
+
+int dvb_generic_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+
+	if (!dvbdev)
+		return -ENODEV;
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		dvbdev->readers++;
+	} else {
+		dvbdev->writers++;
+	}
+
+	dvbdev->users++;
+	return 0;
+}
+EXPORT_SYMBOL(dvb_generic_release);
+
+
+int dvb_generic_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+
+	if (!dvbdev)
+		return -ENODEV;
+
+	if (!dvbdev->kernel_ioctl)
+		return -EINVAL;
+
+	return dvb_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl);
+}
+EXPORT_SYMBOL(dvb_generic_ioctl);
+
+
+static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
+{
+	u32 id = 0;
+
+	while (id < DVB_MAX_IDS) {
+		struct list_head *entry;
+		list_for_each (entry, &adap->device_list) {
+			struct dvb_device *dev;
+			dev = list_entry (entry, struct dvb_device, list_head);
+			if (dev->type == type && dev->id == id)
+				goto skip;
+		}
+		return id;
+skip:
+		id++;
+	}
+	return -ENFILE;
+}
+
+
+int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+			const struct dvb_device *template, void *priv, int type)
+{
+	struct dvb_device *dvbdev;
+	struct file_operations *dvbdevfops;
+	struct class_device *clsdev;
+	int id;
+
+	mutex_lock(&dvbdev_register_lock);
+
+	if ((id = dvbdev_get_free_id (adap, type)) < 0){
+		mutex_unlock(&dvbdev_register_lock);
+		*pdvbdev = NULL;
+		printk ("%s: could get find free device id...\n", __FUNCTION__);
+		return -ENFILE;
+	}
+
+	*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
+
+	if (!dvbdev){
+		mutex_unlock(&dvbdev_register_lock);
+		return -ENOMEM;
+	}
+
+	dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
+
+	if (!dvbdevfops){
+		kfree (dvbdev);
+		mutex_unlock(&dvbdev_register_lock);
+		return -ENOMEM;
+	}
+
+	memcpy(dvbdev, template, sizeof(struct dvb_device));
+	dvbdev->type = type;
+	dvbdev->id = id;
+	dvbdev->adapter = adap;
+	dvbdev->priv = priv;
+	dvbdev->fops = dvbdevfops;
+	init_waitqueue_head (&dvbdev->wait_queue);
+
+	memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations));
+	dvbdev->fops->owner = adap->module;
+
+	list_add_tail (&dvbdev->list_head, &adap->device_list);
+
+	mutex_unlock(&dvbdev_register_lock);
+
+	clsdev = class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR,
+				     nums2minor(adap->num, type, id)),
+				     adap->device, "dvb%d.%s%d", adap->num,
+				     dnames[type], id);
+	if (IS_ERR(clsdev)) {
+		printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
+		       __FUNCTION__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+		return PTR_ERR(clsdev);
+	}
+
+	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
+		adap->num, dnames[type], id, nums2minor(adap->num, type, id),
+		nums2minor(adap->num, type, id));
+
+	return 0;
+}
+EXPORT_SYMBOL(dvb_register_device);
+
+
+void dvb_unregister_device(struct dvb_device *dvbdev)
+{
+	if (!dvbdev)
+		return;
+
+	class_device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
+					dvbdev->type, dvbdev->id)));
+
+	list_del (&dvbdev->list_head);
+	kfree (dvbdev->fops);
+	kfree (dvbdev);
+}
+EXPORT_SYMBOL(dvb_unregister_device);
+
+
+static int dvbdev_get_free_adapter_num (void)
+{
+	int num = 0;
+
+	while (num < DVB_MAX_ADAPTERS) {
+		struct list_head *entry;
+		list_for_each (entry, &dvb_adapter_list) {
+			struct dvb_adapter *adap;
+			adap = list_entry (entry, struct dvb_adapter, list_head);
+			if (adap->num == num)
+				goto skip;
+		}
+		return num;
+skip:
+		num++;
+	}
+
+	return -ENFILE;
+}
+
+
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
+{
+	int num;
+
+	mutex_lock(&dvbdev_register_lock);
+
+	if ((num = dvbdev_get_free_adapter_num ()) < 0) {
+		mutex_unlock(&dvbdev_register_lock);
+		return -ENFILE;
+	}
+
+	memset (adap, 0, sizeof(struct dvb_adapter));
+	INIT_LIST_HEAD (&adap->device_list);
+
+	printk ("DVB: registering new adapter (%s).\n", name);
+
+	adap->num = num;
+	adap->name = name;
+	adap->module = module;
+	adap->device = device;
+
+	list_add_tail (&adap->list_head, &dvb_adapter_list);
+
+	mutex_unlock(&dvbdev_register_lock);
+
+	return num;
+}
+EXPORT_SYMBOL(dvb_register_adapter);
+
+
+int dvb_unregister_adapter(struct dvb_adapter *adap)
+{
+	mutex_lock(&dvbdev_register_lock);
+	list_del (&adap->list_head);
+	mutex_unlock(&dvbdev_register_lock);
+	return 0;
+}
+EXPORT_SYMBOL(dvb_unregister_adapter);
+
+/* if the miracle happens and "generic_usercopy()" is included into
+   the kernel, then this can vanish. please don't make the mistake and
+   define this as video_usercopy(). this will introduce a dependecy
+   to the v4l "videodev.o" module, which is unnecessary for some
+   cards (ie. the budget dvb-cards don't need the v4l module...) */
+int dvb_usercopy(struct inode *inode, struct file *file,
+		     unsigned int cmd, unsigned long arg,
+		     int (*func)(struct inode *inode, struct file *file,
+		     unsigned int cmd, void *arg))
+{
+	char    sbuf[128];
+	void    *mbuf = NULL;
+	void    *parg = NULL;
+	int     err  = -EINVAL;
+
+	/*  Copy arguments into temp kernel buffer  */
+	switch (_IOC_DIR(cmd)) {
+	case _IOC_NONE:
+		/*
+		 * For this command, the pointer is actually an integer
+		 * argument.
+		 */
+		parg = (void *) arg;
+		break;
+	case _IOC_READ: /* some v4l ioctls are marked wrong ... */
+	case _IOC_WRITE:
+	case (_IOC_WRITE | _IOC_READ):
+		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+			parg = sbuf;
+		} else {
+			/* too big to allocate from stack */
+			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
+			if (NULL == mbuf)
+				return -ENOMEM;
+			parg = mbuf;
+		}
+
+		err = -EFAULT;
+		if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+			goto out;
+		break;
+	}
+
+	/* call driver */
+	if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD)
+		err = -EINVAL;
+
+	if (err < 0)
+		goto out;
+
+	/*  Copy results into user buffer  */
+	switch (_IOC_DIR(cmd))
+	{
+	case _IOC_READ:
+	case (_IOC_WRITE | _IOC_READ):
+		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+			err = -EFAULT;
+		break;
+	}
+
+out:
+	kfree(mbuf);
+	return err;
+}
+
+static int __init init_dvbdev(void)
+{
+	int retval;
+	dev_t dev = MKDEV(DVB_MAJOR, 0);
+
+	if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
+		printk("dvb-core: unable to get major %d\n", DVB_MAJOR);
+		return retval;
+	}
+
+	cdev_init(&dvb_device_cdev, &dvb_device_fops);
+	if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
+		printk("dvb-core: unable to get major %d\n", DVB_MAJOR);
+		goto error;
+	}
+
+	dvb_class = class_create(THIS_MODULE, "dvb");
+	if (IS_ERR(dvb_class)) {
+		retval = PTR_ERR(dvb_class);
+		goto error;
+	}
+	return 0;
+
+error:
+	cdev_del(&dvb_device_cdev);
+	unregister_chrdev_region(dev, MAX_DVB_MINORS);
+	return retval;
+}
+
+
+static void __exit exit_dvbdev(void)
+{
+	class_destroy(dvb_class);
+	cdev_del(&dvb_device_cdev);
+	unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
+}
+
+subsys_initcall(init_dvbdev);
+module_exit(exit_dvbdev);
+
+MODULE_DESCRIPTION("DVB Core Driver");
+MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
+MODULE_LICENSE("GPL");
diff -urNp linux-2.6.22.1/drivers/media/dvb/dvb-core/dvb_frontend.c linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvb_frontend.c
--- linux-2.6.22.1/drivers/media/dvb/dvb-core/dvb_frontend.c	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvb_frontend.c	2007-07-28 01:17:12.000000000 +0200
@@ -9,6 +9,9 @@
  *
  * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
  *
+ * Multi protocol support and backward compatibility
+ * Copyright (C) 2007 Manu Abraham
+ *
  * 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
@@ -96,7 +99,12 @@ struct dvb_frontend_private {
 
 	/* thread/frontend values */
 	struct dvb_device *dvbdev;
+	/* Legacy datatype, superseded by dvbfe_params		*/
 	struct dvb_frontend_parameters parameters;
+	/* dvbfe_params supersedes dvb_frontend_parameters	*/
+	struct dvbfe_params	fe_params;
+	struct dvbfe_info	fe_info;
+
 	struct dvb_fe_events events;
 	struct semaphore sem;
 	struct list_head list_head;
@@ -125,10 +133,444 @@ struct dvb_frontend_private {
 	unsigned int step_size;
 	int quality;
 	unsigned int check_wrapped;
+
+	enum dvbfe_search	algo_status;
 };
 
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
 
+struct modcod_table {
+	u32 dvbfe_modcod;
+	u32 dvbfe_modulation;
+	u32 dvbfe_fec;
+};
+
+static struct modcod_table dvbs2_modcod_lookup[] = {
+	{ DVBFE_MODCOD_DUMMY_PLFRAME,	DVBFE_MOD_NONE,		DVBFE_FEC_NONE    },
+	{ DVBFE_MODCOD_QPSK_1_4,	DVBFE_MOD_QPSK,		DVBFE_FEC_1_4	  },
+	{ DVBFE_MODCOD_QPSK_1_3,	DVBFE_MOD_QPSK,		DVBFE_FEC_1_3	  },
+	{ DVBFE_MODCOD_QPSK_2_5,	DVBFE_MOD_QPSK,		DVBFE_FEC_2_5	  },
+	{ DVBFE_MODCOD_QPSK_1_2,	DVBFE_MOD_QPSK,		DVBFE_FEC_1_2	  },
+	{ DVBFE_MODCOD_QPSK_3_5,	DVBFE_MOD_QPSK,		DVBFE_FEC_3_5	  },
+	{ DVBFE_MODCOD_QPSK_2_3,	DVBFE_MOD_QPSK,		DVBFE_FEC_2_3	  },
+	{ DVBFE_MODCOD_QPSK_3_4,	DVBFE_MOD_QPSK,		DVBFE_FEC_3_4	  },
+	{ DVBFE_MODCOD_QPSK_4_5,	DVBFE_MOD_QPSK,		DVBFE_FEC_4_5	  },
+	{ DVBFE_MODCOD_QPSK_5_6,	DVBFE_MOD_QPSK,		DVBFE_FEC_5_6	  },
+	{ DVBFE_MODCOD_QPSK_8_9,	DVBFE_MOD_QPSK,		DVBFE_FEC_8_9	  },
+	{ DVBFE_MODCOD_QPSK_9_10,	DVBFE_MOD_QPSK,		DVBFE_FEC_9_10	  },
+	{ DVBFE_MODCOD_8PSK_3_5,	DVBFE_MOD_8PSK,		DVBFE_FEC_3_5	  },
+	{ DVBFE_MODCOD_8PSK_2_3,	DVBFE_MOD_8PSK,		DVBFE_FEC_2_3	  },
+	{ DVBFE_MODCOD_8PSK_3_4,	DVBFE_MOD_8PSK,		DVBFE_FEC_3_4	  },
+	{ DVBFE_MODCOD_8PSK_5_6,	DVBFE_MOD_8PSK,		DVBFE_FEC_5_6	  },
+	{ DVBFE_MODCOD_8PSK_8_9,	DVBFE_MOD_8PSK,		DVBFE_FEC_8_9	  },
+	{ DVBFE_MODCOD_8PSK_9_10,	DVBFE_MOD_8PSK,		DVBFE_FEC_9_10	  },
+	{ DVBFE_MODCOD_16APSK_2_3,	DVBFE_MOD_16APSK,	DVBFE_FEC_2_3	  },
+	{ DVBFE_MODCOD_16APSK_3_4,	DVBFE_MOD_16APSK,	DVBFE_FEC_3_4	  },
+	{ DVBFE_MODCOD_16APSK_4_5,	DVBFE_MOD_16APSK,	DVBFE_FEC_4_5	  },
+	{ DVBFE_MODCOD_16APSK_5_6,	DVBFE_MOD_16APSK,	DVBFE_FEC_5_6	  },
+	{ DVBFE_MODCOD_16APSK_8_9,	DVBFE_MOD_16APSK,	DVBFE_FEC_8_9	  },
+	{ DVBFE_MODCOD_16APSK_9_10,	DVBFE_MOD_16APSK,	DVBFE_FEC_9_10	  },
+	{ DVBFE_MODCOD_32APSK_3_4,	DVBFE_MOD_32APSK,	DVBFE_FEC_3_4	  },
+	{ DVBFE_MODCOD_32APSK_4_5,	DVBFE_MOD_32APSK,	DVBFE_FEC_4_5	  },
+	{ DVBFE_MODCOD_32APSK_5_6,	DVBFE_MOD_32APSK,	DVBFE_FEC_5_6	  },
+	{ DVBFE_MODCOD_32APSK_8_9,	DVBFE_MOD_32APSK,	DVBFE_FEC_8_9	  },
+	{ DVBFE_MODCOD_32APSK_9_10,	DVBFE_MOD_32APSK,	DVBFE_FEC_9_10	  },
+	{ DVBFE_MODCOD_RESERVED_1,	DVBFE_MOD_NONE,		DVBFE_FEC_NONE	  },
+	{ DVBFE_MODCOD_BPSK_1_3,	DVBFE_MOD_BPSK,		DVBFE_FEC_1_3	  },
+	{ DVBFE_MODCOD_BPSK_1_4,	DVBFE_MOD_BPSK,		DVBFE_FEC_1_4	  },
+	{ DVBFE_MODCOD_RESERVED_2,	DVBFE_MOD_NONE,		DVBFE_FEC_NONE    }
+};
+
+void decode_dvbs2_modcod(u32 dvbfe_modcod,
+			 enum dvbfe_modulation *modulation,
+			 enum dvbfe_fec *fec)
+{
+	BUG_ON(dvbfe_modcod >= ARRAY_SIZE(dvbs2_modcod_lookup));
+	*modulation = dvbs2_modcod_lookup[dvbfe_modcod].dvbfe_modulation;
+	*fec = dvbs2_modcod_lookup[dvbfe_modcod].dvbfe_fec;
+}
+EXPORT_SYMBOL(decode_dvbs2_modcod);
+
+static int newfec_to_oldfec(enum dvbfe_fec new_fec, enum fe_code_rate *old_fec)
+{
+	switch (new_fec) {
+	case DVBFE_FEC_NONE:
+		*old_fec = FEC_NONE;
+		break;
+	case DVBFE_FEC_1_2:
+		*old_fec = FEC_1_2;
+		break;
+	case DVBFE_FEC_2_3:
+		*old_fec = FEC_2_3;
+		break;
+	case DVBFE_FEC_3_4:
+		*old_fec = FEC_3_4;
+		break;
+	case DVBFE_FEC_4_5:
+		*old_fec = FEC_4_5;
+		break;
+	case DVBFE_FEC_5_6:
+		*old_fec = FEC_5_6;
+		break;
+	case DVBFE_FEC_6_7:
+		*old_fec = FEC_6_7;
+		break;
+	case DVBFE_FEC_7_8:
+		*old_fec = FEC_7_8;
+		break;
+	case DVBFE_FEC_8_9:
+		*old_fec = FEC_8_9;
+		break;
+	case DVBFE_FEC_AUTO:
+		*old_fec = FEC_AUTO;
+		break;
+	default:
+		printk("%s: Unsupported FEC\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int oldfec_to_newfec(enum fe_code_rate old_fec, enum dvbfe_fec *new_fec)
+{
+	switch (old_fec) {
+	case FEC_NONE:
+		*new_fec = DVBFE_FEC_NONE;
+		break;
+	case FEC_1_2:
+		*new_fec = DVBFE_FEC_1_2;
+		break;
+	case FEC_2_3:
+		*new_fec = DVBFE_FEC_2_3;
+		break;
+	case FEC_3_4:
+		*new_fec = DVBFE_FEC_3_4;
+		break;
+	case FEC_4_5:
+		*new_fec = DVBFE_FEC_4_5;
+		break;
+	case FEC_5_6:
+		*new_fec = DVBFE_FEC_5_6;
+		break;
+	case FEC_6_7:
+		*new_fec = DVBFE_FEC_6_7;
+		break;
+	case FEC_7_8:
+		*new_fec = DVBFE_FEC_7_8;
+		break;
+	case FEC_8_9:
+		*new_fec = DVBFE_FEC_8_9;
+		break;
+	case FEC_AUTO:
+		*new_fec = DVBFE_FEC_AUTO;
+		break;
+	default:
+		printk("%s: Unsupported FEC\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int newmod_to_oldmod(enum dvbfe_modulation new_mod, enum fe_modulation *old_mod)
+{
+	switch (new_mod) {
+	case DVBFE_MOD_QPSK:
+		*old_mod = QPSK;
+		break;
+	case DVBFE_MOD_QAM16:
+		*old_mod = QAM_16;
+		break;
+	case DVBFE_MOD_QAM32:
+		*old_mod = QAM_32;
+		break;
+	case DVBFE_MOD_QAM64:
+		*old_mod = QAM_64;
+		break;
+	case DVBFE_MOD_QAM128:
+		*old_mod = QAM_128;
+		break;
+	case DVBFE_MOD_QAM256:
+		*old_mod = QAM_256;
+		break;
+	case DVBFE_MOD_QAMAUTO:
+		*old_mod = QAM_AUTO;
+		break;
+	case DVBFE_MOD_VSB8:
+		*old_mod = VSB_8;
+		break;
+	case DVBFE_MOD_VSB16:
+		*old_mod = VSB_16;
+		break;
+	default:
+		printk("%s: Unsupported Modulation\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int oldmod_to_newmod(enum fe_modulation old_mod, enum dvbfe_modulation *new_mod)
+{
+	switch (old_mod) {
+	case QPSK:
+		*new_mod = DVBFE_MOD_QPSK;
+		break;
+	case QAM_16:
+		*new_mod = DVBFE_MOD_QAM16;
+		break;
+	case QAM_32:
+		*new_mod = DVBFE_MOD_QAM32;
+		break;
+	case QAM_64:
+		*new_mod = DVBFE_MOD_QAM64;
+		break;
+	case QAM_128:
+		*new_mod = DVBFE_MOD_QAM128;
+		break;
+	case QAM_256:
+		*new_mod = DVBFE_MOD_QAM256;
+		break;
+	case QAM_AUTO:
+		*new_mod = DVBFE_MOD_AUTO;
+		break;
+	case VSB_8:
+		*new_mod = DVBFE_MOD_VSB8;
+		break;
+	case VSB_16:
+		*new_mod = DVBFE_MOD_VSB16;
+		break;
+	default:
+		printk("%s: Unsupported Modulation\n", __func__);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int newapi_to_olddrv(struct dvbfe_params *params,
+		     struct dvb_frontend_parameters *p,
+		     enum dvbfe_delsys delsys)
+{
+	struct dvb_qpsk_parameters	*qpsk	= &p->u.qpsk;
+	struct dvb_qam_parameters	*qam	= &p->u.qam;
+	struct dvb_ofdm_parameters	*ofdm	= &p->u.ofdm;
+	struct dvb_vsb_parameters	*vsb	= &p->u.vsb;
+
+	struct dvbs_params		*dvbs	= &params->delsys.dvbs;
+	struct dvbc_params		*dvbc	= &params->delsys.dvbc;
+	struct dvbt_params		*dvbt	= &params->delsys.dvbt;
+	struct atsc_params		*atsc	= &params->delsys.atsc;
+
+	p->frequency = params->frequency;
+	p->inversion = params->inversion;
+
+	switch (delsys) {
+	case DVBFE_DELSYS_DVBS:
+		qpsk->symbol_rate		= dvbs->symbol_rate;
+		newfec_to_oldfec(dvbs->fec, &qpsk->fec_inner);
+		break;
+	case DVBFE_DELSYS_DVBC:
+		qam->symbol_rate		= dvbc->symbol_rate;
+		newmod_to_oldmod(dvbc->modulation, &qam->modulation);
+		newfec_to_oldfec(dvbc->fec, &qam->fec_inner);
+		break;
+	case DVBFE_DELSYS_DVBT:
+		switch (dvbt->bandwidth) {
+		case DVBFE_BANDWIDTH_8_MHZ:
+			ofdm->bandwidth		= BANDWIDTH_8_MHZ;
+			break;
+		case DVBFE_BANDWIDTH_7_MHZ:
+			ofdm->bandwidth		= BANDWIDTH_7_MHZ;
+			break;
+		case DVBFE_BANDWIDTH_6_MHZ:
+			ofdm->bandwidth		= BANDWIDTH_6_MHZ;
+			break;
+		case DVBFE_BANDWIDTH_AUTO:
+			ofdm->bandwidth		= BANDWIDTH_AUTO;
+			break;
+		default:
+			dprintk("%s: Unsupported bandwidth\n", __func__);
+			return -EINVAL;
+		}
+		newfec_to_oldfec(dvbt->code_rate_HP, &ofdm->code_rate_HP);
+		newfec_to_oldfec(dvbt->code_rate_LP, &ofdm->code_rate_LP);
+		newmod_to_oldmod(dvbt->constellation, &ofdm->constellation);
+		switch (dvbt->transmission_mode) {
+		case DVBFE_TRANSMISSION_MODE_2K:
+			ofdm->transmission_mode = TRANSMISSION_MODE_2K;
+			break;
+		case DVBFE_TRANSMISSION_MODE_8K:
+			ofdm->transmission_mode = TRANSMISSION_MODE_8K;
+			break;
+		case DVBFE_TRANSMISSION_MODE_AUTO:
+			ofdm->transmission_mode = TRANSMISSION_MODE_AUTO;
+			break;
+		default:
+			dprintk("%s: Unsupported transmission mode\n", __func__);
+			return -EINVAL;
+		}
+		switch (dvbt->guard_interval) {
+		case DVBFE_GUARD_INTERVAL_1_32:
+			ofdm->guard_interval	= GUARD_INTERVAL_1_32;
+			break;
+		case DVBFE_GUARD_INTERVAL_1_16:
+			ofdm->guard_interval	= GUARD_INTERVAL_1_16;
+			break;
+		case DVBFE_GUARD_INTERVAL_1_8:
+			ofdm->guard_interval	= GUARD_INTERVAL_1_8;
+			break;
+		case DVBFE_GUARD_INTERVAL_1_4:
+			ofdm->guard_interval	= GUARD_INTERVAL_1_4;
+			break;
+		case DVBFE_GUARD_INTERVAL_AUTO:
+			ofdm->guard_interval	= GUARD_INTERVAL_AUTO;
+			break;
+		}
+		switch (dvbt->hierarchy) {
+		case DVBFE_HIERARCHY_OFF:
+			ofdm->hierarchy_information		= HIERARCHY_NONE;
+			break;
+		case DVBFE_HIERARCHY_AUTO:
+			ofdm->hierarchy_information		= HIERARCHY_AUTO;
+			break;
+		case DVBFE_HIERARCHY_ON:
+			switch (dvbt->alpha) {
+			case DVBFE_ALPHA_1:
+				ofdm->hierarchy_information	= HIERARCHY_1;
+				break;
+			case DVBFE_ALPHA_2:
+				ofdm->hierarchy_information	= HIERARCHY_2;
+				break;
+			case DVBFE_ALPHA_4:
+				ofdm->hierarchy_information	= HIERARCHY_4;
+				break;
+			}
+			break;
+		}
+	case DVBFE_DELSYS_ATSC:
+		newmod_to_oldmod(atsc->modulation, &vsb->modulation);
+		break;
+	case DVBFE_DELSYS_DVBS2:
+	case DVBFE_DELSYS_DSS:
+	case DVBFE_DELSYS_DVBH:
+/*		printk("%s: SORRY ! Backward compatibility unavailable for these delivery systems !!\n", __func__);
+*/		break;
+	default:
+		dprintk("%s: Unsupported delivery system\n", __func__);
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+int olddrv_to_newapi(struct dvb_frontend *fe,
+		     struct dvbfe_params *params,
+		     struct dvb_frontend_parameters *p,
+		     enum fe_type fe_type)
+{
+	struct dvb_qpsk_parameters	*qpsk	= &p->u.qpsk;
+	struct dvb_qam_parameters	*qam	= &p->u.qam;
+	struct dvb_ofdm_parameters	*ofdm	= &p->u.ofdm;
+	struct dvb_vsb_parameters	*vsb	= &p->u.vsb;
+
+	struct dvbs_params		*dvbs	= &params->delsys.dvbs;
+	struct dvbc_params		*dvbc	= &params->delsys.dvbc;
+	struct dvbt_params		*dvbt	= &params->delsys.dvbt;
+	struct atsc_params		*atsc	= &params->delsys.atsc;
+
+	params->frequency = p->frequency;
+	params->inversion = p->inversion;
+
+	switch (fe_type) {
+	case FE_QPSK:
+		dvbs->symbol_rate		= qpsk->symbol_rate;
+		oldfec_to_newfec(qpsk->fec_inner, &dvbs->fec);
+		break;
+	case FE_QAM:
+		dvbc->symbol_rate		= qam->symbol_rate;
+		oldmod_to_newmod(qam->modulation, &dvbc->modulation);
+		oldfec_to_newfec(qam->fec_inner, &dvbc->fec);
+		break;
+	case FE_OFDM:
+		switch (ofdm->bandwidth) {
+		case BANDWIDTH_8_MHZ:
+			dvbt->bandwidth		= DVBFE_BANDWIDTH_8_MHZ;
+			break;
+		case BANDWIDTH_7_MHZ:
+			dvbt->bandwidth		= DVBFE_BANDWIDTH_7_MHZ;
+			break;
+		case BANDWIDTH_6_MHZ:
+			dvbt->bandwidth		= DVBFE_BANDWIDTH_6_MHZ;
+			break;
+		case BANDWIDTH_AUTO:
+			dvbt->bandwidth		= DVBFE_BANDWIDTH_AUTO;
+			break;
+		}
+		oldfec_to_newfec(ofdm->code_rate_HP, &dvbt->code_rate_HP);
+		oldfec_to_newfec(ofdm->code_rate_LP, &dvbt->code_rate_LP);
+		oldmod_to_newmod(ofdm->constellation, &dvbt->constellation);
+		switch (ofdm->transmission_mode) {
+		case TRANSMISSION_MODE_2K:
+			dvbt->transmission_mode	= DVBFE_TRANSMISSION_MODE_2K;
+			break;
+		case TRANSMISSION_MODE_8K:
+			dvbt->transmission_mode = DVBFE_TRANSMISSION_MODE_8K;
+			break;
+		case TRANSMISSION_MODE_AUTO:
+			dvbt->transmission_mode	= DVBFE_TRANSMISSION_MODE_AUTO;
+			break;
+		}
+		switch (ofdm->guard_interval) {
+		case GUARD_INTERVAL_1_32:
+			dvbt->guard_interval	= DVBFE_GUARD_INTERVAL_1_32;
+			break;
+		case GUARD_INTERVAL_1_16:
+			dvbt->guard_interval	= DVBFE_GUARD_INTERVAL_1_16;
+			break;
+		case GUARD_INTERVAL_1_8:
+			dvbt->guard_interval	= DVBFE_GUARD_INTERVAL_1_8;
+			break;
+		case GUARD_INTERVAL_1_4:
+			dvbt->guard_interval	= DVBFE_GUARD_INTERVAL_1_4;
+			break;
+		case GUARD_INTERVAL_AUTO:
+			dvbt->guard_interval	= DVBFE_GUARD_INTERVAL_AUTO;
+			break;
+		}
+		switch (ofdm->hierarchy_information) {
+		case HIERARCHY_NONE:
+			dvbt->hierarchy		= DVBFE_HIERARCHY_OFF;
+			break;
+		case HIERARCHY_AUTO:
+			dvbt->hierarchy		= DVBFE_HIERARCHY_AUTO;
+			break;
+		case HIERARCHY_1:
+			dvbt->hierarchy		= DVBFE_HIERARCHY_ON;
+			dvbt->alpha		= DVBFE_ALPHA_1;
+			break;
+		case HIERARCHY_2:
+			dvbt->hierarchy		= DVBFE_HIERARCHY_ON;
+			dvbt->alpha		= DVBFE_ALPHA_2;
+			break;
+		case HIERARCHY_4:
+			dvbt->hierarchy		= DVBFE_HIERARCHY_ON;
+			dvbt->alpha		= DVBFE_ALPHA_4;
+			break;
+		}
+		break;
+	case FE_ATSC:
+		newmod_to_oldmod(atsc->modulation, &vsb->modulation);
+		break;
+	default:
+		dprintk("%s: Unsupported delivery system\n", __func__);
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
 static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
 {
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -150,12 +592,21 @@ static void dvb_frontend_add_event(struc
 
 	e = &events->events[events->eventw];
 
-	memcpy (&e->parameters, &fepriv->parameters,
-		sizeof (struct dvb_frontend_parameters));
+	if (fe->legacy)
+		memcpy(&e->parameters, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
+	else
+		memcpy(&e->fe_params, &fepriv->fe_params, sizeof (struct dvbfe_params));
 
-	if (status & FE_HAS_LOCK)
-		if (fe->ops.get_frontend)
-			fe->ops.get_frontend(fe, &e->parameters);
+	if (fe->legacy) {
+		/* Legacy	*/
+		if (status & FE_HAS_LOCK)
+			if (fe->ops.get_frontend)
+				fe->ops.get_frontend(fe, &e->parameters);
+	} else {
+		if (status & FE_HAS_LOCK)
+			if (fe->ops.get_params)
+				fe->ops.get_params(fe, &e->fe_params);
+	}
 
 	events->eventw = wp;
 
@@ -166,6 +617,73 @@ static void dvb_frontend_add_event(struc
 	wake_up_interruptible (&events->wait_queue);
 }
 
+static int dvbfe_sanity_check(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	/* Sanity checks	*/
+	if ((fepriv->fe_params.frequency < fepriv->fe_info.frequency_min) ||
+	    (fepriv->fe_params.frequency > fepriv->fe_info.frequency_max))
+		return -EINVAL;
+
+	switch (fepriv->fe_params.delivery) {
+	case DVBFE_DELSYS_DVBS:
+		if (!(fepriv->fe_params.delsys.dvbs.modulation &
+		      fepriv->fe_info.delsys.dvbs.modulation))
+			return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dvbs.fec &
+		      fepriv->fe_info.delsys.dvbs.fec))
+			return -EINVAL;
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		if (!(fepriv->fe_params.delsys.dvbs2.modulation &
+		      fepriv->fe_info.delsys.dvbs2.modulation))
+			return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dvbs2.fec &
+		      fepriv->fe_info.delsys.dvbs2.fec))
+			return -EINVAL;
+		break;
+	case DVBFE_DELSYS_DSS:
+		if (!(fepriv->fe_params.delsys.dss.modulation &
+		      fepriv->fe_info.delsys.dss.modulation))
+			return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dss.fec &
+		      fepriv->fe_info.delsys.dss.fec))
+			return -EINVAL;
+		break;
+	case DVBFE_DELSYS_DVBC:
+		if (!(fepriv->fe_params.delsys.dvbc.modulation &
+		      fepriv->fe_info.delsys.dvbc.modulation))
+			return -EINVAL;
+		break;
+	case DVBFE_DELSYS_DVBT:
+		if (!(fepriv->fe_params.delsys.dvbt.constellation &
+		      fepriv->fe_info.delsys.dvbt.modulation))
+		      return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dvbt.priority &
+		      fepriv->fe_info.delsys.dvbt.stream_priority))
+		      return -EINVAL;
+		break;
+	case DVBFE_DELSYS_DVBH:
+		if (!(fepriv->fe_params.delsys.dvbh.constellation &
+		      fepriv->fe_info.delsys.dvbh.modulation))
+		      return -EINVAL;
+		if (!(fepriv->fe_params.delsys.dvbh.priority &
+		      fepriv->fe_info.delsys.dvbh.stream_priority))
+		      return -EINVAL;
+		break;
+	case DVBFE_DELSYS_ATSC:
+		if (!(fepriv->fe_params.delsys.atsc.modulation &
+		      fepriv->fe_info.delsys.atsc.modulation))
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int dvb_frontend_get_event(struct dvb_frontend *fe,
 			    struct dvb_frontend_event *event, int flags)
 {
@@ -262,13 +780,29 @@ static int dvb_frontend_swzigzag_autotun
 {
 	int autoinversion;
 	int ready = 0;
+	int original_inversion;
+	u32 original_frequency;
+
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
-	int original_inversion = fepriv->parameters.inversion;
-	u32 original_frequency = fepriv->parameters.frequency;
 
-	/* are we using autoinversion? */
-	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-			 (fepriv->parameters.inversion == INVERSION_AUTO));
+	if (fe->legacy) {
+		/* Legacy	*/
+		original_inversion = fepriv->parameters.inversion;
+		original_frequency = fepriv->parameters.frequency;
+		/* are we using autoinversion ?	*/
+		/* Legacy	*/
+		autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+				 (fepriv->parameters.inversion == INVERSION_AUTO));
+	} else {
+		/* Superseding	*/
+		original_inversion = fepriv->fe_params.inversion;
+		original_frequency = fepriv->fe_params.frequency;
+		if (fe->ops.get_info) {
+			fe->ops.get_info(fe, &fepriv->fe_info);
+		}
+		autoinversion = ((!(fepriv->fe_info.inversion & INVERSION_AUTO)) &&
+				 (fepriv->fe_params.inversion == INVERSION_AUTO));
+	}
 
 	/* setup parameters correctly */
 	while(!ready) {
@@ -330,24 +864,53 @@ static int dvb_frontend_swzigzag_autotun
 
 	dprintk("%s: drift:%i inversion:%i auto_step:%i "
 		"auto_sub_step:%i started_auto_step:%i\n",
-		__FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
-		fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
-
-	/* set the frontend itself */
-	fepriv->parameters.frequency += fepriv->lnb_drift;
-	if (autoinversion)
-		fepriv->parameters.inversion = fepriv->inversion;
-	if (fe->ops.set_frontend)
-		fe->ops.set_frontend(fe, &fepriv->parameters);
+		__func__, fepriv->lnb_drift, fepriv->inversion,
+		fepriv->auto_step, fepriv->auto_sub_step,
+		fepriv->started_auto_step);
+
+	/* set the frontend itself	*/
+	/* Legacy	*/
+	if (fe->legacy)
+		fepriv->parameters.frequency += fepriv->lnb_drift;
+	else
+		/* Supeseding	*/
+		fepriv->fe_params.frequency += fepriv->lnb_drift;
 
-	fepriv->parameters.frequency = original_frequency;
-	fepriv->parameters.inversion = original_inversion;
+	if (autoinversion) {
+		/* Legacy	*/
+		if (fe->legacy)
+			fepriv->parameters.inversion = fepriv->inversion;
+		else
+			/* Superseding	*/
+			fepriv->fe_params.inversion = fepriv->inversion;
+	}
+	/* Legacy	*/
+	if (fe->legacy) {
+		if (fe->ops.set_frontend)
+			fe->ops.set_frontend(fe, &fepriv->parameters);
+	} else {
+//		if ((dvbfe_sanity_check(fe) == 0)) {
+			/* Superseding	*/
+			if (fe->ops.set_params)
+				fe->ops.set_params(fe, &fepriv->fe_params);
+//		} else
+//			return -EINVAL;
+	}
+	/* Legacy	*/
+	if (fe->legacy) {
+		fepriv->parameters.frequency = original_frequency;
+		fepriv->parameters.inversion = original_inversion;
+	} else {
+		/* Superseding	*/
+		fepriv->fe_params.frequency = original_frequency;
+		fepriv->fe_params.inversion = original_inversion;
+	}
 
 	fepriv->auto_sub_step++;
 	return 0;
 }
 
-static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
+static int dvb_frontend_swzigzag(struct dvb_frontend *fe)
 {
 	fe_status_t s = 0;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
@@ -356,19 +919,30 @@ static void dvb_frontend_swzigzag(struct
 	if (fepriv->state & FESTATE_IDLE) {
 		fepriv->delay = 3*HZ;
 		fepriv->quality = 0;
-		return;
+		return 0;
 	}
 
 	/* in SCAN mode, we just set the frontend when asked and leave it alone */
 	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
 		if (fepriv->state & FESTATE_RETUNE) {
-			if (fe->ops.set_frontend)
-				fe->ops.set_frontend(fe, &fepriv->parameters);
+
+			if (fe->legacy) {
+				/* Legacy	*/
+				if (fe->ops.set_frontend)
+					fe->ops.set_frontend(fe, &fepriv->parameters);
+			} else {
+				if (dvbfe_sanity_check(fe) == 0) {
+					/* Superseding	*/
+					if (fe->ops.set_params)
+						fe->ops.set_params(fe, &fepriv->fe_params);
+				} else
+					return -EINVAL;
+			}
 			fepriv->state = FESTATE_TUNED;
 		}
 		fepriv->delay = 3*HZ;
 		fepriv->quality = 0;
-		return;
+		return 0;
 	}
 
 	/* get the frontend status */
@@ -389,11 +963,22 @@ static void dvb_frontend_swzigzag(struct
 		fepriv->state = FESTATE_TUNED;
 
 		/* if we're tuned, then we have determined the correct inversion */
-		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
-		    (fepriv->parameters.inversion == INVERSION_AUTO)) {
-			fepriv->parameters.inversion = fepriv->inversion;
+		/* Legacy	*/
+		if (fe->legacy) {
+			if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+			    (fepriv->parameters.inversion == INVERSION_AUTO)) {
+				fepriv->parameters.inversion = fepriv->inversion;
+			}
+		} else {
+			/* Superseding	*/
+			if (fe->ops.get_info) {
+				fe->ops.get_info(fe, &fepriv->fe_info);
+				if ((!(fepriv->fe_info.inversion & INVERSION_AUTO)) &&
+				    (fepriv->fe_params.inversion == INVERSION_AUTO))
+					fepriv->fe_params.inversion = fepriv->inversion;
+			}
 		}
-		return;
+		return 0;
 	}
 
 	/* if we are tuned already, check we're still locked */
@@ -402,7 +987,7 @@ static void dvb_frontend_swzigzag(struct
 
 		/* we're tuned, and the lock is still good... */
 		if (s & FE_HAS_LOCK) {
-			return;
+			return 0;
 		} else { /* if we _WERE_ tuned, but now don't have a lock */
 			fepriv->state = FESTATE_ZIGZAG_FAST;
 			fepriv->started_auto_step = fepriv->auto_step;
@@ -411,24 +996,43 @@ static void dvb_frontend_swzigzag(struct
 	}
 
 	/* don't actually do anything if we're in the LOSTLOCK state,
-	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
-	if ((fepriv->state & FESTATE_LOSTLOCK) &&
-	    (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
-		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-		return;
+	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0
+	 */
+	/* Legacy	*/
+	if (fe->legacy) {
+		if ((fepriv->state & FESTATE_LOSTLOCK) && (fepriv->max_drift == 0)) {
+			if (fe->ops.get_frontend_algo)
+				if (fe->ops.get_frontend_algo(fe) == DVBFE_ALGO_RECOVERY)
+					dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+			return 0;
+		}
+	} else {
+		if (fepriv->state & FESTATE_LOSTLOCK) {
+			if (fe->ops.get_frontend_algo) {
+				if ((fe->ops.get_frontend_algo(fe) == DVBFE_ALGO_RECOVERY) &&
+				    (fepriv->max_drift == 0)) {
+
+					dvb_frontend_swzigzag_update_delay(fepriv, s & DVBFE_HAS_LOCK);
+					return 0;
+				}
+			}
+		}
 	}
 
 	/* don't do anything if we're in the DISEQC state, since this
 	 * might be someone with a motorized dish controlled by DISEQC.
-	 * If its actually a re-tune, there will be a SET_FRONTEND soon enough.	*/
+	 * If its actually a re-tune, there will be a SET_FRONTEND soon enough.
+	 */
 	if (fepriv->state & FESTATE_DISEQC) {
 		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
-		return;
+		return 0;
 	}
 
 	/* if we're in the RETUNE state, set everything up for a brand
 	 * new scan, keeping the current inversion setting, as the next
-	 * tune is _very_ likely to require the same */
+	 * tune is _very_ likely to require the same
+	 */
 	if (fepriv->state & FESTATE_RETUNE) {
 		fepriv->lnb_drift = 0;
 		fepriv->auto_step = 0;
@@ -444,17 +1048,19 @@ static void dvb_frontend_swzigzag(struct
 		/* peform a tune */
 		if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) {
 			/* OK, if we've run out of trials at the fast speed.
-			 * Drop back to slow for the _next_ attempt */
+			 * Drop back to slow for the _next_ attempt
+			 */
 			fepriv->state = FESTATE_SEARCHING_SLOW;
 			fepriv->started_auto_step = fepriv->auto_step;
-			return;
+			return 0;
 		}
 		fepriv->check_wrapped = 1;
 
 		/* if we've just retuned, enter the ZIGZAG_FAST state.
 		 * This ensures we cannot return from an
 		 * FE_SET_FRONTEND ioctl before the first frontend tune
-		 * occurs */
+		 * occurs
+		 */
 		if (fepriv->state & FESTATE_RETUNE) {
 			fepriv->state = FESTATE_TUNING_FAST;
 		}
@@ -465,9 +1071,12 @@ static void dvb_frontend_swzigzag(struct
 		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
 
 		/* Note: don't bother checking for wrapping; we stay in this
-		 * state until we get a lock */
+		 * state until we get a lock
+		 */
 		dvb_frontend_swzigzag_autotune(fe, 0);
 	}
+
+	return 0;
 }
 
 static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
@@ -510,7 +1119,13 @@ static int dvb_frontend_thread(void *dat
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	unsigned long timeout;
 	fe_status_t s;
+
+	enum dvbfe_algo algo;
+
+	/* Legacy datatype	*/
 	struct dvb_frontend_parameters *params;
+	/* Superseding datatype	*/
+	struct dvbfe_params *fe_params = &fepriv->fe_params;
 
 	dprintk("%s\n", __FUNCTION__);
 
@@ -554,23 +1169,78 @@ restart:
 
 		/* do an iteration of the tuning loop */
 		if (fe->ops.get_frontend_algo) {
-			if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
-				/* have we been asked to retune? */
-				params = NULL;
+			algo = fe->ops.get_frontend_algo(fe);
+			switch (algo) {
+			case DVBFE_ALGO_HW:
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
+				params = NULL; /* have we been asked to RETUNE ?	*/
+
 				if (fepriv->state & FESTATE_RETUNE) {
+					dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
 					params = &fepriv->parameters;
 					fepriv->state = FESTATE_TUNED;
 				}
-
-				fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+				if (fe->ops.tune) {
+					fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+					dprintk("%s: TUNE callback exists at 0x%p\n", __func__, fe->ops.tune);
+				}
 				if (s != fepriv->status) {
+					dprintk("%s: state changed, adding current state\n", __func__);
 					dvb_frontend_add_event(fe, s);
 					fepriv->status = s;
 				}
-			} else
+				break;
+			case DVBFE_ALGO_SW:
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
 				dvb_frontend_swzigzag(fe);
-		} else
+				break;
+			case DVBFE_ALGO_CUSTOM:
+				params = NULL; /* have we been asked to RETUNE ?	*/
+				dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
+				if (fepriv->state & FESTATE_RETUNE) {
+					dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
+					fe_params = &fepriv->fe_params;
+					fepriv->state = FESTATE_TUNED;
+				}
+				/* Case where we are going to search for a carrier
+				 *
+				 * User asked us to retune again for some reason, possibly
+				 * requesting a search with a new set of parameters
+				 */
+				if (fepriv->algo_status & DVBFE_ALGO_SEARCH_AGAIN) {
+					if (fe->ops.search) {
+						fepriv->algo_status = fe->ops.search(fe, fe_params);
+						dprintk("%s: SEARCH callback exists at 0x%p\n", __func__, fe->ops.search);
+						/* We did do a search as was requested, the flags are
+						 * now unset as well and has the flags wrt to search.
+						 */
+					}
+					fepriv->algo_status &= ~DVBFE_ALGO_SEARCH_AGAIN;
+				}
+				/* Track the carrier if the search was successful	*/
+				if (fepriv->algo_status == DVBFE_ALGO_SEARCH_SUCCESS) {
+					if (fepriv->algo_status & DVBFE_ALGO_SEARCH_SUCCESS)
+						dprintk("%s: status = DVBFE_ALGO_SEARCH_SUCCESS\n", __func__);
+					if (fepriv->algo_status & DVBFE_ALGO_SEARCH_FAILED)
+						fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
+					fe->ops.read_status(fe, &s);
+					dvb_frontend_add_event(fe, s); /* update event list	*/
+					fepriv->status = s;
+					if (fe->ops.track) {
+						dprintk("%s: TRACK callback exists at 0x%p\n", __func__, fe->ops.track);
+						fe->ops.track(fe, fe_params);
+					}
+				}
+				break;
+			default:
+				dprintk("%s: UNDEFINED ALGO !\n", __func__);
+				break;
+			}
+
+		} else {
 			dvb_frontend_swzigzag(fe);
+		}
 	}
 
 	if (dvb_shutdown_timeout) {
@@ -589,6 +1259,7 @@ restart:
 	fepriv->thread = NULL;
 	mb();
 
+	dprintk("%s: frontend_wakeup\n", __func__);
 	dvb_frontend_wakeup(fe);
 	return 0;
 }
@@ -703,6 +1374,7 @@ static int dvb_frontend_ioctl(struct ino
 	struct dvb_frontend *fe = dvbdev->priv;
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 	int err = -EOPNOTSUPP;
+	enum dvbfe_delsys delsys = 0;
 
 	dprintk ("%s\n", __FUNCTION__);
 
@@ -882,12 +1554,24 @@ static int dvb_frontend_ioctl(struct ino
 	case FE_SET_FRONTEND: {
 		struct dvb_frontend_tune_settings fetunesettings;
 
-		memcpy (&fepriv->parameters, parg,
-			sizeof (struct dvb_frontend_parameters));
+		fe->legacy = 1;
+
+		/*
+		if ( fepriv ) {
+			memset(&fepriv->fe_info, 0, sizeof (struct dvbfe_info));
+			fepriv->fe_info.delivery = DVBFE_DELSYS_DVBS;
+			fe->ops.get_info(fe, &fepriv->fe_info);
+		}
+		*/
 
+		memcpy(&fepriv->parameters, parg, sizeof (struct dvb_frontend_parameters));
 		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
-		memcpy(&fetunesettings.parameters, parg,
-		       sizeof (struct dvb_frontend_parameters));
+		memcpy(&fetunesettings.parameters, parg, sizeof (struct dvb_frontend_parameters));
+
+		olddrv_to_newapi(fe,&fepriv->fe_params, &fepriv->parameters, FE_QPSK);
+
+		/* Request the search algorithm to search	*/
+		fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
 
 		/* force auto frequency inversion if requested */
 		if (dvb_force_auto_inversion) {
@@ -950,6 +1634,7 @@ static int dvb_frontend_ioctl(struct ino
 		break;
 
 	case FE_GET_FRONTEND:
+		fe->legacy = 1;
 		if (fe->ops.get_frontend) {
 			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
 			err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
@@ -960,6 +1645,116 @@ static int dvb_frontend_ioctl(struct ino
 		fepriv->tune_mode_flags = (unsigned long) parg;
 		err = 0;
 		break;
+
+	case DVBFE_SET_PARAMS: {
+		struct dvb_frontend_tune_settings fetunesettings;
+
+		fe->legacy = 0;
+		memcpy(&fepriv->fe_params, parg, sizeof (struct dvbfe_params));
+		memset(&fetunesettings, 0, sizeof (struct dvb_frontend_tune_settings));
+		memcpy(&fetunesettings.fe_params, parg, sizeof (struct dvbfe_params));
+
+		if (newapi_to_olddrv(&fepriv->fe_params, &fepriv->parameters, fepriv->fe_info.delivery)  == -EINVAL)
+			printk("%s: ERROR !!! Converting New parameters --> Old parameters\n", __func__);
+
+		/* Request the search algorithm to search	*/
+		fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
+
+		/* force auto frequency inversion if requested */
+		if (dvb_force_auto_inversion) {
+			fepriv->fe_params.inversion = DVBFE_INVERSION_AUTO;
+			fetunesettings.fe_params.inversion = DVBFE_INVERSION_AUTO;
+		}
+		if (fe->ops.get_delsys) {
+			fe->ops.get_delsys(fe, &delsys);
+			if ((delsys == DVBFE_DELSYS_DVBT) ||
+			    (delsys == DVBFE_DELSYS_DVBH)) {
+
+				/* without hierachical coding code_rate_LP is irrelevant,
+				 * so we tolerate the otherwise invalid FEC_NONE setting */
+				if (fepriv->fe_params.delsys.dvbt.hierarchy == DVBFE_HIERARCHY_OFF &&
+				    fepriv->fe_params.delsys.dvbt.code_rate_LP == DVBFE_FEC_NONE)
+
+					fepriv->fe_params.delsys.dvbt.code_rate_LP = DVBFE_FEC_AUTO;
+			}
+		}
+
+		/* get frontend-specific tuning settings */
+		if (fe->ops.get_tune_settings &&
+		   (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
+
+			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+			fepriv->max_drift = fetunesettings.max_drift;
+			fepriv->step_size = fetunesettings.step_size;
+		} else {
+			/* default values */
+			switch (fepriv->fe_info.delivery) {
+			case DVBFE_DELSYS_DVBS:
+			case DVBFE_DELSYS_DSS:
+			case DVBFE_DELSYS_DVBS2:
+				fepriv->min_delay = HZ / 20;
+				fepriv->step_size = fepriv->fe_params.delsys.dvbs.symbol_rate / 16000;
+				fepriv->max_drift = fepriv->fe_params.delsys.dvbs.symbol_rate / 2000;
+				break;
+			case DVBFE_DELSYS_DVBC:
+				fepriv->min_delay = HZ / 20;
+				fepriv->step_size = 0; /* no zigzag */
+				fepriv->max_drift = 0;
+				break;
+			case DVBFE_DELSYS_DVBT:
+			case DVBFE_DELSYS_DVBH:
+				fepriv->min_delay = HZ / 20;
+				fepriv->step_size = fepriv->fe_info.frequency_step * 2;
+				fepriv->max_drift = (fepriv->fe_info.frequency_step * 2) + 1;
+				break;
+			case DVBFE_DELSYS_ATSC:
+				fepriv->min_delay = HZ / 20;
+				fepriv->step_size = 0;
+				fepriv->max_drift = 0;
+				break;
+			default:
+				return -EINVAL;
+			}
+		}
+		if (dvb_override_tune_delay > 0)
+			fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+
+		fepriv->state = FESTATE_RETUNE;
+/*		printk("%s: FESTATE_RETUNE: fepriv->state=%d\n", __func__, fepriv->state);
+*/		dvb_frontend_wakeup(fe);
+		dvb_frontend_add_event(fe, 0);
+		fepriv->status = 0;
+		err = 0;
+		break;
+	}
+
+	case DVBFE_GET_PARAMS:
+		fe->legacy = 0;
+		if (fe->ops.get_params) {
+			memcpy(parg, &fepriv->fe_params, sizeof (struct dvbfe_params));
+			err = fe->ops.get_params(fe, (struct dvbfe_params *) parg);
+		} else if (fe->ops.get_frontend) {
+			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
+			err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
+			if (olddrv_to_newapi(fe, &fepriv->fe_params, &fepriv->parameters, fe->ops.info.type) == -EINVAL)
+				printk("%s: ERROR !!! Converting Old parameters --> New parameters\n", __func__);
+		}
+		break;
+	case DVBFE_GET_DELSYS:
+		fe->legacy = 0;
+		if (fe->ops.get_delsys) {
+			err = fe->ops.get_delsys(fe, (enum dvbfe_delsys *) parg);
+		}
+		break;
+	case DVBFE_GET_INFO:
+/*		printk("%s: DVBFE_GET_INFO\n", __func__);
+*/		fe->legacy = 0;
+		if (fe->ops.get_info) {
+			memcpy(&fepriv->fe_info, (struct dvbfe_info *) parg, sizeof (struct dvbfe_info));
+			err = fe->ops.get_info(fe, &fepriv->fe_info);
+			memcpy((struct dvbfe_info *) parg, &fepriv->fe_info, sizeof (struct dvbfe_info));
+		}
+		break;
 	};
 
 	up (&fepriv->sem);
@@ -1123,13 +1918,15 @@ void dvb_frontend_detach(struct dvb_fron
 {
 	void *ptr;
 
-	if (fe->ops.release_sec) {
+	ptr = (void*)fe->ops.release_sec;
+	if (ptr) {
 		fe->ops.release_sec(fe);
-		symbol_put_addr(fe->ops.release_sec);
+		symbol_put_addr(ptr);
 	}
-	if (fe->ops.tuner_ops.release) {
+	ptr = (void*)fe->ops.tuner_ops.release;
+	if (ptr) {
 		fe->ops.tuner_ops.release(fe);
-		symbol_put_addr(fe->ops.tuner_ops.release);
+		symbol_put_addr(ptr);
 	}
 	ptr = (void*)fe->ops.release;
 	if (ptr) {
diff -urNp linux-2.6.22.1/drivers/media/dvb/dvb-core/dvb_frontend.c.orig linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvb_frontend.c.orig
--- linux-2.6.22.1/drivers/media/dvb/dvb-core/dvb_frontend.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvb_frontend.c.orig	2007-07-10 20:56:30.000000000 +0200
@@ -0,0 +1,1151 @@
+/*
+ * dvb_frontend.c: DVB frontend tuning interface/thread
+ *
+ *
+ * Copyright (C) 1999-2001 Ralph  Metzler
+ *			   Marcus Metzler
+ *			   Holger Waechtler
+ *				      for convergence integrated media GmbH
+ *
+ * Copyright (C) 2004 Andrew de Quincey (tuning thread cleanup)
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/list.h>
+#include <linux/freezer.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+#include <asm/processor.h>
+
+#include "dvb_frontend.h"
+#include "dvbdev.h"
+
+static int dvb_frontend_debug;
+static int dvb_shutdown_timeout = 5;
+static int dvb_force_auto_inversion;
+static int dvb_override_tune_delay;
+static int dvb_powerdown_on_sleep = 1;
+
+module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
+MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off).");
+module_param(dvb_shutdown_timeout, int, 0644);
+MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
+module_param(dvb_force_auto_inversion, int, 0644);
+MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
+module_param(dvb_override_tune_delay, int, 0644);
+MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
+module_param(dvb_powerdown_on_sleep, int, 0644);
+MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
+
+#define dprintk if (dvb_frontend_debug) printk
+
+#define FESTATE_IDLE 1
+#define FESTATE_RETUNE 2
+#define FESTATE_TUNING_FAST 4
+#define FESTATE_TUNING_SLOW 8
+#define FESTATE_TUNED 16
+#define FESTATE_ZIGZAG_FAST 32
+#define FESTATE_ZIGZAG_SLOW 64
+#define FESTATE_DISEQC 128
+#define FESTATE_WAITFORLOCK (FESTATE_TUNING_FAST | FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW | FESTATE_DISEQC)
+#define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
+#define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
+#define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
+
+#define FE_ALGO_HW		1
+/*
+ * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
+ * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
+ * FESTATE_TUNING_FAST. Tuning parameters have been supplied and fast zigzag scan is in progress.
+ * FESTATE_TUNING_SLOW. Tuning parameters have been supplied. Fast zigzag failed, so we're trying again, but slower.
+ * FESTATE_TUNED. The frontend has successfully locked on.
+ * FESTATE_ZIGZAG_FAST. The lock has been lost, and a fast zigzag has been initiated to try and regain it.
+ * FESTATE_ZIGZAG_SLOW. The lock has been lost. Fast zigzag has been failed, so we're trying again, but slower.
+ * FESTATE_DISEQC. A DISEQC command has just been issued.
+ * FESTATE_WAITFORLOCK. When we're waiting for a lock.
+ * FESTATE_SEARCHING_FAST. When we're searching for a signal using a fast zigzag scan.
+ * FESTATE_SEARCHING_SLOW. When we're searching for a signal using a slow zigzag scan.
+ * FESTATE_LOSTLOCK. When the lock has been lost, and we're searching it again.
+ */
+
+static DEFINE_MUTEX(frontend_mutex);
+
+struct dvb_frontend_private {
+
+	/* thread/frontend values */
+	struct dvb_device *dvbdev;
+	struct dvb_frontend_parameters parameters;
+	struct dvb_fe_events events;
+	struct semaphore sem;
+	struct list_head list_head;
+	wait_queue_head_t wait_queue;
+	struct task_struct *thread;
+	unsigned long release_jiffies;
+	unsigned int exit;
+	unsigned int wakeup;
+	fe_status_t status;
+	unsigned long tune_mode_flags;
+	unsigned int delay;
+	unsigned int reinitialise;
+	int tone;
+	int voltage;
+
+	/* swzigzag values */
+	unsigned int state;
+	unsigned int bending;
+	int lnb_drift;
+	unsigned int inversion;
+	unsigned int auto_step;
+	unsigned int auto_sub_step;
+	unsigned int started_auto_step;
+	unsigned int min_delay;
+	unsigned int max_drift;
+	unsigned int step_size;
+	int quality;
+	unsigned int check_wrapped;
+};
+
+static void dvb_frontend_wakeup(struct dvb_frontend *fe);
+
+static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_fe_events *events = &fepriv->events;
+	struct dvb_frontend_event *e;
+	int wp;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (down_interruptible (&events->sem))
+		return;
+
+	wp = (events->eventw + 1) % MAX_EVENT;
+
+	if (wp == events->eventr) {
+		events->overflow = 1;
+		events->eventr = (events->eventr + 1) % MAX_EVENT;
+	}
+
+	e = &events->events[events->eventw];
+
+	memcpy (&e->parameters, &fepriv->parameters,
+		sizeof (struct dvb_frontend_parameters));
+
+	if (status & FE_HAS_LOCK)
+		if (fe->ops.get_frontend)
+			fe->ops.get_frontend(fe, &e->parameters);
+
+	events->eventw = wp;
+
+	up (&events->sem);
+
+	e->status = status;
+
+	wake_up_interruptible (&events->wait_queue);
+}
+
+static int dvb_frontend_get_event(struct dvb_frontend *fe,
+			    struct dvb_frontend_event *event, int flags)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct dvb_fe_events *events = &fepriv->events;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (events->overflow) {
+		events->overflow = 0;
+		return -EOVERFLOW;
+	}
+
+	if (events->eventw == events->eventr) {
+		int ret;
+
+		if (flags & O_NONBLOCK)
+			return -EWOULDBLOCK;
+
+		up(&fepriv->sem);
+
+		ret = wait_event_interruptible (events->wait_queue,
+						events->eventw != events->eventr);
+
+		if (down_interruptible (&fepriv->sem))
+			return -ERESTARTSYS;
+
+		if (ret < 0)
+			return ret;
+	}
+
+	if (down_interruptible (&events->sem))
+		return -ERESTARTSYS;
+
+	memcpy (event, &events->events[events->eventr],
+		sizeof(struct dvb_frontend_event));
+
+	events->eventr = (events->eventr + 1) % MAX_EVENT;
+
+	up (&events->sem);
+
+	return 0;
+}
+
+static void dvb_frontend_init(struct dvb_frontend *fe)
+{
+	dprintk ("DVB: initialising frontend %i (%s)...\n",
+		 fe->dvb->num,
+		 fe->ops.info.name);
+
+	if (fe->ops.init)
+		fe->ops.init(fe);
+	if (fe->ops.tuner_ops.init) {
+		fe->ops.tuner_ops.init(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+}
+
+void dvb_frontend_reinitialise(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	fepriv->reinitialise = 1;
+	dvb_frontend_wakeup(fe);
+}
+EXPORT_SYMBOL(dvb_frontend_reinitialise);
+
+static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
+{
+	int q2;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (locked)
+		(fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
+	else
+		(fepriv->quality) = (fepriv->quality * 220 + 0) / 256;
+
+	q2 = fepriv->quality - 128;
+	q2 *= q2;
+
+	fepriv->delay = fepriv->min_delay + q2 * HZ / (128*128);
+}
+
+/**
+ * Performs automatic twiddling of frontend parameters.
+ *
+ * @param fe The frontend concerned.
+ * @param check_wrapped Checks if an iteration has completed. DO NOT SET ON THE FIRST ATTEMPT
+ * @returns Number of complete iterations that have been performed.
+ */
+static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wrapped)
+{
+	int autoinversion;
+	int ready = 0;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	int original_inversion = fepriv->parameters.inversion;
+	u32 original_frequency = fepriv->parameters.frequency;
+
+	/* are we using autoinversion? */
+	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+			 (fepriv->parameters.inversion == INVERSION_AUTO));
+
+	/* setup parameters correctly */
+	while(!ready) {
+		/* calculate the lnb_drift */
+		fepriv->lnb_drift = fepriv->auto_step * fepriv->step_size;
+
+		/* wrap the auto_step if we've exceeded the maximum drift */
+		if (fepriv->lnb_drift > fepriv->max_drift) {
+			fepriv->auto_step = 0;
+			fepriv->auto_sub_step = 0;
+			fepriv->lnb_drift = 0;
+		}
+
+		/* perform inversion and +/- zigzag */
+		switch(fepriv->auto_sub_step) {
+		case 0:
+			/* try with the current inversion and current drift setting */
+			ready = 1;
+			break;
+
+		case 1:
+			if (!autoinversion) break;
+
+			fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
+			ready = 1;
+			break;
+
+		case 2:
+			if (fepriv->lnb_drift == 0) break;
+
+			fepriv->lnb_drift = -fepriv->lnb_drift;
+			ready = 1;
+			break;
+
+		case 3:
+			if (fepriv->lnb_drift == 0) break;
+			if (!autoinversion) break;
+
+			fepriv->inversion = (fepriv->inversion == INVERSION_OFF) ? INVERSION_ON : INVERSION_OFF;
+			fepriv->lnb_drift = -fepriv->lnb_drift;
+			ready = 1;
+			break;
+
+		default:
+			fepriv->auto_step++;
+			fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */
+			break;
+		}
+
+		if (!ready) fepriv->auto_sub_step++;
+	}
+
+	/* if this attempt would hit where we started, indicate a complete
+	 * iteration has occurred */
+	if ((fepriv->auto_step == fepriv->started_auto_step) &&
+	    (fepriv->auto_sub_step == 0) && check_wrapped) {
+		return 1;
+	}
+
+	dprintk("%s: drift:%i inversion:%i auto_step:%i "
+		"auto_sub_step:%i started_auto_step:%i\n",
+		__FUNCTION__, fepriv->lnb_drift, fepriv->inversion,
+		fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
+
+	/* set the frontend itself */
+	fepriv->parameters.frequency += fepriv->lnb_drift;
+	if (autoinversion)
+		fepriv->parameters.inversion = fepriv->inversion;
+	if (fe->ops.set_frontend)
+		fe->ops.set_frontend(fe, &fepriv->parameters);
+
+	fepriv->parameters.frequency = original_frequency;
+	fepriv->parameters.inversion = original_inversion;
+
+	fepriv->auto_sub_step++;
+	return 0;
+}
+
+static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
+{
+	fe_status_t s = 0;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	/* if we've got no parameters, just keep idling */
+	if (fepriv->state & FESTATE_IDLE) {
+		fepriv->delay = 3*HZ;
+		fepriv->quality = 0;
+		return;
+	}
+
+	/* in SCAN mode, we just set the frontend when asked and leave it alone */
+	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
+		if (fepriv->state & FESTATE_RETUNE) {
+			if (fe->ops.set_frontend)
+				fe->ops.set_frontend(fe, &fepriv->parameters);
+			fepriv->state = FESTATE_TUNED;
+		}
+		fepriv->delay = 3*HZ;
+		fepriv->quality = 0;
+		return;
+	}
+
+	/* get the frontend status */
+	if (fepriv->state & FESTATE_RETUNE) {
+		s = 0;
+	} else {
+		if (fe->ops.read_status)
+			fe->ops.read_status(fe, &s);
+		if (s != fepriv->status) {
+			dvb_frontend_add_event(fe, s);
+			fepriv->status = s;
+		}
+	}
+
+	/* if we're not tuned, and we have a lock, move to the TUNED state */
+	if ((fepriv->state & FESTATE_WAITFORLOCK) && (s & FE_HAS_LOCK)) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+		fepriv->state = FESTATE_TUNED;
+
+		/* if we're tuned, then we have determined the correct inversion */
+		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
+		    (fepriv->parameters.inversion == INVERSION_AUTO)) {
+			fepriv->parameters.inversion = fepriv->inversion;
+		}
+		return;
+	}
+
+	/* if we are tuned already, check we're still locked */
+	if (fepriv->state & FESTATE_TUNED) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+		/* we're tuned, and the lock is still good... */
+		if (s & FE_HAS_LOCK) {
+			return;
+		} else { /* if we _WERE_ tuned, but now don't have a lock */
+			fepriv->state = FESTATE_ZIGZAG_FAST;
+			fepriv->started_auto_step = fepriv->auto_step;
+			fepriv->check_wrapped = 0;
+		}
+	}
+
+	/* don't actually do anything if we're in the LOSTLOCK state,
+	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
+	if ((fepriv->state & FESTATE_LOSTLOCK) &&
+	    (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+		return;
+	}
+
+	/* don't do anything if we're in the DISEQC state, since this
+	 * might be someone with a motorized dish controlled by DISEQC.
+	 * If its actually a re-tune, there will be a SET_FRONTEND soon enough.	*/
+	if (fepriv->state & FESTATE_DISEQC) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+		return;
+	}
+
+	/* if we're in the RETUNE state, set everything up for a brand
+	 * new scan, keeping the current inversion setting, as the next
+	 * tune is _very_ likely to require the same */
+	if (fepriv->state & FESTATE_RETUNE) {
+		fepriv->lnb_drift = 0;
+		fepriv->auto_step = 0;
+		fepriv->auto_sub_step = 0;
+		fepriv->started_auto_step = 0;
+		fepriv->check_wrapped = 0;
+	}
+
+	/* fast zigzag. */
+	if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
+		fepriv->delay = fepriv->min_delay;
+
+		/* peform a tune */
+		if (dvb_frontend_swzigzag_autotune(fe, fepriv->check_wrapped)) {
+			/* OK, if we've run out of trials at the fast speed.
+			 * Drop back to slow for the _next_ attempt */
+			fepriv->state = FESTATE_SEARCHING_SLOW;
+			fepriv->started_auto_step = fepriv->auto_step;
+			return;
+		}
+		fepriv->check_wrapped = 1;
+
+		/* if we've just retuned, enter the ZIGZAG_FAST state.
+		 * This ensures we cannot return from an
+		 * FE_SET_FRONTEND ioctl before the first frontend tune
+		 * occurs */
+		if (fepriv->state & FESTATE_RETUNE) {
+			fepriv->state = FESTATE_TUNING_FAST;
+		}
+	}
+
+	/* slow zigzag */
+	if (fepriv->state & FESTATE_SEARCHING_SLOW) {
+		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
+
+		/* Note: don't bother checking for wrapping; we stay in this
+		 * state until we get a lock */
+		dvb_frontend_swzigzag_autotune(fe, 0);
+	}
+}
+
+static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	if (fepriv->exit)
+		return 1;
+
+	if (fepriv->dvbdev->writers == 1)
+		if (time_after(jiffies, fepriv->release_jiffies +
+				  dvb_shutdown_timeout * HZ))
+			return 1;
+
+	return 0;
+}
+
+static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	if (fepriv->wakeup) {
+		fepriv->wakeup = 0;
+		return 1;
+	}
+	return dvb_frontend_is_exiting(fe);
+}
+
+static void dvb_frontend_wakeup(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	fepriv->wakeup = 1;
+	wake_up_interruptible(&fepriv->wait_queue);
+}
+
+static int dvb_frontend_thread(void *data)
+{
+	struct dvb_frontend *fe = data;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	unsigned long timeout;
+	fe_status_t s;
+	struct dvb_frontend_parameters *params;
+
+	dprintk("%s\n", __FUNCTION__);
+
+	fepriv->check_wrapped = 0;
+	fepriv->quality = 0;
+	fepriv->delay = 3*HZ;
+	fepriv->status = 0;
+	fepriv->wakeup = 0;
+	fepriv->reinitialise = 0;
+
+	dvb_frontend_init(fe);
+
+	while (1) {
+		up(&fepriv->sem);	    /* is locked when we enter the thread... */
+restart:
+		timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
+			dvb_frontend_should_wakeup(fe) || kthread_should_stop(),
+			fepriv->delay);
+
+		if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
+			/* got signal or quitting */
+			break;
+		}
+
+		if (try_to_freeze())
+			goto restart;
+
+		if (down_interruptible(&fepriv->sem))
+			break;
+
+		if (fepriv->reinitialise) {
+			dvb_frontend_init(fe);
+			if (fepriv->tone != -1) {
+				fe->ops.set_tone(fe, fepriv->tone);
+			}
+			if (fepriv->voltage != -1) {
+				fe->ops.set_voltage(fe, fepriv->voltage);
+			}
+			fepriv->reinitialise = 0;
+		}
+
+		/* do an iteration of the tuning loop */
+		if (fe->ops.get_frontend_algo) {
+			if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
+				/* have we been asked to retune? */
+				params = NULL;
+				if (fepriv->state & FESTATE_RETUNE) {
+					params = &fepriv->parameters;
+					fepriv->state = FESTATE_TUNED;
+				}
+
+				fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+				if (s != fepriv->status) {
+					dvb_frontend_add_event(fe, s);
+					fepriv->status = s;
+				}
+			} else
+				dvb_frontend_swzigzag(fe);
+		} else
+			dvb_frontend_swzigzag(fe);
+	}
+
+	if (dvb_shutdown_timeout) {
+		if (dvb_powerdown_on_sleep)
+			if (fe->ops.set_voltage)
+				fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
+		if (fe->ops.tuner_ops.sleep) {
+			fe->ops.tuner_ops.sleep(fe);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (fe->ops.sleep)
+			fe->ops.sleep(fe);
+	}
+
+	fepriv->thread = NULL;
+	mb();
+
+	dvb_frontend_wakeup(fe);
+	return 0;
+}
+
+static void dvb_frontend_stop(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	fepriv->exit = 1;
+	mb();
+
+	if (!fepriv->thread)
+		return;
+
+	kthread_stop(fepriv->thread);
+
+	init_MUTEX (&fepriv->sem);
+	fepriv->state = FESTATE_IDLE;
+
+	/* paranoia check in case a signal arrived */
+	if (fepriv->thread)
+		printk("dvb_frontend_stop: warning: thread %p won't exit\n",
+				fepriv->thread);
+}
+
+s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime)
+{
+	return ((curtime.tv_usec < lasttime.tv_usec) ?
+		1000000 - lasttime.tv_usec + curtime.tv_usec :
+		curtime.tv_usec - lasttime.tv_usec);
+}
+EXPORT_SYMBOL(timeval_usec_diff);
+
+static inline void timeval_usec_add(struct timeval *curtime, u32 add_usec)
+{
+	curtime->tv_usec += add_usec;
+	if (curtime->tv_usec >= 1000000) {
+		curtime->tv_usec -= 1000000;
+		curtime->tv_sec++;
+	}
+}
+
+/*
+ * Sleep until gettimeofday() > waketime + add_usec
+ * This needs to be as precise as possible, but as the delay is
+ * usually between 2ms and 32ms, it is done using a scheduled msleep
+ * followed by usleep (normally a busy-wait loop) for the remainder
+ */
+void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec)
+{
+	struct timeval lasttime;
+	s32 delta, newdelta;
+
+	timeval_usec_add(waketime, add_usec);
+
+	do_gettimeofday(&lasttime);
+	delta = timeval_usec_diff(lasttime, *waketime);
+	if (delta > 2500) {
+		msleep((delta - 1500) / 1000);
+		do_gettimeofday(&lasttime);
+		newdelta = timeval_usec_diff(lasttime, *waketime);
+		delta = (newdelta > delta) ? 0 : newdelta;
+	}
+	if (delta > 0)
+		udelay(delta);
+}
+EXPORT_SYMBOL(dvb_frontend_sleep_until);
+
+static int dvb_frontend_start(struct dvb_frontend *fe)
+{
+	int ret;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	struct task_struct *fe_thread;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (fepriv->thread) {
+		if (!fepriv->exit)
+			return 0;
+		else
+			dvb_frontend_stop (fe);
+	}
+
+	if (signal_pending(current))
+		return -EINTR;
+	if (down_interruptible (&fepriv->sem))
+		return -EINTR;
+
+	fepriv->state = FESTATE_IDLE;
+	fepriv->exit = 0;
+	fepriv->thread = NULL;
+	mb();
+
+	fe_thread = kthread_run(dvb_frontend_thread, fe,
+		"kdvb-fe-%i", fe->dvb->num);
+	if (IS_ERR(fe_thread)) {
+		ret = PTR_ERR(fe_thread);
+		printk("dvb_frontend_start: failed to start kthread (%d)\n", ret);
+		up(&fepriv->sem);
+		return ret;
+	}
+	fepriv->thread = fe_thread;
+	return 0;
+}
+
+static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	int err = -EOPNOTSUPP;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (!fe || fepriv->exit)
+		return -ENODEV;
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
+	    (_IOC_DIR(cmd) != _IOC_READ || cmd == FE_GET_EVENT ||
+	     cmd == FE_DISEQC_RECV_SLAVE_REPLY))
+		return -EPERM;
+
+	if (down_interruptible (&fepriv->sem))
+		return -ERESTARTSYS;
+
+	switch (cmd) {
+	case FE_GET_INFO: {
+		struct dvb_frontend_info* info = parg;
+		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
+
+		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
+		 * do it, it is done for it. */
+		info->caps |= FE_CAN_INVERSION_AUTO;
+		err = 0;
+		break;
+	}
+
+	case FE_READ_STATUS: {
+		fe_status_t* status = parg;
+
+		/* if retune was requested but hasn't occured yet, prevent
+		 * that user get signal state from previous tuning */
+		if(fepriv->state == FESTATE_RETUNE) {
+			err=0;
+			*status = 0;
+			break;
+		}
+
+		if (fe->ops.read_status)
+			err = fe->ops.read_status(fe, status);
+		break;
+	}
+	case FE_READ_BER:
+		if (fe->ops.read_ber)
+			err = fe->ops.read_ber(fe, (__u32*) parg);
+		break;
+
+	case FE_READ_SIGNAL_STRENGTH:
+		if (fe->ops.read_signal_strength)
+			err = fe->ops.read_signal_strength(fe, (__u16*) parg);
+		break;
+
+	case FE_READ_SNR:
+		if (fe->ops.read_snr)
+			err = fe->ops.read_snr(fe, (__u16*) parg);
+		break;
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		if (fe->ops.read_ucblocks)
+			err = fe->ops.read_ucblocks(fe, (__u32*) parg);
+		break;
+
+
+	case FE_DISEQC_RESET_OVERLOAD:
+		if (fe->ops.diseqc_reset_overload) {
+			err = fe->ops.diseqc_reset_overload(fe);
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_DISEQC_SEND_MASTER_CMD:
+		if (fe->ops.diseqc_send_master_cmd) {
+			err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_DISEQC_SEND_BURST:
+		if (fe->ops.diseqc_send_burst) {
+			err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_SET_TONE:
+		if (fe->ops.set_tone) {
+			err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
+			fepriv->tone = (fe_sec_tone_mode_t) parg;
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_SET_VOLTAGE:
+		if (fe->ops.set_voltage) {
+			err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
+			fepriv->voltage = (fe_sec_voltage_t) parg;
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_DISHNETWORK_SEND_LEGACY_CMD:
+		if (fe->ops.dishnetwork_send_legacy_command) {
+			err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		} else if (fe->ops.set_voltage) {
+			/*
+			 * NOTE: This is a fallback condition.  Some frontends
+			 * (stv0299 for instance) take longer than 8msec to
+			 * respond to a set_voltage command.  Those switches
+			 * need custom routines to switch properly.  For all
+			 * other frontends, the following shoule work ok.
+			 * Dish network legacy switches (as used by Dish500)
+			 * are controlled by sending 9-bit command words
+			 * spaced 8msec apart.
+			 * the actual command word is switch/port dependant
+			 * so it is up to the userspace application to send
+			 * the right command.
+			 * The command must always start with a '0' after
+			 * initialization, so parg is 8 bits and does not
+			 * include the initialization or start bit
+			 */
+			unsigned long cmd = ((unsigned long) parg) << 1;
+			struct timeval nexttime;
+			struct timeval tv[10];
+			int i;
+			u8 last = 1;
+			if (dvb_frontend_debug)
+				printk("%s switch command: 0x%04lx\n", __FUNCTION__, cmd);
+			do_gettimeofday(&nexttime);
+			if (dvb_frontend_debug)
+				memcpy(&tv[0], &nexttime, sizeof(struct timeval));
+			/* before sending a command, initialize by sending
+			 * a 32ms 18V to the switch
+			 */
+			fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
+			dvb_frontend_sleep_until(&nexttime, 32000);
+
+			for (i = 0; i < 9; i++) {
+				if (dvb_frontend_debug)
+					do_gettimeofday(&tv[i + 1]);
+				if ((cmd & 0x01) != last) {
+					/* set voltage to (last ? 13V : 18V) */
+					fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+					last = (last) ? 0 : 1;
+				}
+				cmd = cmd >> 1;
+				if (i != 8)
+					dvb_frontend_sleep_until(&nexttime, 8000);
+			}
+			if (dvb_frontend_debug) {
+				printk("%s(%d): switch delay (should be 32k followed by all 8k\n",
+					__FUNCTION__, fe->dvb->num);
+				for (i = 1; i < 10; i++)
+					printk("%d: %d\n", i, timeval_usec_diff(tv[i-1] , tv[i]));
+			}
+			err = 0;
+			fepriv->state = FESTATE_DISEQC;
+			fepriv->status = 0;
+		}
+		break;
+
+	case FE_DISEQC_RECV_SLAVE_REPLY:
+		if (fe->ops.diseqc_recv_slave_reply)
+			err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
+		break;
+
+	case FE_ENABLE_HIGH_LNB_VOLTAGE:
+		if (fe->ops.enable_high_lnb_voltage)
+			err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
+		break;
+
+	case FE_SET_FRONTEND: {
+		struct dvb_frontend_tune_settings fetunesettings;
+
+		memcpy (&fepriv->parameters, parg,
+			sizeof (struct dvb_frontend_parameters));
+
+		memset(&fetunesettings, 0, sizeof(struct dvb_frontend_tune_settings));
+		memcpy(&fetunesettings.parameters, parg,
+		       sizeof (struct dvb_frontend_parameters));
+
+		/* force auto frequency inversion if requested */
+		if (dvb_force_auto_inversion) {
+			fepriv->parameters.inversion = INVERSION_AUTO;
+			fetunesettings.parameters.inversion = INVERSION_AUTO;
+		}
+		if (fe->ops.info.type == FE_OFDM) {
+			/* without hierarchical coding code_rate_LP is irrelevant,
+			 * so we tolerate the otherwise invalid FEC_NONE setting */
+			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
+			    fepriv->parameters.u.ofdm.code_rate_LP == FEC_NONE)
+				fepriv->parameters.u.ofdm.code_rate_LP = FEC_AUTO;
+		}
+
+		/* get frontend-specific tuning settings */
+		if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
+			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
+			fepriv->max_drift = fetunesettings.max_drift;
+			fepriv->step_size = fetunesettings.step_size;
+		} else {
+			/* default values */
+			switch(fe->ops.info.type) {
+			case FE_QPSK:
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
+				fepriv->max_drift = fepriv->parameters.u.qpsk.symbol_rate / 2000;
+				break;
+
+			case FE_QAM:
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = 0; /* no zigzag */
+				fepriv->max_drift = 0;
+				break;
+
+			case FE_OFDM:
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
+				fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
+				break;
+			case FE_ATSC:
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = 0;
+				fepriv->max_drift = 0;
+				break;
+			}
+		}
+		if (dvb_override_tune_delay > 0)
+			fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000;
+
+		fepriv->state = FESTATE_RETUNE;
+		dvb_frontend_wakeup(fe);
+		dvb_frontend_add_event(fe, 0);
+		fepriv->status = 0;
+		err = 0;
+		break;
+	}
+
+	case FE_GET_EVENT:
+		err = dvb_frontend_get_event (fe, parg, file->f_flags);
+		break;
+
+	case FE_GET_FRONTEND:
+		if (fe->ops.get_frontend) {
+			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
+			err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
+		}
+		break;
+
+	case FE_SET_FRONTEND_TUNE_MODE:
+		fepriv->tune_mode_flags = (unsigned long) parg;
+		err = 0;
+		break;
+	};
+
+	up (&fepriv->sem);
+	return err;
+}
+
+static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	poll_wait (file, &fepriv->events.wait_queue, wait);
+
+	if (fepriv->events.eventw != fepriv->events.eventr)
+		return (POLLIN | POLLRDNORM | POLLPRI);
+
+	return 0;
+}
+
+static int dvb_frontend_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	int ret;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if ((ret = dvb_generic_open (inode, file)) < 0)
+		return ret;
+
+	if (fe->ops.ts_bus_ctrl) {
+		if ((ret = fe->ops.ts_bus_ctrl (fe, 1)) < 0) {
+			dvb_generic_release (inode, file);
+			return ret;
+		}
+	}
+
+	if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
+
+		/* normal tune mode when opened R/W */
+		fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT;
+		fepriv->tone = -1;
+		fepriv->voltage = -1;
+
+		ret = dvb_frontend_start (fe);
+		if (ret)
+			dvb_generic_release (inode, file);
+
+		/*  empty event queue */
+		fepriv->events.eventr = fepriv->events.eventw = 0;
+	}
+
+	return ret;
+}
+
+static int dvb_frontend_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_frontend *fe = dvbdev->priv;
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	int ret;
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+		fepriv->release_jiffies = jiffies;
+
+	if (fe->ops.ts_bus_ctrl)
+		fe->ops.ts_bus_ctrl (fe, 0);
+
+	ret = dvb_generic_release (inode, file);
+
+	if (dvbdev->users==-1 && fepriv->exit==1) {
+		fops_put(file->f_op);
+		file->f_op = NULL;
+		wake_up(&dvbdev->wait_queue);
+	}
+	return ret;
+}
+
+static struct file_operations dvb_frontend_fops = {
+	.owner		= THIS_MODULE,
+	.ioctl		= dvb_generic_ioctl,
+	.poll		= dvb_frontend_poll,
+	.open		= dvb_frontend_open,
+	.release	= dvb_frontend_release
+};
+
+int dvb_register_frontend(struct dvb_adapter* dvb,
+			  struct dvb_frontend* fe)
+{
+	struct dvb_frontend_private *fepriv;
+	static const struct dvb_device dvbdev_template = {
+		.users = ~0,
+		.writers = 1,
+		.readers = (~0)-1,
+		.fops = &dvb_frontend_fops,
+		.kernel_ioctl = dvb_frontend_ioctl
+	};
+
+	dprintk ("%s\n", __FUNCTION__);
+
+	if (mutex_lock_interruptible(&frontend_mutex))
+		return -ERESTARTSYS;
+
+	fe->frontend_priv = kzalloc(sizeof(struct dvb_frontend_private), GFP_KERNEL);
+	if (fe->frontend_priv == NULL) {
+		mutex_unlock(&frontend_mutex);
+		return -ENOMEM;
+	}
+	fepriv = fe->frontend_priv;
+
+	init_MUTEX (&fepriv->sem);
+	init_waitqueue_head (&fepriv->wait_queue);
+	init_waitqueue_head (&fepriv->events.wait_queue);
+	init_MUTEX (&fepriv->events.sem);
+	fe->dvb = dvb;
+	fepriv->inversion = INVERSION_OFF;
+
+	printk ("DVB: registering frontend %i (%s)...\n",
+		fe->dvb->num,
+		fe->ops.info.name);
+
+	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
+			     fe, DVB_DEVICE_FRONTEND);
+
+	mutex_unlock(&frontend_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(dvb_register_frontend);
+
+int dvb_unregister_frontend(struct dvb_frontend* fe)
+{
+	struct dvb_frontend_private *fepriv = fe->frontend_priv;
+	dprintk ("%s\n", __FUNCTION__);
+
+	mutex_lock(&frontend_mutex);
+	dvb_frontend_stop (fe);
+	mutex_unlock(&frontend_mutex);
+
+	if (fepriv->dvbdev->users < -1)
+		wait_event(fepriv->dvbdev->wait_queue,
+				fepriv->dvbdev->users==-1);
+
+	mutex_lock(&frontend_mutex);
+	dvb_unregister_device (fepriv->dvbdev);
+
+	/* fe is invalid now */
+	kfree(fepriv);
+	mutex_unlock(&frontend_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(dvb_unregister_frontend);
+
+#ifdef CONFIG_DVB_CORE_ATTACH
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+	void *ptr;
+
+	if (fe->ops.release_sec) {
+		fe->ops.release_sec(fe);
+		symbol_put_addr(fe->ops.release_sec);
+	}
+	if (fe->ops.tuner_ops.release) {
+		fe->ops.tuner_ops.release(fe);
+		symbol_put_addr(fe->ops.tuner_ops.release);
+	}
+	ptr = (void*)fe->ops.release;
+	if (ptr) {
+		fe->ops.release(fe);
+		symbol_put_addr(ptr);
+	}
+}
+#else
+void dvb_frontend_detach(struct dvb_frontend* fe)
+{
+	if (fe->ops.release_sec)
+		fe->ops.release_sec(fe);
+	if (fe->ops.tuner_ops.release)
+		fe->ops.tuner_ops.release(fe);
+	if (fe->ops.release)
+		fe->ops.release(fe);
+}
+#endif
+EXPORT_SYMBOL(dvb_frontend_detach);
diff -urNp linux-2.6.22.1/drivers/media/dvb/dvb-core/dvb_frontend.h linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvb_frontend.h
--- linux-2.6.22.1/drivers/media/dvb/dvb-core/dvb_frontend.h	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/dvb-core/dvb_frontend.h	2007-07-28 01:17:12.000000000 +0200
@@ -8,6 +8,9 @@
  * Overhauled by Holger Waechtler
  * Kernel I2C stuff by Michael Hunold <hunold@convergence.de>
  *
+ * Overhauled for Silicon Tuners, Search Algorithms and multiprotocol
+ * support by 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 Lesser General Public License
  * as published by the Free Software Foundation; either version 2.1
@@ -45,6 +48,7 @@ struct dvb_frontend_tune_settings {
 	int step_size;
 	int max_drift;
 	struct dvb_frontend_parameters parameters;
+	struct dvbfe_params fe_params;
 };
 
 struct dvb_frontend;
@@ -61,6 +65,124 @@ struct dvb_tuner_info {
 	u32 bandwidth_step;
 };
 
+enum dvbfe_modcod {
+	DVBFE_MODCOD_DUMMY_PLFRAME	= 0,
+	DVBFE_MODCOD_QPSK_1_4,
+	DVBFE_MODCOD_QPSK_1_3,
+	DVBFE_MODCOD_QPSK_2_5,
+	DVBFE_MODCOD_QPSK_1_2,
+	DVBFE_MODCOD_QPSK_3_5,
+	DVBFE_MODCOD_QPSK_2_3,
+	DVBFE_MODCOD_QPSK_3_4,
+	DVBFE_MODCOD_QPSK_4_5,
+	DVBFE_MODCOD_QPSK_5_6,
+	DVBFE_MODCOD_QPSK_8_9,
+	DVBFE_MODCOD_QPSK_9_10,
+	DVBFE_MODCOD_8PSK_3_5,
+	DVBFE_MODCOD_8PSK_2_3,
+	DVBFE_MODCOD_8PSK_3_4,
+	DVBFE_MODCOD_8PSK_5_6,
+	DVBFE_MODCOD_8PSK_8_9,
+	DVBFE_MODCOD_8PSK_9_10,
+	DVBFE_MODCOD_16APSK_2_3,
+	DVBFE_MODCOD_16APSK_3_4,
+	DVBFE_MODCOD_16APSK_4_5,
+	DVBFE_MODCOD_16APSK_5_6,
+	DVBFE_MODCOD_16APSK_8_9,
+	DVBFE_MODCOD_16APSK_9_10,
+	DVBFE_MODCOD_32APSK_3_4,
+	DVBFE_MODCOD_32APSK_4_5,
+	DVBFE_MODCOD_32APSK_5_6,
+	DVBFE_MODCOD_32APSK_8_9,
+	DVBFE_MODCOD_32APSK_9_10,
+	DVBFE_MODCOD_RESERVED_1,
+	DVBFE_MODCOD_BPSK_1_3,
+	DVBFE_MODCOD_BPSK_1_4,
+	DVBFE_MODCOD_RESERVED_2
+};
+
+enum tuner_param {
+	DVBFE_TUNER_FREQUENCY		= (1 <<  0),
+	DVBFE_TUNER_TUNERSTEP		= (1 <<  1),
+	DVBFE_TUNER_IFFREQ		= (1 <<  2),
+	DVBFE_TUNER_BANDWIDTH		= (1 <<  3),
+	DVBFE_TUNER_REFCLOCK		= (1 <<  4),
+	DVBFE_TUNER_IQSENSE		= (1 <<  5),
+	DVBFE_TUNER_DUMMY		= (1 << 31)
+};
+
+/*
+ * ALGO_HW: (Hardware Algorithm)
+ * ----------------------------------------------------------------
+ * Devices that support this algorithm do everything in hardware
+ * and no software support is needed to handle them.
+ * Requesting these devices to LOCK is the only thing required,
+ * device is supposed to do everything in the hardware.
+ *
+ * ALGO_SW: (Software Algorithm)
+ * ----------------------------------------------------------------
+ * These are dumb devices, that require software to do everything
+ *
+ * ALGO_CUSTOM: (Customizable Agorithm)
+ * ----------------------------------------------------------------
+ * Devices having this algorithm can be customized to have specific
+ * algorithms in the frontend driver, rather than simply doing a
+ * software zig-zag. In this case the zigzag maybe hardware assisted
+ * or it maybe completely done in hardware. In all cases, usage of
+ * this algorithm, in conjunction with the search and track
+ * callbacks, utilizes the driver specific algorithm.
+ *
+ * ALGO_RECOVERY: (Recovery Algorithm)
+ * ----------------------------------------------------------------
+ * These devices has AUTO recovery capabilities from LOCK failure
+ */
+enum dvbfe_algo {
+	DVBFE_ALGO_HW			= (1 <<  0),
+	DVBFE_ALGO_SW			= (1 <<  1),
+	DVBFE_ALGO_CUSTOM		= (1 <<  2),
+	DVBFE_ALGO_RECOVERY		= (1 <<  31)
+};
+
+struct tuner_state {
+	u32 frequency;
+	u32 tunerstep;
+	u32 ifreq;
+	u32 bandwidth;
+	u32 iqsense;
+	u32 refclock;
+};
+
+/*
+ * search callback possible return status
+ *
+ * DVBFE_ALGO_SEARCH_SUCCESS
+ * The frontend search algorithm completed and returned succesfully
+ *
+ * DVBFE_ALGO_SEARCH_ASLEEP
+ * The frontend search algorithm is sleeping
+ *
+ * DVBFE_ALGO_SEARCH_FAILED
+ * The frontend search for a signal failed
+ *
+ * DVBFE_ALGO_SEARCH_INVALID
+ * The frontend search algorith was probably supplied with invalid
+ * parameters and the search is an invalid one
+ *
+ * DVBFE_ALGO_SEARCH_ERROR
+ * The frontend search algorithm failed due to some error
+ *
+ * DVBFE_ALGO_SEARCH_AGAIN
+ * The frontend search algorithm was requested to search again
+ */
+enum dvbfe_search {
+	DVBFE_ALGO_SEARCH_SUCCESS	= (1 <<  0),
+	DVBFE_ALGO_SEARCH_ASLEEP	= (1 <<  1),
+	DVBFE_ALGO_SEARCH_FAILED	= (1 <<  2),
+	DVBFE_ALGO_SEARCH_INVALID	= (1 <<  3),
+	DVBFE_ALGO_SEARCH_AGAIN		= (1 <<  4),
+	DVBFE_ALGO_SEARCH_ERROR		= (1 << 31),
+};
+
 struct dvb_tuner_ops {
 
 	struct dvb_tuner_info info;
@@ -81,10 +203,12 @@ struct dvb_tuner_ops {
 #define TUNER_STATUS_LOCKED 1
 	int (*get_status)(struct dvb_frontend *fe, u32 *status);
 
-	/** These are provided seperately from set_params in order to facilitate silicon
-	 * tuners which require sophisticated tuning loops, controlling each parameter seperately. */
-	int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
-	int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+	/**
+	 * These are provided seperately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter seperately.
+	 */
+	int (*set_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
+	int (*get_state)(struct dvb_frontend *fe, enum tuner_param param, struct tuner_state *state);
 };
 
 struct dvb_frontend_ops {
@@ -106,7 +230,7 @@ struct dvb_frontend_ops {
 		    int *delay,
 		    fe_status_t *status);
 	/* get frontend tuning algorithm from the module */
-	int (*get_frontend_algo)(struct dvb_frontend *fe);
+	enum dvbfe_algo (*get_frontend_algo)(struct dvb_frontend *fe);
 
 	/* these two are only used for the swzigzag code */
 	int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
@@ -131,6 +255,18 @@ struct dvb_frontend_ops {
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
 	int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
 
+	/* These callbacks are based on the superseding IOCTL's	*/
+	int (*set_params)(struct dvb_frontend *fe, struct dvbfe_params *fe_params);
+	int (*get_params)(struct dvb_frontend *fe, struct dvbfe_params *fe_params);
+	int (*get_info)(struct dvb_frontend *fe, struct dvbfe_info *fe_info);
+	int (*get_delsys)(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys);
+
+	/* These callbacks are for devices that implement their own
+	 * tuning algorithms, rather than a simple swzigzag
+	 */
+	enum dvbfe_search (*search)(struct dvb_frontend *fe, struct dvbfe_params *fe_params);
+	int (*track)(struct dvb_frontend *fe, struct dvbfe_params *fe_params);
+
 	struct dvb_tuner_ops tuner_ops;
 };
 
@@ -152,6 +288,7 @@ struct dvb_frontend {
 	void* tuner_priv;
 	void* frontend_priv;
 	void* sec_priv;
+	u32   legacy;
 };
 
 extern int dvb_register_frontend(struct dvb_adapter* dvb,
@@ -166,4 +303,18 @@ extern void dvb_frontend_reinitialise(st
 extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
 extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
 
+extern void decode_dvbs2_modcod(u32 modcod,
+				enum dvbfe_modulation *modulation,
+				enum dvbfe_fec *fec);
+
+
+extern int newapi_to_olddrv(struct dvbfe_params *params,
+			    struct dvb_frontend_parameters *p,
+			    enum dvbfe_delsys delsys);
+
+extern int olddrv_to_newapi(struct dvb_frontend *fe,
+			    struct dvbfe_params *params,
+			    struct dvb_frontend_parameters *p,
+			    enum fe_type fe_type);
+
 #endif
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/Kconfig linux-2.6.22.1-new/drivers/media/dvb/frontends/Kconfig
--- linux-2.6.22.1/drivers/media/dvb/frontends/Kconfig	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/Kconfig	2007-07-28 01:17:12.000000000 +0200
@@ -12,6 +12,23 @@ config DVB_FE_CUSTOMISE
 
 	  If unsure say N.
 
+comment "Multistandard (satellite) frontends"
+	depends on DVB_CORE
+
+config DVB_STB0899
+	tristate "STB0899 based"
+	depends on DVB_CORE
+	help
+	  A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want
+	  to support this demodulator based frontends
+
+config DVB_STB6100
+	tristate "STB6100 based tuners"
+	depends on DVB_CORE
+	help
+	  A Silicon tuner from ST used in conjunction with the STB0899
+	  demodulator. Say Y when you want to support this tuner.
+
 comment "DVB-S (satellite) frontends"
 	depends on DVB_CORE
 
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/Makefile linux-2.6.22.1-new/drivers/media/dvb/frontends/Makefile
--- linux-2.6.22.1/drivers/media/dvb/frontends/Makefile	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/Makefile	2007-07-28 01:17:12.000000000 +0200
@@ -3,9 +3,12 @@
 #
 
 EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/
+stb0899-objs = stb0899_drv.o stb0899_algo.o
 
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
 obj-$(CONFIG_DVB_STV0299) += stv0299.o
+obj-$(CONFIG_DVB_STB0899) += stb0899.o
+obj-$(CONFIG_DVB_STB6100) += stb6100.o
 obj-$(CONFIG_DVB_SP8870) += sp8870.o
 obj-$(CONFIG_DVB_CX22700) += cx22700.o
 obj-$(CONFIG_DVB_CX24110) += cx24110.o
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_algo.c linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_algo.c
--- linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_algo.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_algo.c	2007-07-28 01:17:12.000000000 +0200
@@ -0,0 +1,1580 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 "stb0899_drv.h"
+#include "stb0899_priv.h"
+#include "stb0899_reg.h"
+
+/*
+ * BinaryFloatDiv
+ * float division with integer
+ */
+static long BinaryFloatDiv(long n1, long n2, int precision)
+{
+	int i = 0;
+	long result = 0;
+
+	while (i <= precision) {
+		if (n1 < n2) {
+			result *= 2;
+			n1 *= 2;
+		} else {
+			result = result * 2 + 1;
+			n1 = (n1 - n2) * 2;
+		}
+		i++;
+	}
+
+	return result;
+}
+
+/*
+ * stb0899_calc_srate
+ * Compute symbol rate
+ */
+static u32 stb0899_calc_srate(u32 master_clk, u8 *sfr)
+{
+	u32 tmp, tmp2, mclk;
+
+	mclk  =  master_clk / 4096L; /* MasterClock * 10 / 2^20	*/
+	tmp  = (((u32) sfr[0] << 12) + ((u32) sfr[1] << 4)) / 16;
+
+	tmp *= mclk;
+	tmp /= 16;
+	tmp2 = ((u32) sfr[2] * mclk) / 256;
+	tmp += tmp2;
+
+	return tmp;
+}
+
+/*
+ * stb0899_get_srate
+ * Get the current symbol rate
+ */
+u32 stb0899_get_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 sfr[4];
+
+	stb0899_read_regs(state, STB0899_SFRH, sfr, 3);
+
+	return stb0899_calc_srate(internal->master_clk, sfr);
+}
+
+/*
+ * stb0899_set_srate
+ * Set symbol frequency
+ * MasterClock: master clock frequency (hz)
+ * SymbolRate: symbol rate (bauds)
+ * return symbol frequency
+ */
+static u32 stb0899_set_srate(struct stb0899_state *state, u32 master_clk, u32 srate)
+{
+	u32 tmp, tmp_up, srate_up;
+	u8 sfr_up[3], sfr[3];
+
+	srate_up = srate;
+	dprintk(state->verbose, FE_DEBUG, 1, "-->");
+	/*
+	 * in order to have the maximum precision, the symbol rate entered into
+	 * the chip is computed as the closest value of the "true value".
+	 * In this purpose, the symbol rate value is rounded (1 is added on the bit
+	 * below the LSB )
+	 */
+	srate_up += (srate_up * 3) / 100;
+
+	tmp = BinaryFloatDiv(srate, master_clk, 20);
+	tmp_up = BinaryFloatDiv(srate_up, master_clk, 20);
+
+	sfr_up[0] = (tmp_up >> 12) & 0xff;
+	sfr_up[1] = (tmp_up >>  4) & 0xff;
+	sfr_up[2] =  tmp_up & 0x0f;
+
+	sfr[0] = (tmp >> 12) & 0xff;
+	sfr[1] = (tmp >>  4) & 0xff;
+	sfr[2] =  tmp & 0x0f;
+
+	stb0899_write_regs(state, STB0899_SFRUPH, sfr_up, 3);
+	stb0899_write_regs(state, STB0899_SFRH, sfr, 3);
+
+	return srate;
+}
+
+/*
+ * stb0899_calc_loop_time
+ * Compute the amount of time needed by the timing loop to lock
+ * SymbolRate: Symbol rate
+ * return: timing loop time constant (ms)
+ */
+static long stb0899_calc_loop_time(long srate)
+{
+	if (srate > 0)
+		return (100000 / (srate / 1000));
+	else
+		return 0;
+}
+
+/*
+ * stb0899_calc_derot_time
+ * Compute the amount of time needed by the derotator to lock
+ * SymbolRate: Symbol rate
+ * return: derotator time constant (ms)
+ */
+static long stb0899_calc_derot_time(long srate)
+{
+	if (srate > 0)
+		return (100000 / (srate / 1000));
+	else
+		return 0;
+}
+
+/*
+ * stb0899_carr_width
+ * Compute the width of the carrier
+ * return: width of carrier (kHz or Mhz)
+ */
+long stb0899_carr_width(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	return (internal->srate + (internal->srate * internal->rolloff) / 100);
+}
+
+/*
+ * stb0899_first_subrange
+ * Compute the first subrange of the search
+ */
+static void stb0899_first_subrange(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_params *params		= &state->params;
+	struct stb0899_config *config		=  state->config;
+
+	int range = 0;
+	u32 bandwidth = 0;
+
+	if (config->tuner_get_bandwidth) {
+		config->tuner_get_bandwidth(&state->frontend, &bandwidth);
+		range = bandwidth - stb0899_carr_width(state) / 2;
+	}
+
+	if (range > 0)
+		internal->sub_range = MIN(internal->srch_range, range);
+	else
+		internal->sub_range = 0;
+
+	internal->freq = params->freq;
+	internal->tuner_offst = 0L;
+	internal->sub_dir = 1;
+}
+
+/*
+ * stb0899_check_tmg
+ * check for timing lock
+ * internal.Ttiming: time to wait for loop lock
+ */
+static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	int lock, timing;
+	u8 reg;
+
+	msleep(internal->t_timing);
+
+	reg = stb0899_read_reg(state, STB0899_RTF);
+	STB0899_SETFIELD_VAL(RTF_TIMING_LOOP_FREQ, reg, 0xf2);
+	stb0899_write_reg(state, STB0899_RTF, reg);
+	reg = stb0899_read_reg(state, STB0899_TLIR);
+	lock = STB0899_GETFIELD(TLIR_TMG_LOCK_IND, reg);
+	timing = stb0899_read_reg(state, STB0899_RTF);
+
+	if (lock >= 42) {
+		if ((lock > 48) && (timing >= 110)) {
+			internal->status = ANALOGCARRIER;
+			dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !");
+		} else {
+			internal->status = TIMINGOK;
+			dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK !");
+		}
+	} else {
+		internal->status = NOTIMING;
+		dprintk(state->verbose, FE_DEBUG, 1, "-->NO TIMING !");
+	}
+	return internal->status;
+}
+
+/*
+ * stb0899_search_tmg
+ * perform a fs/2 zig-zag to find timing
+ */
+static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	short int derot_step, derot_freq = 0, derot_limit, next_loop = 3;
+	int index = 0;
+	u8 cfr[2];
+
+	internal->status = NOTIMING;
+
+	/* timing loop computation & symbol rate optimisation	*/
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_step = (params->srate / 2L) / internal->mclk;
+
+	while ((stb0899_check_tmg(state) != TIMINGOK) && next_loop) {
+		index++;
+		derot_freq += index * internal->direction * derot_step;	/* next derot zig zag position	*/
+
+		if (ABS(derot_freq) > derot_limit)
+			next_loop--;
+
+		if (next_loop) {
+			STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+			STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+			stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency		*/
+		}
+		internal->direction = -internal->direction;	/* Change zigzag direction		*/
+	}
+
+	if (internal->status == TIMINGOK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency		*/
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "------->TIMING OK ! Derot Freq = %d", internal->derot_freq);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_carrier
+ * Check for carrier found
+ */
+static enum stb0899_status stb0899_check_carrier(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 reg;
+
+	msleep(internal->t_derot); /* wait for derotator ok	*/
+
+	reg = stb0899_read_reg(state, STB0899_CFD);
+	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+	stb0899_write_reg(state, STB0899_RTF, reg);
+
+	reg = stb0899_read_reg(state, STB0899_DSTATUS);
+	dprintk(state->verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg);
+	if (STB0899_GETFIELD(CARRIER_FOUND, reg)) {
+		internal->status = CARRIEROK;
+		dprintk(state->verbose, FE_DEBUG, 1, "-------------> CARRIEROK !");
+	} else {
+		internal->status = NOCARRIER;
+		dprintk(state->verbose, FE_DEBUG, 1, "-------------> NOCARRIER !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_search_carrier
+ * Search for a QPSK carrier with the derotator
+ */
+static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3;
+	int index = 0;
+	u8 cfr[2];
+	u8 reg;
+
+	internal->status = NOCARRIER;
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_freq = internal->derot_freq;
+
+	reg = stb0899_read_reg(state, STB0899_CFD);
+	STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+	stb0899_write_reg(state, STB0899_RTF, reg);
+
+	do {
+		dprintk(state->verbose, FE_DEBUG, 1, "Derot Freq=%d, mclk=%d", derot_freq, internal->mclk);
+		if (stb0899_check_carrier(state) == NOCARRIER) {
+			index++;
+			last_derot_freq = derot_freq;
+			derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position	*/
+
+			if(ABS(derot_freq) > derot_limit)
+				next_loop--;
+
+			if (next_loop) {
+				reg = stb0899_read_reg(state, STB0899_CFD);
+				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+				stb0899_write_reg(state, STB0899_RTF, reg);
+
+				STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+				STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+				stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency	*/
+			}
+		}
+
+		internal->direction = -internal->direction; /* Change zigzag direction	*/
+	} while ((internal->status != CARRIEROK) && next_loop);
+
+	if (internal->status == CARRIEROK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency	*/
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "----> CARRIER OK !, Derot Freq=%d", internal->derot_freq);
+	} else {
+		internal->derot_freq = last_derot_freq;
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_data
+ * Check for data found
+ */
+static enum stb0899_status stb0899_check_data(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	int lock = 0, index = 0, dataTime = 500, loop;
+	u8 reg;
+
+	internal->status = NODATA;
+
+	/* RESET FEC	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESACS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+	msleep(1);
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESACS, reg, 0);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	if (params->srate <= 2000000)
+		dataTime = 2000;
+	else if (params->srate <= 5000000)
+		dataTime = 1500;
+	else if (params->srate <= 15000000)
+		dataTime = 1000;
+	else
+		dataTime = 500;
+
+	stb0899_write_reg(state, STB0899_DSTATUS2, 0x00); /* force search loop	*/
+	while (1) {
+		/* WARNING! VIT LOCKED has to be tested before VIT_END_LOOOP	*/
+		reg = stb0899_read_reg(state, STB0899_VSTATUS);
+		lock = STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg);
+		loop = STB0899_GETFIELD(VSTATUS_END_LOOPVIT, reg);
+
+		if (lock || loop || (index > dataTime))
+			break;
+		index++;
+	}
+
+	if (lock) {	/* DATA LOCK indicator	*/
+		internal->status = DATAOK;
+		dprintk(state->verbose, FE_DEBUG, 1, "-----------------> DATA OK !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_search_data
+ * Search for a QPSK carrier with the derotator
+ */
+static enum stb0899_status stb0899_search_data(struct stb0899_state *state)
+{
+	short int derot_freq, derot_step, derot_limit, next_loop = 3;
+	u8 cfr[2];
+	u8 reg;
+	int index = 1;
+
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	derot_step = (params->srate / 4L) / internal->mclk;
+	derot_limit = (internal->sub_range / 2L) / internal->mclk;
+	derot_freq = internal->derot_freq;
+
+	do {
+		if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) {
+
+			derot_freq += index * internal->direction * derot_step;	/* next zig zag derotator position	*/
+			if (ABS(derot_freq) > derot_limit)
+				next_loop--;
+
+			if (next_loop) {
+				dprintk(state->verbose, FE_DEBUG, 1, "Derot freq=%d, mclk=%d", derot_freq, internal->mclk);
+				reg = stb0899_read_reg(state, STB0899_CFD);
+				STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+				stb0899_write_reg(state, STB0899_RTF, reg);
+
+				STB0899_SETFIELD_VAL(CFRM, cfr[0], MSB(state->config->inversion * derot_freq));
+				STB0899_SETFIELD_VAL(CFRL, cfr[1], LSB(state->config->inversion * derot_freq));
+				stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* derotator frequency	*/
+
+				stb0899_check_carrier(state);
+				index++;
+			}
+		}
+		internal->direction = -internal->direction; /* change zig zag direction		*/
+	} while ((internal->status != DATAOK) && next_loop);
+
+	if (internal->status == DATAOK) {
+		stb0899_read_regs(state, STB0899_CFRM, cfr, 2); /* get derotator frequency	*/
+		internal->derot_freq = state->config->inversion * MAKEWORD16(cfr[0], cfr[1]);
+		dprintk(state->verbose, FE_DEBUG, 1, "------> DATAOK ! Derot Freq=%d", internal->derot_freq);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_check_range
+ * check if the found frequency is in the correct range
+ */
+static enum stb0899_status stb0899_check_range(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	int range_offst, tp_freq;
+
+	range_offst = internal->srch_range / 2000;
+	tp_freq = internal->freq + (internal->derot_freq * internal->mclk) / 1000;
+
+	if ((tp_freq >= params->freq - range_offst) && (tp_freq <= params->freq + range_offst)) {
+		internal->status = RANGEOK;
+		dprintk(state->verbose, FE_DEBUG, 1, "----> RANGEOK !");
+	} else {
+		internal->status = OUTOFRANGE;
+		dprintk(state->verbose, FE_DEBUG, 1, "----> OUT OF RANGE !");
+	}
+
+	return internal->status;
+}
+
+/*
+ * NextSubRange
+ * Compute the next subrange of the search
+ */
+static void next_sub_range(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_params *params = &state->params;
+
+	long old_sub_range;
+
+	if (internal->sub_dir > 0) {
+		old_sub_range = internal->sub_range;
+		internal->sub_range = MIN((internal->srch_range / 2) -
+					  (internal->tuner_offst + internal->sub_range / 2),
+					   internal->sub_range);
+
+		if (internal->sub_range < 0)
+			internal->sub_range = 0;
+
+		internal->tuner_offst += (old_sub_range + internal->sub_range) / 2;
+	}
+
+	internal->freq = params->freq + (internal->sub_dir * internal->tuner_offst) / 1000;
+	internal->sub_dir = -internal->sub_dir;
+}
+
+/*
+ * stb0899_dvbs_algo
+ * Search for a signal, timing, carrier and data for a
+ * given frequency in a given range
+ */
+enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state)
+{
+	struct stb0899_params *params		= &state->params;
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u8 bclc, reg;
+	u8 cfr[1];
+	u8 eq_const[10];
+	s32 clnI = 3;
+	u32 bandwidth = 0;
+	s32 retry = 0;
+
+	/* BETA values rated @ 99MHz	*/
+	s32 betaTab[5][4] = {
+	       /*  5   10   20   30MBps */
+		{ 37,  34,  32,  31 }, /* QPSK 1/2	*/
+		{ 37,  35,  33,  31 }, /* QPSK 2/3	*/
+		{ 37,  35,  33,  31 }, /* QPSK 3/4	*/
+		{ 37,  36,  33,	 32 }, /* QPSK 5/6	*/
+		{ 37,  36,  33,	 32 }  /* QPSK 7/8	*/
+	};
+
+	internal->direction = 1;
+
+	stb0899_set_srate(state, internal->master_clk, params->srate);
+	/* Carrier loop optimization versus symbol rate for acquisition*/
+	if (params->srate <= 5000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0x89);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x1c);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 0;
+	} else if (params->srate <= 15000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0xc9);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x22);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 1;
+	} else if(params->srate <= 25000000) {
+		stb0899_write_reg(state, STB0899_ACLC, 0x89);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x27);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 2;
+	} else {
+		stb0899_write_reg(state, STB0899_ACLC, 0xc8);
+		bclc = stb0899_read_reg(state, STB0899_BCLC);
+		STB0899_SETFIELD_VAL(BETA, bclc, 0x29);
+		stb0899_write_reg(state, STB0899_BCLC, bclc);
+		clnI = 3;
+	}
+
+	dprintk(state->verbose, FE_DEBUG, 1, "Set the timing loop to acquisition");
+	/* Set the timing loop to acquisition	*/
+	stb0899_write_reg(state, STB0899_RTC, 0x46);
+	stb0899_write_reg(state, STB0899_CFD, 0xee);
+
+	/* !! WARNING !!
+	 * Do not read any status variables while acquisition,
+	 * If any needed, read before the acquisition starts
+	 * querying status while acquiring causes the
+	 * acquisition to go bad and hence no locks.
+	 */
+	dprintk(state->verbose, FE_DEBUG, 1, "Derot Percent=%d Srate=%d mclk=%d",
+		internal->derot_percent, params->srate, internal->mclk);
+
+	/* Initial calculations	*/
+	internal->derot_step = internal->derot_percent * (params->srate / 1000L) / internal->mclk; /* DerotStep/1000 * Fsymbol	*/
+	internal->t_timing = stb0899_calc_loop_time(params->srate);
+	internal->t_derot = stb0899_calc_derot_time(params->srate);
+	internal->t_data = 500;
+
+	dprintk(state->verbose, FE_DEBUG, 1, "RESET stream merger");
+	/* RESET Stream merger	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	/*
+	 * Set KDIVIDER to an intermediate value between
+	 * 1/2 and 7/8 for acquisition
+	 */
+	reg = stb0899_read_reg(state, STB0899_DEMAPVIT);
+	STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 60);
+	stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+
+	stb0899_write_reg(state, STB0899_EQON, 0x01); /* Equalizer OFF while acquiring	*/
+	stb0899_write_reg(state, STB0899_VITSYNC, 0x19);
+	
+	stb0899_first_subrange(state);
+	do {
+	    retry = 0;
+	    do
+	    {
+		/* Initialisations	*/
+		cfr[0] = cfr[1] = 0;
+		stb0899_write_regs(state, STB0899_CFRM, cfr, 2); /* RESET derotator frequency	*/
+
+		reg = stb0899_read_reg(state, STB0899_RTF);
+		STB0899_SETFIELD_VAL(RTF_TIMING_LOOP_FREQ, reg, 0);
+		stb0899_write_reg(state, STB0899_RTF, reg);
+		reg = stb0899_read_reg(state, STB0899_CFD);
+		STB0899_SETFIELD_VAL(CFD_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_RTF, reg);
+
+		internal->derot_freq = 0;
+		internal->status = NOAGC1;
+
+		/* Move tuner to frequency	*/
+		dprintk(state->verbose, FE_DEBUG, 1, "Tuner set frequency");
+		if (state->config->tuner_set_frequency)
+			state->config->tuner_set_frequency(&state->frontend, internal->freq);
+
+		msleep(100);
+
+		if (state->config->tuner_get_frequency)
+			state->config->tuner_get_frequency(&state->frontend, &internal->freq);
+
+		msleep(internal->t_agc1 + internal->t_agc2 + internal->t_timing); /* AGC1, AGC2 and timing loop	*/
+		dprintk(state->verbose, FE_DEBUG, 1, "current derot freq=%d", internal->derot_freq);
+		internal->status = AGC1OK;
+
+		/* There is signal in the band	*/
+		if (config->tuner_get_bandwidth)
+			config->tuner_get_bandwidth(&state->frontend, &bandwidth);
+		if (params->srate <= bandwidth / 2)
+			stb0899_search_tmg(state); /* For low rates (SCPC)	*/
+		else
+			stb0899_check_tmg(state); /* For high rates (MCPC)	*/
+
+		if (internal->status == TIMINGOK) {
+			dprintk(state->verbose, FE_DEBUG, 1,
+				"TIMING OK ! Derot freq=%d, mclk=%d",
+				internal->derot_freq, internal->mclk);
+
+			if (stb0899_search_carrier(state) == CARRIEROK) {	/* Search for carrier	*/
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"CARRIER OK ! Derot freq=%d, mclk=%d",
+					internal->derot_freq, internal->mclk);
+
+				if (stb0899_search_data(state) == DATAOK) {	/* Check for data	*/
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"DATA OK ! Derot freq=%d, mclk=%d",
+						internal->derot_freq, internal->mclk);
+
+					if (stb0899_check_range(state) == RANGEOK) {
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"RANGE OK ! derot freq=%d, mclk=%d",
+							internal->derot_freq, internal->mclk);
+
+						internal->freq = params->freq + ((internal->derot_freq * internal->mclk) / 1000);
+						reg = stb0899_read_reg(state, STB0899_PLPARM);
+						internal->fecrate = STB0899_GETFIELD(VITCURPUN, reg);
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"freq=%d, internal resultant freq=%d",
+							params->freq, internal->freq);
+
+						dprintk(state->verbose, FE_DEBUG, 1,
+							"internal puncture rate=%d",
+							internal->fecrate);
+					}
+				}
+			}
+	        }
+	    }
+	    while ( ++retry < 5 && (internal->status != RANGEOK) );
+		
+	    if (internal->status != RANGEOK)
+			next_sub_range(state);
+
+	} while (internal->sub_range && internal->status != RANGEOK);
+
+	/* Set the timing loop to tracking	*/
+	stb0899_write_reg(state, STB0899_RTC, 0x33);
+	stb0899_write_reg(state, STB0899_CFD, 0xf7);
+	reg = 0;
+	/* if locked and range ok, set Kdiv	*/
+	if (internal->status == RANGEOK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "Locked & Range OK !");
+
+		stb0899_write_reg(state, STB0899_EQON, 0x41);		/* Equalizer OFF while acquiring	*/
+		stb0899_write_reg(state, STB0899_VITSYNC, 0x39);	/* SN to b'11 for acquisition		*/
+
+		/*
+		 * Carrier loop optimization versus
+		 * symbol Rate/Puncture Rate for Tracking
+		 */
+		switch (internal->fecrate) {
+		case STB0899_FEC_1_2:		/* 13	*/
+			STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 0x1a);
+			stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[0][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_2_3:		/* 18	*/
+			STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 44);
+			stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[1][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_3_4:		/* 21	*/
+			STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 60);
+			stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[2][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_5_6:		/* 24	*/
+			STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 75);
+			stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[3][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		case STB0899_FEC_6_7:		/* 25	*/
+			STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 88);
+			stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+			stb0899_write_reg(state, STB0899_ACLC, 0x88);
+			stb0899_write_reg(state, STB0899_BCLC, 0x9a);
+			break;
+		case STB0899_FEC_7_8:		/* 26	*/
+			STB0899_SETFIELD_VAL(DEMAPVIT_KDIVIDER, reg, 94);
+			stb0899_write_reg(state, STB0899_DEMAPVIT, reg);
+			STB0899_SETFIELD_VAL(BETA, reg, betaTab[4][clnI]);
+			stb0899_write_reg(state, STB0899_BCLC, reg);
+			break;
+		default:
+			dprintk(state->verbose, FE_DEBUG, 1, "Unsupported Puncture Rate");
+			break;
+		}
+		/* release stream merger RESET	*/
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESRS, reg, 0);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+#if 1
+		/* TODO: Only for the moment and for TT3200 */
+		if (   ((internal->freq > 1870000) && (internal->freq < 1890000))
+		    || ((internal->freq > 1570000) && (internal->freq < 1590000))
+		    || ((internal->freq > 1500000) && (internal->freq < 1520000))
+		   )
+		{
+		    /* do not disable carrier detector	*/
+		    /* for special frequencies (ProSieben, RTL ...) */
+		    printk("%s: special for frequency=%d\n",__func__,internal->freq);
+		}
+		else
+#endif
+		{
+		    /* disable carrier detector	*/
+		    reg = stb0899_read_reg(state, STB0899_CFD);
+		    STB0899_SETFIELD_VAL(CFD_ON, reg, 0);
+		    stb0899_write_reg(state, STB0899_RTF, reg);
+		}
+		stb0899_read_regs(state, STB0899_EQUAI1, eq_const, 10);
+	}
+
+	return internal->status;
+}
+
+/*
+ * stb0899_dvbs2_config_uwp
+ * Configure UWP state machine
+ */
+static void stb0899_dvbs2_config_uwp(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+	u32 uwp1, uwp2, uwp3, reg;
+
+	uwp1 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
+	uwp2 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL2);
+	uwp3 = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL3);
+
+	STB0899_SETFIELD_VAL(UWP_ESN0_AVE, uwp1, config->esno_ave);
+	STB0899_SETFIELD_VAL(UWP_ESN0_QUANT, uwp1, config->esno_quant);
+	STB0899_SETFIELD_VAL(UWP_TH_SOF, uwp1, config->uwp_threshold_sof);
+
+	STB0899_SETFIELD_VAL(FE_COARSE_TRK, uwp2, internal->av_frame_coarse);
+	STB0899_SETFIELD_VAL(FE_FINE_TRK, uwp2, internal->av_frame_fine);
+	STB0899_SETFIELD_VAL(UWP_MISS_TH, uwp2, config->miss_threshold);
+
+	STB0899_SETFIELD_VAL(UWP_TH_ACQ, uwp3, config->uwp_threshold_acq);
+	STB0899_SETFIELD_VAL(UWP_TH_TRACK, uwp3, config->uwp_threshold_track);
+
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL1, STB0899_OFF0_UWP_CNTRL1, uwp1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL2, STB0899_OFF0_UWP_CNTRL2, uwp2);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_UWP_CNTRL3, STB0899_OFF0_UWP_CNTRL3, uwp3);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, SOF_SRCH_TO);
+	STB0899_SETFIELD_VAL(SOF_SEARCH_TIMEOUT, reg, config->sof_search_timeout);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_SOF_SRCH_TO, STB0899_OFF0_SOF_SRCH_TO, reg);
+}
+
+/*
+ * stb0899_dvbs2_config_csm_auto
+ * Set CSM to AUTO mode
+ */
+static void stb0899_dvbs2_config_csm_auto(struct stb0899_state *state)
+{
+	u32 reg;
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+	STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, reg);
+}
+
+long Log2Int(int number)
+{
+	int i;
+
+	i = 0;
+	while ((1 << i) <= ABS(number))
+		i++;
+
+	if (number == 0)
+		i = 1;
+
+	return i - 1;
+}
+
+/*
+ * stb0899_dvbs2_calc_srate
+ * compute BTR_NOM_FREQ for the symbol rate
+ */
+static u32 stb0899_dvbs2_calc_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u32 dec_ratio, dec_rate, decim, remain, intval, btr_nom_freq;
+	u32 master_clk, srate;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+	decim = 1 << dec_rate;
+	master_clk = internal->master_clk / 1000;
+	srate = internal->srate / 1000;
+
+	if (decim <= 4) {
+		intval = (decim * (1 << (config->btr_nco_bits - 1))) / master_clk;
+		remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
+	} else {
+		intval = (1 << (config->btr_nco_bits - 1)) / (master_clk / 100) * decim / 100;
+		remain = (decim * (1 << (config->btr_nco_bits - 1))) % master_clk;
+	}
+	btr_nom_freq = (intval * srate) + ((remain * srate) / master_clk);
+
+	return btr_nom_freq;
+}
+
+/*
+ * stb0899_dvbs2_calc_dev
+ * compute the correction to be applied to symbol rate
+ */
+static u32 stb0899_dvbs2_calc_dev(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u32 dec_ratio, correction, master_clk, srate;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+
+	master_clk = internal->master_clk / 1000;	/* for integer Caculation*/
+	srate = internal->srate / 1000;	/* for integer Caculation*/
+	correction = (512 * master_clk) / (2 * dec_ratio * srate);
+
+	return	correction;
+}
+
+/*
+ * stb0899_dvbs2_set_srate
+ * Set DVBS2 symbol rate
+ */
+static void stb0899_dvbs2_set_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+
+	u32 dec_ratio, dec_rate, win_sel, decim, f_sym, btr_nom_freq;
+	u32 correction, freq_adj, band_lim, decim_cntrl, reg;
+	u8 anti_alias;
+
+	/*set decimation to 1*/
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+
+	win_sel = 0;
+	if (dec_rate >= 5)
+		win_sel = dec_rate - 4;
+
+	decim = (1 << dec_rate);
+	/* (FSamp/Fsymbol *100) for integer Caculation */
+	f_sym = internal->master_clk / ((decim * internal->srate) / 1000);
+
+	if (f_sym <= 2250)	/* don't band limit signal going into btr block*/
+		band_lim = 1;
+	else
+		band_lim = 0;	/* band limit signal going into btr block*/
+
+	decim_cntrl = ((win_sel << 3) & 0x18) + ((band_lim << 5) & 0x20) + (dec_rate & 0x7);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DECIM_CNTRL, STB0899_OFF0_DECIM_CNTRL, decim_cntrl);
+
+	if (f_sym <= 3450)
+		anti_alias = 0;
+	else if (f_sym <= 4250)
+		anti_alias = 1;
+	else
+		anti_alias = 2;
+
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ANTI_ALIAS_SEL, STB0899_OFF0_ANTI_ALIAS_SEL, anti_alias);
+	btr_nom_freq = stb0899_dvbs2_calc_srate(state);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_NOM_FREQ, STB0899_OFF0_BTR_NOM_FREQ, btr_nom_freq);
+
+	correction = stb0899_dvbs2_calc_dev(state);
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
+	STB0899_SETFIELD_VAL(BTR_FREQ_CORR, reg, correction);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
+
+	/* scale UWP+CSM frequency to sample rate*/
+	freq_adj =  internal->srate / (internal->master_clk / 4096);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_FREQ_ADJ_SCALE, STB0899_OFF0_FREQ_ADJ_SCALE, freq_adj);
+}
+
+/*
+ * stb0899_dvbs2_set_btr_loopbw
+ * set bit timing loop bandwidth as a percentage of the symbol rate
+ */
+static void stb0899_dvbs2_set_btr_loopbw(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal	= &state->internal;
+	struct stb0899_config *config		= state->config;
+
+	u32 sym_peak = 23, zeta = 707, loopbw_percent = 60;
+	s32 dec_ratio, dec_rate, k_btr1_rshft, k_btr1, k_btr0_rshft;
+	s32 k_btr0, k_btr2_rshft, k_direct_shift, k_indirect_shift;
+	u32 decim, K, wn, k_direct, k_indirect;
+	u32 reg;
+
+	dec_ratio = (internal->master_clk * 2) / (5 * internal->srate);
+	dec_ratio = (dec_ratio == 0) ? 1 : dec_ratio;
+	dec_rate = Log2Int(dec_ratio);
+	decim = (1 << dec_rate);
+
+	sym_peak *= 576000;
+	K = (1 << config->btr_nco_bits) / (internal->master_clk / 1000);
+	K *= (internal->srate / 1000000) * decim; /*k=k 10^-8*/
+
+	if (K != 0) {
+		K = sym_peak / K;
+		wn = (4 * zeta * zeta) + 1000000;
+		wn = (2 * (loopbw_percent * 1000) * 40 * zeta) /wn;  /*wn =wn 10^-8*/
+
+		k_indirect = (wn * wn) / K;
+		k_indirect = k_indirect;	  /*kindirect = kindirect 10^-6*/
+		k_direct   = (2 * wn * zeta) / K;	/*kDirect = kDirect 10^-2*/
+		k_direct  *= 100;
+
+		k_direct_shift = Log2Int(k_direct) - Log2Int(10000) - 2;
+		k_btr1_rshft = (-1 * k_direct_shift) + config->btr_gain_shift_offset;
+		k_btr1 = k_direct / (1 << k_direct_shift);
+		k_btr1 /= 10000;
+
+		k_indirect_shift = Log2Int(k_indirect + 15) - 20 /*- 2*/;
+		k_btr0_rshft = (-1 * k_indirect_shift) + config->btr_gain_shift_offset;
+		k_btr0 = k_indirect * (1 << (-k_indirect_shift));
+		k_btr0 /= 1000000;
+
+		k_btr2_rshft = 0;
+		if (k_btr0_rshft > 15) {
+			k_btr2_rshft = k_btr0_rshft - 15;
+			k_btr0_rshft = 15;
+		}
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_LOOP_GAIN);
+		STB0899_SETFIELD_VAL(KBTR0_RSHFT, reg, k_btr0_rshft);
+		STB0899_SETFIELD_VAL(KBTR0, reg, k_btr0);
+		STB0899_SETFIELD_VAL(KBTR1_RSHFT, reg, k_btr1_rshft);
+		STB0899_SETFIELD_VAL(KBTR1, reg, k_btr1);
+		STB0899_SETFIELD_VAL(KBTR2_RSHFT, reg, k_btr2_rshft);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, reg);
+	} else
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_LOOP_GAIN, STB0899_OFF0_BTR_LOOP_GAIN, 0xc4c4f);
+}
+
+/*
+ * stb0899_dvbs2_set_carr_freq
+ * set nominal frequency for carrier search
+ */
+static void stb0899_dvbs2_set_carr_freq(struct stb0899_state *state, s32 carr_freq, u32 master_clk)
+{
+	struct stb0899_config *config = state->config;
+	s32 crl_nom_freq;
+	u32 reg;
+
+	crl_nom_freq = (1 << config->crl_nco_bits) / master_clk;
+	crl_nom_freq *= carr_freq;
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+	STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, crl_nom_freq);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, reg);
+}
+
+/*
+ * stb0899_dvbs2_init_calc
+ * Initialize DVBS2 UWP, CSM, carrier and timing loops
+ */
+static void stb0899_dvbs2_init_calc(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	s32 steps, step_size;
+	u32 range, reg;
+
+	/* config uwp and csm */
+	stb0899_dvbs2_config_uwp(state);
+	stb0899_dvbs2_config_csm_auto(state);
+
+	/* initialize BTR	*/
+	stb0899_dvbs2_set_srate(state);
+	stb0899_dvbs2_set_btr_loopbw(state);
+
+	if (internal->srate / 1000000 >= 15)
+		step_size = (1 << 17) / 5;
+	else if (internal->srate / 1000000 >= 10)
+		step_size = (1 << 17) / 7;
+	else if (internal->srate / 1000000 >= 5)
+		step_size = (1 << 17) / 10;
+	else
+		step_size = (1 << 17) / 4;
+
+	range = internal->srch_range / 1000000;
+	steps = (10 * range * (1 << 17)) / (step_size * (internal->srate / 1000000));
+	steps = (steps + 6) / 10;
+	steps = (steps == 0) ? 1 : steps;
+	if (steps % 2 == 0)
+		stb0899_dvbs2_set_carr_freq(state, internal->center_freq -
+					   (internal->step_size * (internal->srate / 20000000)),
+					   (internal->master_clk) / 1000000);
+	else
+		stb0899_dvbs2_set_carr_freq(state, internal->center_freq, (internal->master_clk) / 1000000);
+
+	/*Set Carrier Search params (zigzag, num steps and freq step size*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, ACQ_CNTRL2);
+	STB0899_SETFIELD_VAL(ZIGZAG, reg, 1);
+	STB0899_SETFIELD_VAL(NUM_STEPS, reg, steps);
+	STB0899_SETFIELD_VAL(FREQ_STEPSIZE, reg, step_size);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQ_CNTRL2, STB0899_OFF0_ACQ_CNTRL2, reg);
+}
+
+/*
+ * stb0899_dvbs2_btr_init
+ * initialize the timing loop
+ */
+static void stb0899_dvbs2_btr_init(struct stb0899_state *state)
+{
+	u32 reg;
+
+	/* set enable BTR loopback	*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_CNTRL);
+	STB0899_SETFIELD_VAL(INTRP_PHS_SENSE, reg, 1);
+	STB0899_SETFIELD_VAL(BTR_ERR_ENA, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_CNTRL, STB0899_OFF0_BTR_CNTRL, reg);
+
+	/* fix btr freq accum at 0	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x10000000);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_FREQ_INIT, STB0899_OFF0_BTR_FREQ_INIT, 0x00000000);
+
+	/* fix btr freq accum at 0	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x10000000);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_BTR_PHS_INIT, STB0899_OFF0_BTR_PHS_INIT, 0x00000000);
+}
+
+/*
+ * stb0899_dvbs2_reacquire
+ * trigger a DVB-S2 acquisition
+ */
+static void stb0899_dvbs2_reacquire(struct stb0899_state *state)
+{
+	u32 reg = 0;
+
+	/* demod soft reset	*/
+	STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
+
+	/*Reset Timing Loop	*/
+	stb0899_dvbs2_btr_init(state);
+
+	/* reset Carrier loop	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, (1 << 30));
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_FREQ_INIT, STB0899_OFF0_CRL_FREQ_INIT, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_LOOP_GAIN, STB0899_OFF0_CRL_LOOP_GAIN, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, (1 << 30));
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_PHS_INIT, STB0899_OFF0_CRL_PHS_INIT, 0);
+
+	/*release demod soft reset	*/
+	reg = 0;
+	STB0899_SETFIELD_VAL(DVBS2_RESET, reg, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_RESET_CNTRL, STB0899_OFF0_RESET_CNTRL, reg);
+
+	/* start acquisition process	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_ACQUIRE_TRIG, STB0899_OFF0_ACQUIRE_TRIG, 1);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_LOCK_LOST, STB0899_OFF0_LOCK_LOST, 0);
+
+	/* equalizer Init	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 1);
+
+	/*Start equilizer	*/
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQUALIZER_INIT, STB0899_OFF0_EQUALIZER_INIT, 0);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+	STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0);
+	STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 0);
+	STB0899_SETFIELD_VAL(EQ_DELAY, reg, 0x05);
+	STB0899_SETFIELD_VAL(EQ_ADAPT_MODE, reg, 0x01);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+
+	/* RESET Packet delineator	*/
+	stb0899_write_reg(state, STB0899_PDELCTRL, 0x4a);
+}
+
+/*
+ * stb0899_dvbs2_get_dmd_status
+ * get DVB-S2 Demod LOCK status
+ */
+static enum stb0899_status stb0899_dvbs2_get_dmd_status(struct stb0899_state *state, int timeout)
+{
+	int time = -10, lock = 0, uwp, csm;
+	u32 reg;
+
+	do {
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS);
+		dprintk(state->verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg);
+		if (STB0899_GETFIELD(IF_AGC_LOCK, reg))
+			dprintk(state->verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !");
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
+		dprintk(state->verbose, FE_DEBUG, 1, "----------->DMD STAT2=[0x%02x]", reg);
+		uwp = STB0899_GETFIELD(UWP_LOCK, reg);
+		csm = STB0899_GETFIELD(CSM_LOCK, reg);
+		if (uwp && csm)
+			lock = 1;
+
+		time += 10;
+		msleep(10);
+
+	} while ((!lock) && (time <= timeout));
+
+	if (lock) {
+		dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 LOCK !");
+		return DVBS2_DEMOD_LOCK;
+	} else {
+		return DVBS2_DEMOD_NOLOCK;
+	}
+}
+
+/*
+ * stb0899_dvbs2_get_data_lock
+ * get FEC status
+ */
+static int stb0899_dvbs2_get_data_lock(struct stb0899_state *state, int timeout)
+{
+	int time = 0, lock = 0;
+	u8 reg;
+
+	while ((!lock) && (time < timeout)) {
+		reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
+		dprintk(state->verbose, FE_DEBUG, 1, "---------> CFGPDELSTATUS=[0x%02x]", reg);
+		lock = STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg);
+		time++;
+	}
+
+	return lock;
+}
+
+/*
+ * stb0899_dvbs2_get_fec_status
+ * get DVB-S2 FEC LOCK status
+ */
+static enum stb0899_status stb0899_dvbs2_get_fec_status(struct stb0899_state *state, int timeout)
+{
+	int time = 0, Locked;
+
+	do {
+		Locked = stb0899_dvbs2_get_data_lock(state, 1);
+		time++;
+		msleep(1);
+
+	} while ((!Locked) && (time < timeout));
+
+	if (Locked) {
+		dprintk(state->verbose, FE_DEBUG, 1, "---------->DVB-S2 FEC LOCK !");
+		return DVBS2_FEC_LOCK;
+	} else {
+		return DVBS2_FEC_NOLOCK;
+	}
+}
+
+#if 0
+/*
+ * stb0899_dvbs2_get_modcod
+ * get MODCOD
+ */
+static u32 stb0899_dvbs2_get_modcod(struct stb0899_state *state)
+{
+	u32 reg;
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+	return (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2);
+}
+#endif
+
+/*
+ * stb0899_dvbs2_init_csm
+ * set parameters for manual mode
+ */
+static void stb0899_dvbs2_init_csm(struct stb0899_state *state, int pilots, enum stb0899_modcod modcod)
+{
+	struct stb0899_internal *internal = &state->internal;
+	s32 dvt_tbl = 1, two_pass = 0, agc_gain = 6, agc_shift = 0, loop_shift = 0, phs_diff_thr = 0x80;
+	s32 gamma_acq, gamma_rho_acq, gamma_trk, gamma_rho_trk, lock_count_thr;
+	u32 csm1, csm2, csm3, csm4;
+
+	if (((internal->master_clk / internal->srate) <= 4) && (modcod <= 11) && (pilots == 1)) {
+		switch (modcod) {
+		case STB0899_QPSK_12:
+			gamma_acq		= 25;
+			gamma_rho_acq		= 2700;
+			gamma_trk		= 12;
+			gamma_rho_trk		= 180;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_35:
+			gamma_acq		= 38;
+			gamma_rho_acq		= 7182;
+			gamma_trk		= 14;
+			gamma_rho_trk		= 308;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_23:
+			gamma_acq		= 42;
+			gamma_rho_acq		= 9408;
+			gamma_trk		= 17;
+			gamma_rho_trk		= 476;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_34:
+			gamma_acq		= 53;
+			gamma_rho_acq		= 16642;
+			gamma_trk		= 19;
+			gamma_rho_trk		= 646;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_45:
+			gamma_acq		= 53;
+			gamma_rho_acq		= 17119;
+			gamma_trk		= 22;
+			gamma_rho_trk		= 880;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_56:
+			gamma_acq		= 55;
+			gamma_rho_acq		= 19250;
+			gamma_trk		= 23;
+			gamma_rho_trk		= 989;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_89:
+			gamma_acq		= 60;
+			gamma_rho_acq		= 24240;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		case STB0899_QPSK_910:
+			gamma_acq		= 66;
+			gamma_rho_acq		= 29634;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		default:
+			gamma_acq		= 66;
+			gamma_rho_acq		= 29634;
+			gamma_trk		= 24;
+			gamma_rho_trk		= 1176;
+			lock_count_thr		= 8;
+			break;
+		}
+
+		csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+		STB0899_SETFIELD_VAL(CSM_AUTO_PARAM, csm1, 0);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+
+		csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+		csm2 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL2);
+		csm3 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL3);
+		csm4 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL4);
+
+		STB0899_SETFIELD_VAL(CSM_DVT_TABLE, csm1, dvt_tbl);
+		STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, two_pass);
+		STB0899_SETFIELD_VAL(CSM_AGC_GAIN, csm1, agc_gain);
+		STB0899_SETFIELD_VAL(CSM_AGC_SHIFT, csm1, agc_shift);
+		STB0899_SETFIELD_VAL(FE_LOOP_SHIFT, csm1, loop_shift);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_ACQ, csm2, gamma_acq);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_RHOACQ, csm2, gamma_rho_acq);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_TRACK, csm3, gamma_trk);
+		STB0899_SETFIELD_VAL(CSM_GAMMA_RHOTRACK, csm3, gamma_rho_trk);
+		STB0899_SETFIELD_VAL(CSM_LOCKCOUNT_THRESH, csm4, lock_count_thr);
+		STB0899_SETFIELD_VAL(CSM_PHASEDIFF_THRESH, csm4, phs_diff_thr);
+
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL2, STB0899_OFF0_CSM_CNTRL2, csm2);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL3, STB0899_OFF0_CSM_CNTRL3, csm3);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL4, STB0899_OFF0_CSM_CNTRL4, csm4);
+	}
+}
+
+/*
+ * stb0899_dvbs2_get_srate
+ * get DVB-S2 Symbol Rate
+ */
+static u32 stb0899_dvbs2_get_srate(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+
+	u32 bTrNomFreq, srate, decimRate, intval1, intval2, reg;
+	int div1, div2, rem1, rem2;
+
+	div1 = config->btr_nco_bits / 2;
+	div2 = config->btr_nco_bits - div1 - 1;
+
+	bTrNomFreq = STB0899_READ_S2REG(STB0899_S2DEMOD, BTR_NOM_FREQ);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DECIM_CNTRL);
+	decimRate = STB0899_GETFIELD(DECIM_RATE, reg);
+	decimRate = (1 << decimRate);
+
+	intval1 = internal->master_clk / (1 << div1);
+	intval2 = bTrNomFreq / (1 << div2);
+
+	rem1 = internal->master_clk % (1 << div1);
+	rem2 = bTrNomFreq % (1 << div2);
+	/* only for integer calculation	*/
+	srate = (intval1 * intval2) + ((intval1 * rem2) / (1 << div2)) + ((intval2 * rem1) / (1 << div1));
+	srate /= decimRate;	/*symbrate = (btrnomfreq_register_val*MasterClock)/2^(27+decim_rate_field) */
+
+	return	srate;
+}
+
+/*
+ * stb0899_dvbs2_algo
+ * Search for signal, timing, carrier and data for a given
+ * frequency in a given range
+ */
+enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	enum stb0899_modcod modcod;
+
+	s32 offsetfreq, searchTime, FecLockTime, pilots, iqSpectrum;
+	int i = 0;
+	u32 reg, csm1;
+
+    s32 retry = 0;
+    do {
+	if (internal->srate <= 2000000) {
+		searchTime	= 5000;	/* 5000 ms max time to lock UWP and CSM, SYMB <= 2Mbs		*/
+		FecLockTime	= 350;	/* 350  ms max time to lock FEC, SYMB <= 2Mbs			*/
+	} else if (internal->srate <= 5000000) {
+		searchTime	= 2500;	/* 2500 ms max time to lock UWP and CSM, 2Mbs < SYMB <= 5Mbs	*/
+		FecLockTime	= 170;	/* 170  ms max time to lock FEC, 2Mbs< SYMB <= 5Mbs		*/
+	} else if (internal->srate <= 10000000) {
+		searchTime	= 1500;	/* 1500 ms max time to lock UWP and CSM, 5Mbs <SYMB <= 10Mbs	*/
+		FecLockTime	= 80;	/* 80  ms max time to lock FEC, 5Mbs< SYMB <= 10Mbs		*/
+	} else if (internal->srate <= 15000000) {
+		searchTime	= 500;	/* 500 ms max time to lock UWP and CSM, 10Mbs <SYMB <= 15Mbs	*/
+		FecLockTime	= 50;	/* 50  ms max time to lock FEC, 10Mbs< SYMB <= 15Mbs		*/
+	} else if (internal->srate <= 20000000) {
+		searchTime	= 300;	/* 300 ms max time to lock UWP and CSM, 15Mbs < SYMB <= 20Mbs	*/
+		FecLockTime	= 30;	/* 50  ms max time to lock FEC, 15Mbs< SYMB <= 20Mbs		*/
+	} else if (internal->srate <= 25000000) {
+		searchTime	= 250;	/* 250 ms max time to lock UWP and CSM, 20 Mbs < SYMB <= 25Mbs	*/
+		FecLockTime	= 25;	/* 25 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs		*/
+	} else {
+		searchTime	= 150;	/* 150 ms max time to lock UWP and CSM, SYMB > 25Mbs		*/
+		FecLockTime	= 20;	/* 20 ms max time to lock FEC, 20Mbs< SYMB <= 25Mbs		*/
+	}
+	/* Maintain Stream Merger in reset during acquisition	*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 1);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+	/* Move tuner to frequency	*/
+	if (state->config->tuner_set_frequency)
+		state->config->tuner_set_frequency(&state->frontend, internal->freq);
+	if (state->config->tuner_get_frequency)
+		state->config->tuner_get_frequency(&state->frontend, &internal->freq);
+
+	/* Set IF AGC to acquisition	*/
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+	STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg,  4);
+	STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 32);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
+	STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 0);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
+
+	/* Initialisation	*/
+	stb0899_dvbs2_init_calc(state);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+	switch (internal->inversion) {
+	case IQ_SWAP_OFF:
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 0);
+		break;
+	case IQ_SWAP_ON:
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
+		break;
+	case IQ_SWAP_AUTO:	/* use last successful search first	*/
+		STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, 1);
+		break;
+	}
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
+	stb0899_dvbs2_reacquire(state);
+
+	/* Wait for demod lock (UWP and CSM)	*/
+	internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
+
+	if (internal->status == DVBS2_DEMOD_LOCK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "------------> DVB-S2 DEMOD LOCK !");
+		i = 0;
+		/* Demod Locked, check FEC status	*/
+		internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+
+		/*If false lock (UWP and CSM Locked but no FEC) try 3 time max*/
+		while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+			/*	Read the frequency offset*/
+			offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+			/* Set the Nominal frequency to the found frequency offset for the next reacquire*/
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+			STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, offsetfreq);
+			stb0899_dvbs2_reacquire(state);
+			internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
+			i++;
+		}
+    	}
+	    
+	if (internal->status != DVBS2_FEC_LOCK) {
+		/*if (internal->inversion == IQ_SWAP_AUTO)*/ {	// TODO: Special for TT3200
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+			iqSpectrum = STB0899_GETFIELD(SPECTRUM_INVERT, reg);
+			/* IQ Spectrum Inversion	*/
+			STB0899_SETFIELD_VAL(SPECTRUM_INVERT, reg, !iqSpectrum);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_DMD_CNTRL2, STB0899_OFF0_DMD_CNTRL2, reg);
+			/* start acquistion process	*/
+			stb0899_dvbs2_reacquire(state);
+
+			/* Wait for demod lock (UWP and CSM)	*/
+			internal->status = stb0899_dvbs2_get_dmd_status(state, searchTime);
+			if (internal->status == DVBS2_DEMOD_LOCK) {
+				i = 0;
+				/* Demod Locked, check FEC	*/
+				internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+				/*try thrice for false locks, (UWP and CSM Locked but no FEC)	*/
+				while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+					/*	Read the frequency offset*/
+					offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+					/* Set the Nominal frequency to the found frequency offset for the next reacquire*/
+					reg = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_NOM_FREQ);
+					STB0899_SETFIELD_VAL(CRL_NOM_FREQ, reg, offsetfreq);
+					stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CRL_NOM_FREQ, STB0899_OFF0_CRL_NOM_FREQ, offsetfreq);
+
+					stb0899_dvbs2_reacquire(state);
+					internal->status = stb0899_dvbs2_get_fec_status(state, searchTime);
+					i++;
+				}
+			}
+/*
+			if (pParams->DVBS2State == FE_DVBS2_FEC_LOCKED)
+				pParams->IQLocked = !iqSpectrum;
+*/
+		}
+	}
+	if (internal->status == DVBS2_FEC_LOCK) {
+		dprintk(state->verbose, FE_DEBUG, 1, "----------------> DVB-S2 FEC Lock !");
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+		modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
+		pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
+
+		if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
+		      (INRANGE(STB0899_QPSK_23, modcod, STB0899_QPSK_910)) &&
+		      (pilots == 1)) {
+
+			stb0899_dvbs2_init_csm(state, pilots, modcod);
+			/* Wait for UWP,CSM and data LOCK 20ms max	*/
+			internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+
+			i = 0;
+			while ((internal->status != DVBS2_FEC_LOCK) && (i < 3)) {
+				csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+				STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 1);
+				stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+				csm1 = STB0899_READ_S2REG(STB0899_S2DEMOD, CSM_CNTRL1);
+				STB0899_SETFIELD_VAL(CSM_TWO_PASS, csm1, 0);
+				stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_CSM_CNTRL1, STB0899_OFF0_CSM_CNTRL1, csm1);
+
+				internal->status = stb0899_dvbs2_get_fec_status(state, FecLockTime);
+				i++;
+			}
+		}
+
+		if ((((10 * internal->master_clk) / (internal->srate / 10)) <= 410) &&
+		      (INRANGE(STB0899_QPSK_12, modcod, STB0899_QPSK_35)) &&
+		      (pilots == 1)) {
+
+			/* Equalizer Disable update	 */
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+			STB0899_SETFIELD_VAL(EQ_DISABLE_UPDATE, reg, 1);
+			stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+		}
+
+		/* slow down the Equalizer once locked	*/
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, EQ_CNTRL);
+		STB0899_SETFIELD_VAL(EQ_SHIFT, reg, 0x02);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_EQ_CNTRL, STB0899_OFF0_EQ_CNTRL, reg);
+
+		/* Store signal parameters	*/
+		offsetfreq = STB0899_READ_S2REG(STB0899_S2DEMOD, CRL_FREQ);
+
+		offsetfreq = offsetfreq / ((1 << 30) / 1000);
+		offsetfreq *= (internal->master_clk / 1000000);
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CNTRL2);
+		if (STB0899_GETFIELD(SPECTRUM_INVERT, reg))
+			offsetfreq *= -1;
+
+		internal->freq = internal->freq - offsetfreq;
+		internal->srate = stb0899_dvbs2_get_srate(state);
+
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+		internal->modcod = STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 2;
+		internal->pilots = STB0899_GETFIELD(UWP_DECODE_MOD, reg) & 0x01;
+		internal->frame_length = (STB0899_GETFIELD(UWP_DECODE_MOD, reg) >> 1) & 0x01;
+
+		 /* Set IF AGC to tracking	*/
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+		STB0899_SETFIELD_VAL(IF_LOOP_GAIN, reg,  3);
+
+		/* if QPSK 1/2,QPSK 3/5 or QPSK 2/3 set IF AGC reference to 16 otherwise 32*/
+		if (INRANGE(STB0899_QPSK_12, internal->modcod, STB0899_QPSK_23))
+			STB0899_SETFIELD_VAL(IF_AGC_REF, reg, 16);
+
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+		reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL2);
+		STB0899_SETFIELD_VAL(IF_AGC_DUMP_PER, reg, 7);
+		stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL2, STB0899_OFF0_IF_AGC_CNTRL2, reg);
+	}
+
+	/* Release Stream Merger Reset		*/
+	reg = stb0899_read_reg(state, STB0899_TSTRES);
+	STB0899_SETFIELD_VAL(FRESRS, reg, 0);
+	stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+    }
+    while ( (++retry < 5) && (internal->status != DVBS2_FEC_LOCK) );
+	
+    return internal->status;
+}
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_drv.c linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_drv.c
--- linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_drv.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_drv.c	2007-07-28 01:17:12.000000000 +0200
@@ -0,0 +1,2036 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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/string.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#include "stb0899_drv.h"
+#include "stb0899_priv.h"
+#include "stb0899_reg.h"
+
+//static unsigned int verbose = 5;
+static unsigned int verbose = 0;
+module_param(verbose, int, 0644);
+
+/* C/N in dB/10, NIRM/NIRL */
+static const struct stb0899_tab stb0899_cn_tab[] = {
+	{ 200,	2600 },
+	{ 190,	2700 },
+	{ 180,	2860 },
+	{ 170,	3020 },
+	{ 160,	3210 },
+	{ 150,	3440 },
+	{ 140,	3710 },
+	{ 130,	4010 },
+	{ 120,	4360 },
+	{ 110,	4740 },
+	{ 100,	5190 },
+	{ 90,	5670 },
+	{ 80,	6200 },
+	{ 70,	6770 },
+	{ 60,	7360 },
+	{ 50,	7970 },
+	{ 40,	8250 },
+	{ 30,	9000 },
+	{ 20,	9450 },
+	{ 15,	9600 },
+};
+
+/* DVB-S AGCIQ_VALUE vs. signal level in dBm/10.
+ * As measured, connected to a modulator.
+ * -8.0 to -50.0 dBm directly connected,
+ * -52.0 to -74.8 with extra attenuation.
+ * Cut-off to AGCIQ_VALUE = 0x80 below -74.8dBm.
+ * Crude linear extrapolation below -84.8dBm and above -8.0dBm.
+ */
+static const struct stb0899_tab stb0899_dvbsrf_tab[] = {
+	{ -950,	-128 },
+	{ -748,	 -94 },
+	{ -745,	 -92 },
+	{ -735,	 -90 },
+	{ -720,	 -87 },
+	{ -670,	 -77 },
+	{ -640,	 -70 },
+	{ -610,	 -62 },
+	{ -600,	 -60 },
+	{ -590,	 -56 },
+	{ -560,	 -41 },
+	{ -540,	 -25 },
+	{ -530,	 -17 },
+	{ -520,	 -11 },
+	{ -500,	   1 },
+	{ -490,	   6 },
+	{ -480,	  10 },
+	{ -440,	  22 },
+	{ -420,	  27 },
+	{ -400,	  31 },
+	{ -380,	  34 },
+	{ -340,	  40 },
+	{ -320,	  43 },
+	{ -280,	  48 },
+	{ -250,	  52 },
+	{ -230,	  55 },
+	{ -180,	  61 },
+	{ -140,	  66 },
+	{  -90,	  73 },
+	{  -80,	  74 },
+	{  500,	 127 }
+};
+
+/* DVB-S2 IF_AGC_GAIN vs. signal level in dBm/10.
+ * As measured, connected to a modulator.
+ * -8.0 to -50.1 dBm directly connected,
+ * -53.0 to -76.6 with extra attenuation.
+ * Cut-off to IF_AGC_GAIN = 0x3fff below -76.6dBm.
+ * Crude linear extrapolation below -76.6dBm and above -8.0dBm.
+ */
+static const struct stb0899_tab stb0899_dvbs2rf_tab[] = {
+	{  700,	    0 },
+	{  -80,	 3217 },
+	{ -150,	 3893 },
+	{ -190,	 4217 },
+	{ -240,	 4621 },
+	{ -280,	 4945 },
+	{ -320,	 5273 },
+	{ -350,	 5545 },
+	{ -370,	 5741 },
+	{ -410,	 6147 },
+	{ -450,	 6671 },
+	{ -490,	 7413 },
+	{ -501,	 7665 },
+	{ -530,	 8767 },
+	{ -560,	10219 },
+	{ -580,	10939 },
+	{ -590,	11518 },
+	{ -600,	11723 },
+	{ -650,	12659 },
+	{ -690,	13219 },
+	{ -730,	13645 },
+	{ -750,	13909 },
+	{ -766,	14153 },
+	{ -999,	16383 }
+};
+
+/* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/
+struct stb0899_tab stb0899_quant_tab[] = {
+	{    0,	    0 },
+	{    0,	  100 },
+	{  600,	  200 },
+	{  950,	  299 },
+	{ 1200,	  398 },
+	{ 1400,	  501 },
+	{ 1560,	  603 },
+	{ 1690,	  700 },
+	{ 1810,	  804 },
+	{ 1910,	  902 },
+	{ 2000,	 1000 },
+	{ 2080,	 1096 },
+	{ 2160,	 1202 },
+	{ 2230,	 1303 },
+	{ 2350,	 1496 },
+	{ 2410,	 1603 },
+	{ 2460,	 1698 },
+	{ 2510,	 1799 },
+	{ 2600,	 1995 },
+	{ 2650,	 2113 },
+	{ 2690,  2213 },
+	{ 2720,	 2291 },
+	{ 2760,	 2399 },
+	{ 2800,	 2512 },
+	{ 2860,	 2692 },
+	{ 2930,	 2917 },
+	{ 2960,	 3020 },
+	{ 3010,	 3199 },
+	{ 3040,	 3311 },
+	{ 3060,	 3388 },
+	{ 3120,	 3631 },
+	{ 3190,	 3936 },
+	{ 3400,	 5012 },
+	{ 3610,	 6383 },
+	{ 3800,	 7943 },
+	{ 4210,	12735 },
+	{ 4500,	17783 },
+	{ 4690,	22131 },
+	{ 4810,	25410 }
+};
+
+/* DVB-S2 Es/N0 estimate in dB/100 vs read value */
+struct stb0899_tab stb0899_est_tab[] = {
+	{    0,	     0 },
+	{    0,	     1 },
+	{  301,	     2 },
+	{ 1204,	    16 },
+	{ 1806,	    64 },
+	{ 2408,	   256 },
+	{ 2709,	   512 },
+	{ 3010,	  1023 },
+	{ 3311,	  2046 },
+	{ 3612,	  4093 },
+	{ 3823,	  6653 },
+	{ 3913,	  8185 },
+	{ 4010,	 10233 },
+	{ 4107,	 12794 },
+	{ 4214,	 16368 },
+	{ 4266,	 18450 },
+	{ 4311,	 20464 },
+	{ 4353,	 22542 },
+	{ 4391,	 24604 },
+	{ 4425,	 26607 },
+	{ 4457,	 28642 },
+	{ 4487,	 30690 },
+	{ 4515,	 32734 },
+	{ 4612,	 40926 },
+	{ 4692,	 49204 },
+	{ 4816,	 65464 },
+	{ 4913,	 81846 },
+	{ 4993,	 98401 },
+	{ 5060,	114815 },
+	{ 5118,	131220 },
+	{ 5200,	158489 },
+	{ 5300,	199526 },
+	{ 5400,	251189 },
+	{ 5500,	316228 },
+	{ 5600,	398107 },
+	{ 5720,	524807 },
+	{ 5721,	526017 },
+};
+
+int _stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+{
+	int ret;
+
+	u8 b0[] = { reg >> 8, reg & 0xff };
+	u8 buf;
+
+	struct i2c_msg msg[] = {
+		{
+			.addr	= state->config->demod_address,
+			.flags	= 0,
+			.buf	= b0,
+			.len	= 2
+		},{
+			.addr	= state->config->demod_address,
+			.flags	= I2C_M_RD,
+			.buf	= &buf,
+			.len	= 1
+		}
+	};
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2) {
+		if (ret != -ERESTARTSYS)
+			dprintk(verbose, FE_ERROR, 1,
+				"Read error, Reg=[0x%02x], Status=%d",
+				reg, ret);
+
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+	if (unlikely(verbose >= FE_DEBUGREG))
+		dprintk(verbose, FE_ERROR, 1, "Reg=[0x%02x], data=%02x",
+			reg, buf);
+
+
+	return (unsigned int)buf;
+}
+
+int stb0899_read_reg(struct stb0899_state *state, unsigned int reg)
+{
+	int result;
+	
+	result = _stb0899_read_reg(state, reg);
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
+	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		_stb0899_read_reg(state, (reg | 0x00ff));
+
+	return result;
+}
+
+u32 _stb0899_read_s2reg(struct stb0899_state *state,
+		        u32 stb0899_i2cdev,
+		        u32 stb0899_base_addr,
+		        u16 stb0899_reg_offset)
+{
+	int status;
+	u32 data;
+	u8 buf[7] = { 0 };
+	u16 tmpaddr;
+
+	u8 buf_0[] = {
+		GETBYTE(stb0899_i2cdev, BYTE1),		/* 0xf3	S2 Base Address (MSB)	*/
+		GETBYTE(stb0899_i2cdev, BYTE0),		/* 0xfc	S2 Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE0),	/* 0x00	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE1),	/* 0x04	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE2),	/* 0x00	Base Address (MSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE3),	/* 0x00	Base Address (MSB)	*/
+	};
+	u8 buf_1[] = {
+		0x00,	/* 0xf3	Reg Offset	*/
+		0x00,	/* 0x44	Reg Offset	*/
+	};
+
+	struct i2c_msg msg_0 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_0,
+		.len	= 6
+	};
+
+	struct i2c_msg msg_1 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_1,
+		.len	= 2
+	};
+
+	struct i2c_msg msg_r = {
+		.addr	= state->config->demod_address,
+		.flags	= I2C_M_RD,
+		.buf	= buf,
+		.len	= 4
+	};
+
+	tmpaddr = stb0899_reg_offset & 0xff00;
+	if (!(stb0899_reg_offset & 0x8))
+		tmpaddr = stb0899_reg_offset | 0x20;
+
+	buf_1[0] = GETBYTE(tmpaddr, BYTE1);
+	buf_1[1] = GETBYTE(tmpaddr, BYTE0);
+
+	status = i2c_transfer(state->i2c, &msg_0, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(1), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+
+		goto err;
+	}
+
+	/* Dummy	*/
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (status < 1)
+		goto err;
+
+	status = i2c_transfer(state->i2c, &msg_r, 1);
+	if (status < 1)
+		goto err;
+
+	buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
+	buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
+
+	/* Actual	*/
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(2), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+		goto err;
+	}
+
+	status = i2c_transfer(state->i2c, &msg_r, 1);
+	if (status < 1) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR(3), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status);
+		return status < 0 ? status : -EREMOTEIO;
+	}
+
+	data = MAKEWORD32(buf[3], buf[2], buf[1], buf[0]);
+	if (unlikely(state->verbose >= FE_DEBUGREG))
+		printk(KERN_DEBUG "%s Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
+		       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, data);
+
+	return data;
+
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_write_s2reg(struct stb0899_state *state,
+		 	u32 stb0899_i2cdev,
+			u32 stb0899_base_addr,
+			u16 stb0899_reg_offset,
+			u32 stb0899_data)
+{
+	int status;
+
+	/* Base Address Setup	*/
+	u8 buf_0[] = {
+		GETBYTE(stb0899_i2cdev, BYTE1),		/* 0xf3	S2 Base Address (MSB)	*/
+		GETBYTE(stb0899_i2cdev, BYTE0),		/* 0xfc	S2 Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE0),	/* 0x00	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE1),	/* 0x04	Base Address (LSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE2),	/* 0x00	Base Address (MSB)	*/
+		GETBYTE(stb0899_base_addr, BYTE3),	/* 0x00	Base Address (MSB)	*/
+	};
+	u8 buf_1[] = {
+		0x00,	/* 0xf3	Reg Offset	*/
+		0x00,	/* 0x44	Reg Offset	*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+		0x00,	/* data			*/
+	};
+
+	struct i2c_msg msg_0 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_0,
+		.len	= 6
+	};
+
+	struct i2c_msg msg_1 = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf_1,
+		.len	= 6
+	};
+
+	buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1);
+	buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0);
+	buf_1[2] = GETBYTE(stb0899_data, BYTE0);
+	buf_1[3] = GETBYTE(stb0899_data, BYTE1);
+	buf_1[4] = GETBYTE(stb0899_data, BYTE2);
+	buf_1[5] = GETBYTE(stb0899_data, BYTE3);
+
+	if (unlikely(state->verbose >= FE_DEBUGREG))
+		printk(KERN_DEBUG "%s Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n",
+		       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data);
+
+	status = i2c_transfer(state->i2c, &msg_0, 1);
+	if (unlikely(status < 1)) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR (1), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
+		goto err;
+	}
+	status = i2c_transfer(state->i2c, &msg_1, 1);
+	if (unlikely(status < 1)) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s ERR (2), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n",
+			       __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status);
+
+		return status < 0 ? status : -EREMOTEIO;
+	}
+
+	return 0;
+
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_read_regs(struct stb0899_state *state, unsigned int reg, u8 *buf, size_t count)
+{
+	int status;
+
+	u8 b0[] = { reg >> 8, reg & 0xff };
+
+	struct i2c_msg msg[] = {
+		{
+			.addr	= state->config->demod_address,
+			.flags	= 0,
+			.buf	= b0,
+			.len	= 2
+		},{
+			.addr	= state->config->demod_address,
+			.flags	= I2C_M_RD,
+			.buf	= buf,
+			.len	= count
+		}
+	};
+
+	status = i2c_transfer(state->i2c, msg, 2);
+	if (status != 2) {
+		if (status != -ERESTARTSYS)
+			printk(KERN_ERR "%s Read error, Reg=[0x%04x], Count=%u, Status=%d\n",
+			       __func__, reg, count, status);
+		goto err;
+	}
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((reg != 0xf2ff) && (reg != 0xf6ff) &&
+	    (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		_stb0899_read_reg(state, (reg | 0x00ff));
+
+	if (unlikely(state->verbose >= FE_DEBUGREG)) {
+		int i;
+
+		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+		for (i = 0; i < count; i++) {
+			printk(" %02x", buf[i]);
+		}
+		printk("\n");
+	}
+
+	return 0;
+err:
+	return status < 0 ? status : -EREMOTEIO;
+}
+
+int stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, size_t count)
+{
+	int ret;
+	u8 buf[2 + count];
+	struct i2c_msg i2c_msg = {
+		.addr	= state->config->demod_address,
+		.flags	= 0,
+		.buf	= buf,
+		.len	= 2 + count
+	};
+
+	buf[0] = reg >> 8;
+	buf[1] = reg & 0xff;
+	memcpy(&buf[2], data, count);
+
+	if (unlikely(state->verbose >= FE_DEBUGREG)) {
+		int i;
+
+		printk(KERN_DEBUG "%s [0x%04x]:", __func__, reg);
+		for (i = 0; i < count; i++)
+			printk(" %02x", data[i]);
+		printk("\n");
+	}
+	ret = i2c_transfer(state->i2c, &i2c_msg, 1);
+
+	/*
+	 * Bug ID 9:
+	 * access to 0xf2xx/0xf6xx
+	 * must be followed by read from 0xf2ff/0xf6ff.
+	 */
+	if ((((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600)))
+		stb0899_read_reg(state, (reg | 0x00ff));
+
+	if (ret != 1) {
+		if (ret != -ERESTARTSYS)
+			dprintk(verbose, FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d",
+				reg, data[0], count, ret);
+		return ret < 0 ? ret : -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
+{
+	return stb0899_write_regs(state, reg, &data, 1);
+}
+
+/*
+ * stb0899_get_mclk
+ * Get STB0899 master clock frequency
+ * ExtClk: external clock frequency (Hz)
+ */
+static u32 stb0899_get_mclk(struct stb0899_state *state)
+{
+	u32 mclk = 90000000, div = 0;
+
+	div = stb0899_read_reg(state, STB0899_NCOARSE);
+	mclk = (div + 1) * state->config->xtal_freq / 6;
+	dprintk(verbose, FE_DEBUG, 1, "div=%d, mclk=%d", div, mclk);
+
+	return mclk;
+}
+
+/*
+ * stb0899_set_mclk
+ * Set STB0899 master Clock frequency
+ * Mclk: demodulator master clock
+ * ExtClk: external clock frequency (Hz)
+ */
+static void stb0899_set_mclk(struct stb0899_state *state, u32 Mclk)
+{
+	struct stb0899_internal *internal = &state->internal;
+	u8 mdiv = 0;
+
+	dprintk(verbose, FE_DEBUG, 1, "state->config=%p", state->config);
+	mdiv = ((6 * Mclk) / state->config->xtal_freq) - 1;
+	dprintk(verbose, FE_DEBUG, 1, "mdiv=%d", mdiv);
+
+	stb0899_write_reg(state, STB0899_NCOARSE, mdiv);
+	internal->master_clk = stb0899_get_mclk(state);
+
+	dprintk(verbose, FE_DEBUG, 1, "MasterCLOCK=%d", internal->master_clk);
+}
+
+static void stb0899_release(struct dvb_frontend *fe)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	dprintk(verbose, FE_DEBUG, 1, "Release Frontend");
+	kfree(state);
+}
+
+/*
+ * stb0899_get_alpha
+ * return: rolloff
+ */
+static int stb0899_get_alpha(struct stb0899_state *state)
+{
+	u8 mode_coeff;
+
+	mode_coeff = stb0899_read_reg(state, STB0899_DEMOD);
+
+	if (STB0899_GETFIELD(MODECOEFF, mode_coeff) == 1)
+		return 20;
+	else
+		return 35;
+}
+
+/*
+ * stb0899_init_calc
+ */
+static void stb0899_init_calc(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	int master_clk;
+	u8 agc[1];
+	u8 agc1cn;
+	u32 reg;
+
+	/* Read registers (in burst mode)	*/
+	agc1cn = stb0899_read_reg(state, STB0899_AGC1CN);
+	stb0899_read_regs(state, STB0899_AGC1REF, agc, 2); /* AGC1R and AGC2O	*/
+
+	/* Initial calculations	*/
+	master_clk			= stb0899_get_mclk(state);
+	internal->t_agc1		= 0;
+	internal->t_agc2		= 0;
+	internal->master_clk		= master_clk;
+	internal->mclk			= master_clk / 65536L;
+	internal->rolloff		= stb0899_get_alpha(state);
+
+	/* DVBS2 Initial calculations	*/
+	/* Set AGC value to the middle	*/
+	internal->agc_gain		= 8154;
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL);
+	STB0899_SETFIELD_VAL(IF_GAIN_INIT, reg, internal->agc_gain);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg);
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, RRC_ALPHA);
+	internal->rrc_alpha		= STB0899_GETFIELD(RRC_ALPHA, reg);
+
+	internal->center_freq		= 0;
+	internal->av_frame_coarse	= 10;
+	internal->av_frame_fine		= 20;
+	internal->step_size		= 2;
+/*
+	if ((pParams->SpectralInv == FE_IQ_NORMAL) || (pParams->SpectralInv == FE_IQ_AUTO))
+		pParams->IQLocked = 0;
+	else
+		pParams->IQLocked = 1;
+*/
+}
+
+static int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (1) {
+		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
+		if (!STB0899_GETFIELD(FIFOFULL, reg))
+			break;
+		if ((jiffies - start) > timeout) {
+			dprintk(verbose, FE_ERROR, 1, "timed out !!");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, i;
+
+	if (cmd->msg_len > 8)
+		return -EINVAL;
+
+	/* enable FIFO precharge	*/
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 1);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	for (i = 0; i < cmd->msg_len; i++) {
+		/* wait for FIFO empty	*/
+		if (stb0899_wait_diseqc_fifo_empty(state, 10) < 0)
+			return -ETIMEDOUT;
+
+		stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]);
+	}
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+
+	return 0;
+}
+
+static int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (!STB0899_GETFIELD(RXEND, reg)) {
+		reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
+		if (jiffies - start > timeout) {
+			dprintk(verbose, FE_ERROR, 1, "timed out!!");
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	}
+
+	return 0;
+}
+
+static int stb0899_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, length = 0, i;
+	int result;
+
+	if (stb0899_wait_diseqc_rxidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	reg = stb0899_read_reg(state, STB0899_DISRX_ST0);
+	if (STB0899_GETFIELD(RXEND, reg)) {
+
+		reg = stb0899_read_reg(state, STB0899_DISRX_ST1);
+		length = STB0899_GETFIELD(FIFOBYTENBR, reg);
+
+		if (length > sizeof (reply->msg)) {
+			result = -EOVERFLOW;
+			goto exit;
+		}
+		reply->msg_len = length;
+
+		/* extract data */
+		for (i = 0; i < length; i++)
+			reply->msg[i] = stb0899_read_reg(state, STB0899_DISFIFO);
+	}
+
+	return 0;
+exit:
+
+	return result;
+}
+
+static int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout)
+{
+	u8 reg = 0;
+	unsigned long start = jiffies;
+
+	while (!STB0899_GETFIELD(TXIDLE, reg)) {
+		reg = stb0899_read_reg(state, STB0899_DISSTATUS);
+		if (jiffies - start > timeout) {
+			dprintk(verbose, FE_ERROR, 1, "timed out!!");
+			return -ETIMEDOUT;
+		}
+		msleep(10);
+	}
+	return 0;
+}
+
+static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg, old_state;
+
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	old_state = reg;
+	/* set to burst mode	*/
+	STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	switch (burst) {
+	case SEC_MINI_A:
+		/* unmodulated	*/
+		stb0899_write_reg(state, STB0899_DISFIFO, 0x00);
+		break;
+	case SEC_MINI_B:
+		/* modulated	*/
+		stb0899_write_reg(state, STB0899_DISFIFO, 0xff);
+		break;
+	}
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x00);
+	stb0899_write_reg(state, STB0899_DISCNTRL1, reg);
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	/* restore state	*/
+	stb0899_write_reg(state, STB0899_DISCNTRL1, old_state);
+
+	return 0;
+}
+
+#if 0
+static int stb0899_diseqc_init(struct stb0899_state *state)
+{
+	struct dvb_diseqc_master_cmd tx_data;
+	struct dvb_diseqc_slave_reply rx_data;
+
+	u8 f22_tx, f22_rx, reg;
+
+	u32 mclk, tx_freq = 22000, count = 0, i;
+
+	u32 trial = 0;	/* try max = 2 (try 20khz and 17.5 khz)	*/
+	u32 ret_1 = 0;	/* 20 Khz status	*/
+	u32 ret_2 = 0;	/* 17.5 Khz status	*/
+
+	tx_data.msg[0] = 0xe2;
+	tx_data.msg_len = 3;
+	/* disable Tx spy	*/
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL2);
+	STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL2, reg);
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 1);
+	stb0899_write_reg(state, STB0899_DISCNTRL2, reg);
+
+	reg = stb0899_read_reg(state, STB0899_DISCNTRL1);
+	STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 0);
+	stb0899_write_reg(state, STB0899_DISCNTRL2, reg);
+
+	mclk = stb0899_get_mclk(state);
+	f22_tx = mclk / (tx_freq * 32);
+	stb0899_write_reg(state, STB0899_DISF22, f22_tx); /* DiSEqC Tx freq	*/
+	state->rx_freq = 20000;
+	f22_rx = mclk / (state->rx_freq * 32);
+
+	while ((count < 5) && (trial < 2)) {
+		stb0899_write_reg(state, STB0899_DISF22, f22_tx); /* 2 possible values 17.5k/20k	*/
+
+		for (i = 0; i < 5; i++) {
+			msleep(50);
+			stb0899_send_diseqc_msg(&state->frontend, &tx_data);
+			msleep(100);
+			stb0899_recv_slave_reply(&state->frontend, &rx_data);
+			if (rx_data.msg_len >= 1) {
+				if ((rx_data.msg[0] == 0xe4) || (rx_data.msg[0] == 0xe5))
+					count++;
+			}
+		}
+		if (trial == 0)
+			ret_1 = count;
+		else
+			ret_2 = count;
+
+		trial++;
+		state->rx_freq = 17500;
+		f22_rx = mclk / (state->rx_freq * 32);
+	}
+	if (ret_1 > ret_2) {
+		state->rx_freq = 20000;
+		f22_rx = mclk / (state->rx_freq * 32);
+	} else {
+		state->rx_freq = 17500;
+		f22_rx = mclk / (state->rx_freq * 32);
+	}
+
+	stb0899_write_reg(state, STB0899_DISF22, f22_tx);
+	if ((ret_1 == 0) && (ret_2 == 0))
+			state->rx_freq = 0;	/* no DiSEqC 2.0 slave	*/
+
+	return 0;
+}
+#endif
+
+static int stb0899_sleep(struct dvb_frontend *fe)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	u8 reg;
+
+	dprintk(verbose, FE_DEBUG, 1, "Going to Sleep .. (Really tired .. :-))");
+
+	reg = stb0899_read_reg(state, STB0899_SYNTCTRL);
+	STB0899_SETFIELD_VAL(STANDBY, reg, 1);
+	stb0899_write_reg(state, STB0899_SYNTCTRL, reg);
+
+	return 0;
+}
+
+static int stb0899_wakeup(struct dvb_frontend *fe)
+{
+	int rc;
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	if ((rc = stb0899_write_reg(state, STB0899_SYNTCTRL, STB0899_SELOSCI)))
+		return rc;
+	/* Activate all clocks; DVB-S2 registers are inaccessible otherwise. */
+	if ((rc = stb0899_write_reg(state, STB0899_STOPCLK1, 0x00)))
+		return rc;
+	if ((rc = stb0899_write_reg(state, STB0899_STOPCLK2, 0x00)))
+		return rc;
+
+	return 0;
+}
+
+static int stb0899_init(struct dvb_frontend *fe)
+{
+	int i;
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_config *config = state->config;
+
+	dprintk(verbose, FE_DEBUG, 1, "Initializing STB0899 ... ");
+//	mutex_init(&state->search_lock);
+
+	/* init device		*/
+	dprintk(verbose, FE_DEBUG, 1, "init device");
+	for (i = 0; config->init_dev[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_dev[i].address, config->init_dev[i].data);
+
+	dprintk(verbose, FE_DEBUG, 1, "init S2 demod");
+	/* init S2 demod	*/
+	for (i = 0; config->init_s2_demod[i].offset != 0xffff; i++)
+		stb0899_write_s2reg(state, STB0899_S2DEMOD,
+				    config->init_s2_demod[i].base_address,
+				    config->init_s2_demod[i].offset,
+				    config->init_s2_demod[i].data);
+
+	dprintk(verbose, FE_DEBUG, 1, "init S1 demod");
+	/* init S1 demod	*/
+	for (i = 0; config->init_s1_demod[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_s1_demod[i].address, config->init_s1_demod[i].data);
+
+	dprintk(verbose, FE_DEBUG, 1, "init S2 FEC");
+	/* init S2 fec		*/
+	for (i = 0; config->init_s2_fec[i].offset != 0xffff; i++)
+		stb0899_write_s2reg(state, STB0899_S2FEC,
+				    config->init_s2_fec[i].base_address,
+				    config->init_s2_fec[i].offset,
+				    config->init_s2_fec[i].data);
+
+	dprintk(verbose, FE_DEBUG, 1, "init TST");
+	/* init test		*/
+	for (i = 0; config->init_tst[i].address != 0xffff; i++)
+		stb0899_write_reg(state, config->init_tst[i].address, config->init_tst[i].data);
+
+	stb0899_init_calc(state);
+//	stb0899_diseqc_init(state);
+
+	return 0;
+}
+
+static int stb0899_table_lookup(const struct stb0899_tab *tab, int max, int val)
+{
+	int res = 0;
+	int min = 0, med;
+
+	if (val < tab[min].read)
+		res = tab[min].real;
+	else if (val >= tab[max].read)
+		res = tab[max].real;
+	else {
+		while ((max - min) > 1) {
+			med = (max + min) / 2;
+			if (val >= tab[min].read && val < tab[med].read)
+				max = med;
+			else
+				min = med;
+		}
+		res = ((val - tab[min].read) *
+		       (tab[max].real - tab[min].real) /
+		       (tab[max].read - tab[min].read)) +
+			tab[min].real;
+	}
+
+	return res;
+}
+
+static int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	int val;
+	u32 reg;
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+	case DVBFE_DELSYS_DSS:
+		if (internal->lock) {
+			reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+
+				reg = stb0899_read_reg(state, STB0899_AGCIQIN);
+				val = (s32)(s8)STB0899_GETFIELD(AGCIQVALUE, reg);
+
+				*strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val);
+				*strength += 750;
+				dprintk(verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm",
+					val & 0xff, *strength);
+			}
+		}
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_DEMOD, IF_AGC_GAIN);
+			val = STB0899_GETFIELD(IF_AGC_GAIN, reg);
+
+			*strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val);
+			*strength += 750;
+			dprintk(verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm",
+				val & 0x3fff, *strength);
+		}
+		break;
+	default:
+		dprintk(verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		break;
+	}
+
+	return 0;
+}
+
+static int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	unsigned int val, quant, quantn = -1, est, estn = -1;
+	u8 buf[2];
+	u32 reg;
+
+	reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+	case DVBFE_DELSYS_DSS:
+		if (internal->lock) {
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+
+				stb0899_read_regs(state, STB0899_NIRM, buf, 2);
+				val = MAKEWORD16(buf[0], buf[1]);
+
+				*snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val);
+				dprintk(verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n",
+					buf[0], buf[1], val, *snr);
+			}
+		}
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1);
+			quant = STB0899_GETFIELD(UWP_ESN0_QUANT, reg);
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2);
+			est = STB0899_GETFIELD(ESN0_EST, reg);
+			if (est == 1)
+				val = 301; /* C/N = 30.1 dB */
+			else if (est == 2)
+				val = 270; /* C/N = 27.0 dB */
+			else {
+				/* quantn = 100 * log(quant^2) */
+				quantn = stb0899_table_lookup(stb0899_quant_tab, ARRAY_SIZE(stb0899_quant_tab) - 1, quant * 100);
+				/* estn = 100 * log(est) */
+				estn = stb0899_table_lookup(stb0899_est_tab, ARRAY_SIZE(stb0899_est_tab) - 1, est);
+				/* snr(dBm/10) = -10*(log(est)-log(quant^2)) => snr(dBm/10) = (100*log(quant^2)-100*log(est))/10 */
+				val = (quantn - estn) / 10;
+			}
+			*snr = val;
+			dprintk(verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm",
+				quant, quantn, est, estn, val);
+		}
+		break;
+	default:
+		dprintk(verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		break;
+	}
+
+	return 0;
+}
+
+static int stb0899_read_status(struct dvb_frontend *fe, enum fe_status *status)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+	u8 reg;
+	*status = 0;
+
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+	case DVBFE_DELSYS_DSS:
+		dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S/DSS");
+		if (internal->lock) {
+			reg  = stb0899_read_reg(state, STB0899_VSTATUS);
+			if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) {
+				dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK");
+				*status |= FE_HAS_CARRIER | FE_HAS_LOCK;
+
+				reg = stb0899_read_reg(state, STB0899_PLPARM);
+				if (STB0899_GETFIELD(VITCURPUN, reg)) {
+					dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_VITERBI | FE_HAS_SYNC");
+					*status |= FE_HAS_VITERBI | FE_HAS_SYNC;
+				}
+			}
+		}
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S2");
+		if (internal->lock) {
+			reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2);
+			if (STB0899_GETFIELD(UWP_LOCK, reg) && STB0899_GETFIELD(CSM_LOCK, reg)) {
+				*status |= FE_HAS_CARRIER;
+				dprintk(state->verbose, FE_DEBUG, 1,
+					"UWP & CSM Lock ! ---> DVB-S2 FE_HAS_CARRIER");
+
+				reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1);
+				if (STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg)) {
+					*status |= FE_HAS_LOCK;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator Locked ! -----> DVB-S2 FE_HAS_LOCK");
+
+				}
+				if (STB0899_GETFIELD(CONTINUOUS_STREAM, reg)) {
+					*status |= FE_HAS_VITERBI;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator found VITERBI ! -----> DVB-S2 FE_HAS_VITERBI");
+				}
+				if (STB0899_GETFIELD(ACCEPTED_STREAM, reg)) {
+					*status |= FE_HAS_SYNC;
+					dprintk(state->verbose, FE_DEBUG, 1,
+						"Packet Delineator found SYNC ! -----> DVB-S2 FE_HAS_SYNC");
+				}
+			}
+		}
+		break;
+	default:
+		dprintk(verbose, FE_DEBUG, 1, "Unsupported delivery system");
+		break;
+	}
+	return 0;
+}
+
+/*
+ * stb0899_get_error
+ * viterbi error for DVB-S/DSS
+ * packet error for DVB-S2
+ * Bit Error Rate or Packet Error Rate * 10 ^ 7
+ */
+static int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	u8  lsb, msb;
+	u32 i;
+
+	*ber = 0;
+
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+	case DVBFE_DELSYS_DSS:
+		if (internal->lock) {
+			/* average 5 BER values	*/
+			for (i = 0; i < 5; i++) {
+				msleep(100);
+				lsb = stb0899_read_reg(state, STB0899_ECNT1L);
+				msb = stb0899_read_reg(state, STB0899_ECNT1M);
+				*ber += MAKEWORD16(msb, lsb);
+			}
+			*ber /= 5;
+			/* Viterbi Check	*/
+			if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) {
+				/* Error Rate		*/
+				*ber *= 9766;
+				/* ber = ber * 10 ^ 7	*/
+				*ber /= (-1 + (1 << (2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
+				*ber /= 8;
+			}
+		}
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		if (internal->lock) {
+			/* Average 5 PER values	*/
+			for (i = 0; i < 5; i++) {
+				msleep(100);
+				lsb = stb0899_read_reg(state, STB0899_ECNT1L);
+				msb = stb0899_read_reg(state, STB0899_ECNT1M);
+				*ber += MAKEWORD16(msb, lsb);
+			}
+			/* ber = ber * 10 ^ 7	*/
+			*ber *= 10000000;
+			*ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl))));
+		}
+		break;
+	default:
+		dprintk(verbose, FE_DEBUG, 1, "Unsupported delivery system");
+	}
+
+	return 0;
+}
+
+static int stb0899_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x00);
+		break;
+	case SEC_VOLTAGE_18:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
+		break;
+	case SEC_VOLTAGE_OFF:
+		stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO01CFG, 0x82);
+		stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_internal *internal = &state->internal;
+
+	u8 div;
+
+	/* wait for diseqc idle	*/
+	if (stb0899_wait_diseqc_txidle(state, 100) < 0)
+		return -ETIMEDOUT;
+
+	switch (tone) {
+	case SEC_TONE_ON:
+		div = (internal->master_clk / 100) / 5632;
+		div = (div + 5) / 10;
+		stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x66);
+		stb0899_write_reg(state, STB0899_ACRPRESC, 0x31);
+		stb0899_write_reg(state, STB0899_ACRDIV1, div);
+		break;
+	case SEC_TONE_OFF:
+		stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x20);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	int i2c_stat;
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	i2c_stat = stb0899_read_reg(state, STB0899_I2CRPT);
+	if (i2c_stat < 0)
+		goto err;
+
+	if (enable) {
+		dprintk(state->verbose, FE_DEBUG, 1, "Enabling I2C Repeater ...");
+		i2c_stat |=  STB0899_I2CTON;
+		if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0)
+			goto err;
+	}
+	return 0;
+err:
+	dprintk(state->verbose, FE_ERROR, 1, "I2C Repeater enable failed");
+	return -EREMOTEIO;
+}
+
+
+static inline void CONVERT32(u32 x, char *str)
+{
+	*str++	= (x >> 24) & 0xff;
+	*str++	= (x >> 16) & 0xff;
+	*str++	= (x >>  8) & 0xff;
+	*str++	= (x >>  0) & 0xff;
+	*str	= '\0';
+}
+
+int stb0899_get_dev_id(struct stb0899_state *state)
+{
+	u8 chip_id, release;
+	u16 id;
+	u32 demod_ver = 0, fec_ver = 0;
+	char demod_str[4] = { 0 };
+	char fec_str[4] = { 0 };
+
+	id = stb0899_read_reg(state, STB0899_DEV_ID);
+	dprintk(state->verbose, FE_DEBUG, 1, "ID reg=[0x%02x]", id);
+	chip_id = STB0899_GETFIELD(CHIP_ID, id);
+	release = STB0899_GETFIELD(CHIP_REL, id);
+
+	dprintk(state->verbose, FE_ERROR, 1, "Device ID=[%d], Release=[%d]",
+		chip_id, release);
+
+	CONVERT32(STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CORE_ID), (char *)&demod_str);
+
+	demod_ver = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_VERSION_ID);
+	dprintk(state->verbose, FE_ERROR, 1, "Demodulator Core ID=[%s], Version=[%d]", (char *) &demod_str, demod_ver);
+	CONVERT32(STB0899_READ_S2REG(STB0899_S2FEC, FEC_CORE_ID_REG), (char *)&fec_str);
+	fec_ver = STB0899_READ_S2REG(STB0899_S2FEC, FEC_VER_ID_REG);
+	if (! (chip_id > 0)) {
+		dprintk(state->verbose, FE_ERROR, 1, "couldn't find a STB 0899");
+
+		return -ENODEV;
+	}
+	dprintk(state->verbose, FE_ERROR, 1, "FEC Core ID=[%s], Version=[%d]", (char*) &fec_str, fec_ver);
+
+	return 0;
+}
+
+static const struct dvbfe_info dvbs_info	= {
+	.name					= "STB0899 DVB-S",
+	.delivery				= DVBFE_DELSYS_DVBS,
+	.delsys					= {
+		.dvbs.modulation		= DVBFE_MOD_QPSK,
+		.dvbs.fec			= DVBFE_FEC_1_2	| DVBFE_FEC_2_3 |
+						  DVBFE_FEC_3_4	| DVBFE_FEC_5_6 |
+						  DVBFE_FEC_6_7
+	},
+
+	.frequency_min				= 950000,
+	.frequency_max				= 2150000,
+	.frequency_step				= 0,
+	.symbol_rate_min			= 1000000,
+	.symbol_rate_max			= 45000000,
+	.symbol_rate_tolerance			= 0
+};
+
+static const struct dvbfe_info dss_info		= {
+	.name					= "STB0899 DSS",
+	.delivery				= DVBFE_DELSYS_DSS,
+	.delsys					= {
+		.dss.modulation			= DVBFE_MOD_BPSK | DVBFE_MOD_QPSK,
+		.dss.fec			= DVBFE_FEC_1_2	 | DVBFE_FEC_2_3 |
+						  DVBFE_FEC_3_4	 | DVBFE_FEC_5_6 |
+						  DVBFE_FEC_6_7
+	},
+
+	.frequency_min				= 950000,
+	.frequency_max				= 2150000,
+	.frequency_step				= 0,
+	.symbol_rate_min			= 1000000,
+	.symbol_rate_max			= 45000000,
+	.symbol_rate_tolerance			= 0
+};
+
+static const struct dvbfe_info dvbs2_info	= {
+	.name					= "STB0899 DVB-S2",
+	.delivery				= DVBFE_DELSYS_DVBS2,
+	.delsys					= {
+		.dvbs2.modulation		= DVBFE_MOD_QPSK   | DVBFE_MOD_8PSK |
+						  DVBFE_MOD_16APSK | DVBFE_MOD_32APSK,
+
+		.dvbs2.fec			= DVBFE_FEC_1_4	| DVBFE_FEC_1_3 |
+						  DVBFE_FEC_2_5	| DVBFE_FEC_1_2 |
+						  DVBFE_FEC_3_5	| DVBFE_FEC_2_3 |
+						  DVBFE_FEC_3_4	| DVBFE_FEC_4_5 |
+						  DVBFE_FEC_5_6	| DVBFE_FEC_8_9 |
+						  DVBFE_FEC_9_10,
+	},
+
+	.frequency_min		= 950000,
+	.frequency_max		= 2150000,
+	.frequency_step		= 0,
+	.symbol_rate_min	= 1000000,
+	.symbol_rate_max	= 45000000,
+	.symbol_rate_tolerance	= 0
+};
+
+static int stb0899_get_info(struct dvb_frontend *fe, struct dvbfe_info *fe_info)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+
+	dprintk(verbose, FE_DEBUG, 1, "Get Info");
+
+	state->delsys = fe_info->delivery;
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+		dprintk(verbose, FE_ERROR, 1, "Querying DVB-S info");
+		memcpy(fe_info, &dvbs_info, sizeof (struct dvbfe_info));
+		break;
+	case DVBFE_DELSYS_DSS:
+		dprintk(verbose, FE_ERROR, 1, "Querying DSS info");
+		memcpy(fe_info, &dss_info, sizeof (struct dvbfe_info));
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		dprintk(verbose, FE_ERROR, 1, "Querying DVB-S2 info");
+		memcpy(fe_info, &dvbs2_info, sizeof (struct dvbfe_info));
+		break;
+	default:
+		dprintk(verbose, FE_ERROR, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+	dprintk(verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys);
+
+	return 0;
+}
+
+static int stb0899_get_delsys(struct dvb_frontend *fe, enum dvbfe_delsys *fe_delsys)
+{
+	*fe_delsys = DVBFE_DELSYS_DVBS | DVBFE_DELSYS_DSS | DVBFE_DELSYS_DVBS2;
+
+	return 0;
+}
+
+void stb0899_set_delsys(struct stb0899_state *state)
+{
+	u8 reg;
+	u8 stop_clk[2];
+
+	stop_clk[0] = stb0899_read_reg(state, STB0899_STOPCLK1);
+	stop_clk[1] = stb0899_read_reg(state, STB0899_STOPCLK2);
+
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+		dprintk(verbose, FE_DEBUG, 1, "Delivery System -- DVB-S");
+		/* FECM/Viterbi ON	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xb1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x40);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x42);
+		stb0899_write_reg(state, STB0899_TSLPL, 0x12);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		/* FECM/Viterbi OFF	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 0);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xb1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x42);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x40);
+		stb0899_write_reg(state, STB0899_TSLPL, 0x02);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 0);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 0);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 0);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 0);
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 0);
+		break;
+	case DVBFE_DELSYS_DSS:
+		/* FECM/Viterbi ON	*/
+		reg = stb0899_read_reg(state, STB0899_FECM);
+		STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 1);
+		STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1);
+		stb0899_write_reg(state, STB0899_FECM, reg);
+
+		stb0899_write_reg(state, STB0899_RSULC, 0xa1);
+		stb0899_write_reg(state, STB0899_TSULC, 0x61);
+		stb0899_write_reg(state, STB0899_RSLLC, 0x42);
+
+		reg = stb0899_read_reg(state, STB0899_TSTRES);
+		STB0899_SETFIELD_VAL(FRESLDPC, reg, 1);
+		stb0899_write_reg(state, STB0899_TSTRES, reg);
+
+		STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1);
+		STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1);
+		STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1);
+
+		STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0);
+
+		STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1);
+		break;
+	default:
+		dprintk(verbose, FE_ERROR, 1, "Unsupported delivery system");
+		break;
+	}
+	STB0899_SETFIELD_VAL(STOP_CKADCI108, stop_clk[0], 0);
+	stb0899_write_regs(state, STB0899_STOPCLK1, stop_clk, 2);
+}
+
+/*
+ * stb0899_set_iterations
+ * set the LDPC iteration scale function
+ */
+static void stb0899_set_iterations(struct stb0899_state *state)
+{
+	struct stb0899_internal *internal = &state->internal;
+	struct stb0899_config *config = state->config;
+
+	s32 iter_scale;
+	u32 reg;
+
+	iter_scale = 17 * (internal->master_clk / 1000);
+	iter_scale += 410000;
+	iter_scale /= (internal->srate / 1000000);
+	iter_scale /= 1000;
+
+	if (iter_scale > config->ldpc_max_iter)
+		iter_scale = config->ldpc_max_iter;
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, MAX_ITER);
+	STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale);
+	stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg);
+}
+
+static enum dvbfe_search stb0899_search(struct dvb_frontend *fe, struct dvbfe_params *params)
+{
+	struct stb0899_state *state = fe->demodulator_priv;
+	struct stb0899_params *i_params = &state->params;
+	struct stb0899_internal *internal = &state->internal;
+
+	u32 SearchRange, gain;
+
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+		dprintk(verbose, FE_ERROR, 1, "set DVB-S params");
+		i_params->freq	= params->frequency;
+		i_params->srate	= params->delsys.dvbs.symbol_rate;
+		break;
+	case DVBFE_DELSYS_DSS:
+		dprintk(verbose, FE_ERROR, 1, "set DSS params");
+		i_params->freq	= params->frequency;
+		i_params->srate	= params->delsys.dss.symbol_rate;
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		dprintk(verbose, FE_ERROR, 1, "set DVB-S2 params");
+		i_params->freq	= params->frequency;
+		i_params->srate	= params->delsys.dvbs2.symbol_rate;
+		break;
+	default:
+		dprintk(verbose, FE_ERROR, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+	dprintk(verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys);
+
+//	SearchRange = 3000000; /* Search Bandwidth (3 Mhz, was initially 10  Mhz)	*/
+	SearchRange = 10000000; /* Search Bandwidth (3 Mhz, was initially 10  Mhz)	*/
+	dprintk(verbose, FE_DEBUG, 1, "Frequency=%d, Srate=%d", i_params->freq, i_params->srate);
+	/* checking Search Range is meaningless for a fixed 3 Mhz			*/
+	if (INRANGE(i_params->srate, 1000000, 45000000)) {
+		dprintk(verbose, FE_DEBUG, 1, "Parameters IN RANGE");
+		stb0899_set_delsys(state);
+
+		if (state->config->tuner_set_rfsiggain) {
+			if (internal->srate > 15000000)
+				gain =  8;	/* 15Mb < srate < 45Mb, gain = 8dB	*/
+			else if (internal->srate > 5000000)
+				gain = 12;	/*  5Mb < srate < 15Mb, gain = 12dB	*/
+			else
+				gain = 14;	/*  1Mb < srate <  5Mb, gain = 14db	*/
+			state->config->tuner_set_rfsiggain(fe, gain);
+		}
+
+		if (i_params->srate <= 5000000)
+			stb0899_set_mclk(state, 76500000);
+		else
+			stb0899_set_mclk(state, 99000000);
+
+		switch (state->delsys) {
+		case DVBFE_DELSYS_DVBS:
+		case DVBFE_DELSYS_DSS:
+			dprintk(verbose, FE_DEBUG, 1, "DVB-S delivery system");
+			internal->freq	= i_params->freq;
+			internal->srate	= i_params->srate;
+			/*
+			 * search = user search range +
+			 *	    500Khz +
+			 *	    2 * Tuner_step_size +
+			 *	    10% of the symbol rate
+			 */
+			internal->srch_range	= SearchRange + 1500000 + (i_params->srate / 5);
+			internal->derot_percent	= 30;
+
+			/* What to do for tuners having no bandwidth setup ?	*/
+			if (state->config->tuner_set_bandwidth)
+				state->config->tuner_set_bandwidth(fe, (13 * (stb0899_carr_width(state) + 10000000)) / 10);
+			if (state->config->tuner_get_bandwidth)
+				state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
+			/* Set DVB-S1 AGC		*/
+			stb0899_write_reg(state, STB0899_AGCRFCFG, 0x11);
+
+			/* Run the search algorithm	*/
+			dprintk(verbose, FE_DEBUG, 1, "running DVB-S search algo ..");
+			if (stb0899_dvbs_algo(state)	== RANGEOK) {
+				internal->lock		= 1;
+				dprintk(verbose, FE_DEBUG, 1,
+					"-------------------------------------> DVB-S LOCK !");
+
+//				stb0899_write_reg(state, STB0899_ERRCTRL1, 0x3d); /* Viterbi Errors	*/
+//				internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
+//				internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
+//				dprintk(verbose, FE_DEBUG, 1, "VSTATUS=0x%02x", internal->v_status);
+//				dprintk(verbose, FE_DEBUG, 1, "ERR_CTRL=0x%02x", internal->err_ctrl);
+				
+				return DVBFE_ALGO_SEARCH_SUCCESS;
+			} else {
+				internal->lock		= 0;
+
+				return DVBFE_ALGO_SEARCH_FAILED;
+			}
+			break;
+		case DVBFE_DELSYS_DVBS2:
+			internal->freq			= i_params->freq;
+			internal->srate			= i_params->srate;
+			internal->srch_range		= SearchRange;
+
+			if (state->config->tuner_set_bandwidth)
+				state->config->tuner_set_bandwidth(fe, (stb0899_carr_width(state) + 10000000));
+			if (state->config->tuner_get_bandwidth)
+				state->config->tuner_get_bandwidth(fe, &internal->tuner_bw);
+
+//			pParams->SpectralInv		= pSearch->IQ_Inversion;
+
+			/* Set DVB-S2 AGC		*/
+			stb0899_write_reg(state, STB0899_AGCRFCFG, 0x1c);
+
+			/* Set IterScale =f(MCLK,SYMB)	*/
+			stb0899_set_iterations(state);
+
+			/* Run the search algorithm	*/
+			dprintk(verbose, FE_DEBUG, 1, "running DVB-S2 search algo ..");
+			if (stb0899_dvbs2_algo(state)	== DVBS2_FEC_LOCK) {
+				internal->lock		= 1;
+				dprintk(verbose, FE_DEBUG, 1,
+					"-------------------------------------> DVB-S2 LOCK !");
+
+//				stb0899_write_reg(state, STB0899_ERRCTRL1, 0xb6); /* Packet Errors	*/
+//				internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS);
+//				internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1);
+
+				return DVBFE_ALGO_SEARCH_SUCCESS;
+			} else {
+				internal->lock		= 0;
+
+				return DVBFE_ALGO_SEARCH_FAILED;
+			}
+			break;
+		default:
+			dprintk(verbose, FE_ERROR, 1, "Unsupported delivery system");
+			return DVBFE_ALGO_SEARCH_INVALID;
+		}
+	}
+
+	return DVBFE_ALGO_SEARCH_ERROR;
+}
+
+static enum stb0899_status stb0899_track_carrier(struct stb0899_state *state)
+{
+	u8 reg;
+
+	reg = stb0899_read_reg(state, STB0899_DSTATUS);
+	dprintk(verbose, FE_DEBUG, 1, "--------------------> STB0899_DSTATUS=[0x%02x]", reg);
+	if (STB0899_GETFIELD(CARRIER_FOUND, reg)) {
+		dprintk(verbose, FE_DEBUG, 1, "-------------> CARRIEROK !");
+		return CARRIEROK;
+	} else {
+		dprintk(verbose, FE_DEBUG, 1, "-------------> NOCARRIER !");
+		return NOCARRIER;
+	}
+
+	return NOCARRIER;
+}
+
+static enum stb0899_status stb0899_get_ifagc(struct stb0899_state *state)
+{
+	u8 reg;
+
+	reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STATUS);
+	dprintk(verbose, FE_DEBUG, 1, "DMD_STATUS=[0x%02x]", reg);
+	if (STB0899_GETFIELD(IF_AGC_LOCK, reg)) {
+		dprintk(verbose, FE_DEBUG, 1, "------------->IF AGC LOCKED !");
+		return AGC1OK;
+	} else {
+		dprintk(verbose, FE_DEBUG, 1, "------------->IF AGC LOCK LOST !");
+		return NOAGC1;
+	}
+
+	return NOAGC1;
+}
+
+static int stb0899_get_s1fec(struct stb0899_internal *internal, enum dvbfe_fec *fec)
+{
+	switch (internal->fecrate) {
+	case STB0899_FEC_1_2:
+		*fec = DVBFE_FEC_1_2;
+		break;
+	case STB0899_FEC_2_3:
+		*fec = DVBFE_FEC_2_3;
+		break;
+	case STB0899_FEC_3_4:
+		*fec = DVBFE_FEC_3_4;
+		break;
+	case STB0899_FEC_5_6:
+		*fec = DVBFE_FEC_5_6;
+		break;
+	case STB0899_FEC_6_7:
+		*fec = DVBFE_FEC_6_7;
+		break;
+	case STB0899_FEC_7_8:
+		*fec = DVBFE_FEC_7_8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_get_modcod(struct stb0899_internal *internal, struct dvbs2_params *params)
+{
+	switch (internal->modcod) {
+	case STB0899_DUMMY_PLF:
+		params->modulation	= DVBFE_MOD_NONE;
+		params->fec		= DVBFE_FEC_NONE;
+		break;
+	case STB0899_QPSK_14:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_1_4;
+		break;
+	case STB0899_QPSK_13:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_1_3;
+		break;
+	case STB0899_QPSK_25:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_2_5;
+		break;
+	case STB0899_QPSK_12:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_1_2;
+		break;
+	case STB0899_QPSK_35:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_3_5;
+		break;
+	case STB0899_QPSK_23:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_2_3;
+		break;
+	case STB0899_QPSK_34:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_3_4;
+		break;
+	case STB0899_QPSK_45:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_4_5;
+		break;
+	case STB0899_QPSK_56:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_5_6;
+		break;
+	case STB0899_QPSK_89:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_8_9;
+		break;
+	case STB0899_QPSK_910:
+		params->modulation	= DVBFE_MOD_QPSK;
+		params->fec		= DVBFE_FEC_9_10;
+		break;
+	case STB0899_8PSK_35:
+		params->modulation	= DVBFE_MOD_8PSK;
+		params->fec		= DVBFE_FEC_3_5;
+		break;
+	case STB0899_8PSK_23:
+		params->modulation	= DVBFE_MOD_8PSK;
+		params->fec		= DVBFE_FEC_2_3;
+		break;
+	case STB0899_8PSK_34:
+		params->modulation	= DVBFE_MOD_8PSK;
+		params->fec		= DVBFE_FEC_3_4;
+		break;
+	case STB0899_8PSK_56:
+		params->modulation	= DVBFE_MOD_8PSK;
+		params->fec		= DVBFE_FEC_5_6;
+		break;
+	case STB0899_8PSK_89:
+		params->modulation	= DVBFE_MOD_8PSK;
+		params->fec		= DVBFE_FEC_8_9;
+		break;
+	case STB0899_8PSK_910:
+		params->modulation	= DVBFE_MOD_8PSK;
+		params->fec		= DVBFE_FEC_9_10;
+		break;
+	case STB0899_16APSK_23:
+		params->modulation	= DVBFE_MOD_16APSK;
+		params->fec		= DVBFE_FEC_2_3;
+		break;
+	case STB0899_16APSK_34:
+		params->modulation	= DVBFE_MOD_16APSK;
+		params->fec		= DVBFE_FEC_3_4;
+		break;
+	case STB0899_16APSK_45:
+		params->modulation	= DVBFE_MOD_16APSK;
+		params->fec		= DVBFE_FEC_4_5;
+		break;
+	case STB0899_16APSK_56:
+		params->modulation	= DVBFE_MOD_16APSK;
+		params->fec		= DVBFE_FEC_5_6;
+		break;
+	case STB0899_16APSK_89:
+		params->modulation	= DVBFE_MOD_16APSK;
+		params->fec		= DVBFE_FEC_8_9;
+		break;
+	case STB0899_16APSK_910:
+		params->modulation	= DVBFE_MOD_16APSK;
+		params->fec		= DVBFE_FEC_9_10;
+		break;
+	case STB0899_32APSK_34:
+		params->modulation	= DVBFE_MOD_32APSK;
+		params->fec		= DVBFE_FEC_3_4;
+		break;
+	case STB0899_32APSK_45:
+		params->modulation	= DVBFE_MOD_32APSK;
+		params->fec		= DVBFE_FEC_4_5;
+		break;
+	case STB0899_32APSK_56:
+		params->modulation	= DVBFE_MOD_32APSK;
+		params->fec		= DVBFE_FEC_5_6;
+		break;
+	case STB0899_32APSK_89:
+		params->modulation	= DVBFE_MOD_32APSK;
+		params->fec		= DVBFE_FEC_8_9;
+		break;
+	case STB0899_32APSK_910:
+		params->modulation	= DVBFE_MOD_32APSK;
+		params->fec		= DVBFE_FEC_9_10;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * stb0899_track
+ * periodically check the signal level against a specified
+ * threshold level and perform derotator centering.
+ * called once we have a lock from a succesful search
+ * event.
+ *
+ * Will be called periodically called to maintain the
+ * lock.
+ *
+ * Will be used to get parameters as well as info from
+ * the decoded baseband header
+ *
+ * Once a new lock has established, the internal state
+ * frequency (internal->freq) is updated
+ */
+static int stb0899_track(struct dvb_frontend *fe, struct dvbfe_params *params)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+		dprintk(verbose, FE_DEBUG, 1, "Tracking DVB-S state");
+		if (stb0899_track_carrier(state) == CARRIEROK) {
+			params->frequency			= internal->freq;
+			params->inversion			= internal->inversion;
+			params->delivery			= state->delsys;
+			params->delsys.dvbs.symbol_rate		= internal->srate;
+			params->delsys.dvbs.modulation		= DVBFE_MOD_QPSK;
+			stb0899_get_s1fec(internal, &params->delsys.dvbs.fec);
+		}
+		break;
+	case DVBFE_DELSYS_DSS:
+		dprintk(verbose, FE_DEBUG, 1, "Tracking DSS state");
+		if (stb0899_track_carrier(state) == CARRIEROK) {
+			params->frequency			= internal->freq;
+			params->inversion			= internal->inversion;
+			params->delivery			= state->delsys;
+			params->delsys.dss.symbol_rate		= internal->srate;
+			params->delsys.dss.modulation		= DVBFE_MOD_QPSK;
+			stb0899_get_s1fec(internal, &params->delsys.dss.fec);
+		}
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		dprintk(verbose, FE_DEBUG, 1, "Tracking DVB-S2 state");
+		if (stb0899_get_ifagc(state) == AGC1OK) {
+			params->frequency			= internal->freq;
+			params->inversion			= internal->inversion;
+			params->delivery			= state->delsys;
+			params->delsys.dvbs2.symbol_rate	= internal->srate;
+			stb0899_get_modcod(internal, &params->delsys.dvbs2);
+			params->delsys.dvbs2.rolloff		= internal->rolloff;
+			params->delsys.dvbs2.matype_1		= stb0899_read_reg(state, STB0899_MATSTRL);
+			params->delsys.dvbs2.matype_2		= stb0899_read_reg(state, STB0899_MATSTRM);
+			params->delsys.dvbs2.upl_1		= stb0899_read_reg(state, STB0899_UPLSTRL);
+			params->delsys.dvbs2.upl_2		= stb0899_read_reg(state, STB0899_UPLSTRM);
+			params->delsys.dvbs2.dfl_1		= stb0899_read_reg(state, STB0899_DFLSTRL);
+			params->delsys.dvbs2.dfl_2		= stb0899_read_reg(state, STB0899_DFLSTRM);
+			params->delsys.dvbs2.sync		= stb0899_read_reg(state, STB0899_SYNCSTR);
+			params->delsys.dvbs2.syncd_1		= stb0899_read_reg(state, STB0899_SYNCDSTRL);
+			params->delsys.dvbs2.syncd_2		= stb0899_read_reg(state, STB0899_SYNCDSTRM);
+		}
+		break;
+	default:
+		dprintk(verbose, FE_ERROR, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int stb0899_get_params(struct dvb_frontend *fe, struct dvbfe_params *params)
+{
+	struct stb0899_state *state		= fe->demodulator_priv;
+	struct stb0899_internal *internal	= &state->internal;
+
+	params->frequency			= internal->freq;
+	params->inversion			= internal->inversion;
+	params->delivery			= state->delsys;
+	switch (state->delsys) {
+	case DVBFE_DELSYS_DVBS:
+		dprintk(verbose, FE_DEBUG, 1, "Get DVB-S params");
+		params->delsys.dvbs.symbol_rate		= internal->srate;
+		params->delsys.dvbs.modulation		= DVBFE_MOD_QPSK;
+		break;
+	case DVBFE_DELSYS_DSS:
+		dprintk(verbose, FE_DEBUG, 1, "Get DSS params");
+		params->delsys.dss.symbol_rate		= internal->srate;
+		params->delsys.dss.modulation		= DVBFE_MOD_QPSK;
+		
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		dprintk(verbose, FE_DEBUG, 1, "Get DVB-S2 params");
+		params->delsys.dvbs2.symbol_rate	= internal->srate;
+		break;
+	default:
+		dprintk(verbose, FE_ERROR, 1, "Unsupported delivery system");
+		return -EINVAL;
+	}
+
+	return 0;
+} 
+
+static enum dvbfe_algo stb0899_frontend_algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+
+static struct dvb_frontend_ops stb0899_ops = {
+
+	.info = {
+		.name			= "STB0899 Multistandard",
+	},
+
+	.release			= stb0899_release,
+	.init				= stb0899_init,
+	.sleep				= stb0899_sleep,
+//	.wakeup				= stb0899_wakeup,
+
+	.i2c_gate_ctrl			= stb0899_i2c_gate_ctrl,
+	.get_info			= stb0899_get_info,
+	.get_delsys			= stb0899_get_delsys,
+
+	.get_frontend_algo		= stb0899_frontend_algo,
+	.search				= stb0899_search,
+	.track				= stb0899_track,
+	.get_params			= stb0899_get_params,
+
+	.read_status			= stb0899_read_status,
+	.read_snr			= stb0899_read_snr,
+	.read_signal_strength		= stb0899_read_signal_strength,
+	.read_status			= stb0899_read_status,
+	.read_ber			= stb0899_read_ber,
+
+	.set_voltage			= stb0899_set_voltage,
+	.set_tone			= stb0899_set_tone,
+
+	.diseqc_send_master_cmd		= stb0899_send_diseqc_msg,
+	.diseqc_recv_slave_reply	= stb0899_recv_slave_reply,
+	.diseqc_send_burst		= stb0899_send_diseqc_burst,
+};
+
+struct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c)
+{
+	struct stb0899_state *state = NULL;
+
+	state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->verbose				= verbose;
+	state->config				= config;
+	state->i2c				= i2c;
+	state->frontend.ops			= stb0899_ops;
+	state->frontend.demodulator_priv	= state;
+	state->delsys                           = DVBFE_DELSYS_DVBS;
+
+	stb0899_wakeup(&state->frontend);
+	if (stb0899_get_dev_id(state) == -ENODEV) {
+		printk("%s: Exiting .. !\n", __func__);
+		goto error;
+	}
+
+	printk("%s: Attaching STB0899 \n", __func__);
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stb0899_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STB0899 Multi-Std frontend");
+MODULE_LICENSE("GPL");
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_drv.h linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_drv.h
--- linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_drv.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_drv.h	2007-07-28 01:17:12.000000000 +0200
@@ -0,0 +1,94 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB0899_DRV_H
+#define __STB0899_DRV_H
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "dvb_frontend.h"
+
+#define STB0899_TSMODE_SERIAL		1
+#define STB0899_CLKPOL_FALLING		2
+#define STB0899_CLKNULL_PARITY		3
+#define STB0899_SYNC_FORCED		4
+#define STB0899_FECMODE_DSS		5
+
+struct stb0899_s1_reg {
+	u16	address;
+	u8	data;
+};
+
+struct stb0899_s2_reg {
+	u16	offset;
+	u32	base_address;
+	u32	data;
+};
+
+struct stb0899_config {
+	const struct stb0899_s1_reg	*init_dev;
+	const struct stb0899_s2_reg	*init_s2_demod;
+	const struct stb0899_s1_reg	*init_s1_demod;
+	const struct stb0899_s2_reg	*init_s2_fec;
+	const struct stb0899_s1_reg	*init_tst;
+
+	u32	xtal_freq;
+
+	u8	demod_address;
+	u8	ts_output_mode;
+	u8	block_sync_mode;
+	u8	ts_pfbit_toggle;
+
+	u8	clock_polarity;
+	u8	data_clk_parity;
+	u8	fec_mode;
+	u8	data_output_ctl;
+	u8	data_fifo_mode;
+	u8	out_rate_comp;
+	u8	i2c_repeater;
+	int	inversion;
+
+	u32	esno_ave;
+	u32	esno_quant;
+	u32	avframes_coarse;
+	u32	avframes_fine;
+	u32	miss_threshold;
+	u32	uwp_threshold_acq;
+	u32	uwp_threshold_track;
+	u32	uwp_threshold_sof;
+	u32	sof_search_timeout;
+
+	u32	btr_nco_bits;
+	u32	btr_gain_shift_offset;
+	u32	crl_nco_bits;
+	u32	ldpc_max_iter;
+
+	int (*tuner_set_frequency)(struct dvb_frontend *fe, u32 frequency);
+	int (*tuner_get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+	int (*tuner_set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+	int (*tuner_get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+	int (*tuner_set_rfsiggain)(struct dvb_frontend *fe, u32 rf_gain);
+};
+
+extern struct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c);
+
+#endif
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_priv.h linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_priv.h
--- linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_priv.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_priv.h	2007-07-28 01:17:12.000000000 +0200
@@ -0,0 +1,279 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB0899_PRIV_H
+#define __STB0899_PRIV_H
+
+#include "dvb_frontend.h"
+#include "stb0899_drv.h"
+
+#define FE_ERROR				0
+#define FE_NOTICE				1
+#define FE_INFO					2
+#define FE_DEBUG				3
+#define FE_DEBUGREG				4
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((x > FE_ERROR) && (x > y))					\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((x > FE_NOTICE) && (x > y))					\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((x > FE_INFO) && (x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((x > FE_DEBUG) && (x > y))					\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (x > y)								\
+			printk(format, ##arg);						\
+	}										\
+} while(0)
+
+#define INRANGE(val, x, y)			(((x <= val) && (val <= y)) ||		\
+						 ((y <= val) && (val <= x)) ? 1 : 0)
+
+#define BYTE0					0
+#define BYTE1					8
+#define BYTE2					16
+#define BYTE3					24
+
+#define GETBYTE(x, y)				(((x) >> (y)) & 0xff)
+#define MAKEWORD32(a, b, c, d)			(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+#define MAKEWORD16(a, b)			(((a) << 8) | (b))
+
+#define MIN(x, y)				((x) <= (y) ? (x) : (y))
+#define MAX(x, y)				((x) >= (y) ? (x) : (y))
+#define ABS(x)					((x) >= 0 ? (x) : -(x))
+
+#define LSB(x)					((x & 0xff))
+#define MSB(y)					((y >> 8) & 0xff)
+
+
+#define STB0899_GETFIELD(bitf, val)		((val >> STB0899_OFFST_##bitf) & ((1 << STB0899_WIDTH_##bitf) - 1))
+
+
+#define STB0899_SETFIELD(mask, val, width, offset)      (mask & (~(((1 << width) - 1) <<	\
+							 offset))) | ((val &			\
+							 ((1 << width) - 1)) << offset)
+
+#define STB0899_SETFIELD_VAL(bitf, mask, val)	(mask = (mask & (~(((1 << STB0899_WIDTH_##bitf) - 1) <<\
+							 STB0899_OFFST_##bitf))) | \
+							 (val << STB0899_OFFST_##bitf))
+
+
+enum stb0899_status {
+	NOAGC1	= 0,
+	AGC1OK,
+	NOTIMING,
+	ANALOGCARRIER,
+	TIMINGOK,
+	NOAGC2,
+	AGC2OK,
+	NOCARRIER,
+	CARRIEROK,
+	NODATA,
+	FALSELOCK,
+	DATAOK,
+	OUTOFRANGE,
+	RANGEOK,
+	DVBS2_DEMOD_LOCK,
+	DVBS2_DEMOD_NOLOCK,
+	DVBS2_FEC_LOCK,
+	DVBS2_FEC_NOLOCK
+};
+
+enum stb0899_modcod {
+	STB0899_DUMMY_PLF,
+	STB0899_QPSK_14,
+	STB0899_QPSK_13,
+	STB0899_QPSK_25,
+	STB0899_QPSK_12,
+	STB0899_QPSK_35,
+	STB0899_QPSK_23,
+	STB0899_QPSK_34,
+	STB0899_QPSK_45,
+	STB0899_QPSK_56,
+	STB0899_QPSK_89,
+	STB0899_QPSK_910,
+	STB0899_8PSK_35,
+	STB0899_8PSK_23,
+	STB0899_8PSK_34,
+	STB0899_8PSK_56,
+	STB0899_8PSK_89,
+	STB0899_8PSK_910,
+	STB0899_16APSK_23,
+	STB0899_16APSK_34,
+	STB0899_16APSK_45,
+	STB0899_16APSK_56,
+	STB0899_16APSK_89,
+	STB0899_16APSK_910,
+	STB0899_32APSK_34,
+	STB0899_32APSK_45,
+	STB0899_32APSK_56,
+	STB0899_32APSK_89,
+	STB0899_32APSK_910
+};
+
+enum stb0899_frame {
+	STB0899_LONG_FRAME,
+	STB0899_SHORT_FRAME
+};
+
+enum stb0899_inversion {
+	IQ_SWAP_OFF	= 0,
+	IQ_SWAP_ON,
+	IQ_SWAP_AUTO
+};
+
+enum stb0899_alpha {
+	RRC_20,
+	RRC_25,
+	RRC_35
+};
+
+struct stb0899_tab {
+	s32 real;
+	s32 read;
+};
+
+enum stb0899_fec {
+	STB0899_FEC_1_2			= 13,
+	STB0899_FEC_2_3			= 18,
+	STB0899_FEC_3_4			= 21,
+	STB0899_FEC_5_6			= 24,
+	STB0899_FEC_6_7			= 25,
+	STB0899_FEC_7_8			= 26
+};
+
+struct stb0899_params {
+	u32	freq;					/* Frequency	*/
+	u32	srate;					/* Symbol rate	*/
+	enum dvbfe_fec fecrate;
+};
+
+struct stb0899_internal {
+	u32			master_clk;
+	u32			freq;			/* Demod internal Frequency		*/
+	u32			srate;			/* Demod internal Symbol rate		*/
+	enum stb0899_fec	fecrate;		/* Demod internal FEC rate		*/
+	u32			srch_range;		/* Demod internal Search Range		*/
+	u32			sub_range;		/* Demod current sub range (Hz)		*/
+	u32			tuner_step;		/* Tuner step (Hz)			*/
+	u32			tuner_offst;		/* Relative offset to carrier (Hz)	*/
+	u32			tuner_bw;		/* Current bandwidth of the tuner (Hz)	*/
+
+	s32			mclk;			/* Masterclock Divider factor (binary)	*/
+	s32			rolloff;		/* Current RollOff of the filter (x100)	*/
+
+	s16			derot_freq;		/* Current derotator frequency (Hz)	*/
+	s16			derot_percent;
+
+	s16			direction;		/* Current derotator search direction	*/
+	s16			derot_step;		/* Derotator step (binary value)	*/
+	s16			t_timing;		/* Timing loop time constant (ms)	*/
+	s16			t_derot;		/* Derotator time constant (ms)		*/
+	s16			t_data;			/* Data recovery time constant (ms)	*/
+	s16			sub_dir;		/* Direction of the next sub range	*/
+
+	s16			t_agc1;			/* Agc1 time constant (ms)		*/
+	s16			t_agc2;			/* Agc2 time constant (ms)		*/
+
+	u32			lock;			/* Demod internal lock state		*/
+	enum stb0899_status	status;			/* Demod internal status		*/
+
+	/* DVB-S2 */
+	s32			agc_gain;		/* RF AGC Gain				*/
+	s32			center_freq;		/* Nominal carrier frequency		*/
+	s32			av_frame_coarse;	/* Coarse carrier freq search frames	*/
+	s32			av_frame_fine;		/* Fine carrier freq search frames	*/
+
+	s16			step_size;		/* Carrier frequency search step size	*/
+
+	enum stb0899_alpha	rrc_alpha;
+	enum stb0899_inversion	inversion;
+	enum stb0899_modcod	modcod;
+	u8			pilots;			/* Pilots found				*/
+
+	enum stb0899_frame	frame_length;
+	u8			v_status;		/* VSTATUS				*/
+	u8			err_ctrl;		/* ERRCTRLn				*/
+};
+
+struct stb0899_state {
+	struct i2c_adapter		*i2c;
+	struct stb0899_config		*config;
+	struct dvb_frontend		frontend;
+
+	u32				verbose;	/* Cached module verbosity level	*/
+
+	struct stb0899_internal		internal;	/* Device internal parameters		*/
+
+	/*	cached params from API	*/
+	enum dvbfe_delsys		delsys;
+	struct stb0899_params		params;
+
+	u32				rx_freq;	/* DiSEqC 2.0 receiver freq		*/
+	struct mutex			search_lock;
+};
+/* stb0899.c		*/
+extern int stb0899_read_reg(struct stb0899_state *state,
+			    unsigned int reg);
+
+extern u32 _stb0899_read_s2reg(struct stb0899_state *state,
+			       u32 stb0899_i2cdev,
+			       u32 stb0899_base_addr,
+			       u16 stb0899_reg_offset);
+
+extern int stb0899_read_regs(struct stb0899_state *state,
+			     unsigned int reg, u8 *buf,
+			     size_t count);
+
+extern int stb0899_write_regs(struct stb0899_state *state,
+			      unsigned int reg, u8 *data,
+			      size_t count);
+
+extern int stb0899_write_reg(struct stb0899_state *state,
+			     unsigned int reg,
+			     u8 data);
+
+extern int stb0899_write_s2reg(struct stb0899_state *state,
+			       u32 stb0899_i2cdev,
+			       u32 stb0899_base_addr,
+			       u16 stb0899_reg_offset,
+			       u32 stb0899_data);
+
+#if 0
+extern int _stb0899_write_s2reg(struct stb0899_state *state,
+			        u32 stb0899_i2cdev,
+			        u32 stb0899_base_addr,
+			        u16 stb0899_reg_offset,
+			        u32 stb0899_data);
+#endif
+
+#define STB0899_READ_S2REG(DEVICE, REG) 	(_stb0899_read_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG))
+//#define STB0899_WRITE_S2REG(DEVICE, REG, DATA)	(_stb0899_write_s2reg(state, DEVICE, STB0899_BASE_##REG, STB0899_OFF0_##REG, DATA))
+
+/* stb0899_algo.c	*/
+extern enum stb0899_status stb0899_dvbs_algo(struct stb0899_state *state);
+extern enum stb0899_status stb0899_dvbs2_algo(struct stb0899_state *state);
+extern long stb0899_carr_width(struct stb0899_state *state);
+
+#endif //__STB0899_PRIV_H
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_reg.h linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_reg.h
--- linux-2.6.22.1/drivers/media/dvb/frontends/stb0899_reg.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/stb0899_reg.h	2007-07-28 01:17:12.000000000 +0200
@@ -0,0 +1,2018 @@
+/*
+	STB0899 Multistandard Frontend driver
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB0899_REG_H
+#define __STB0899_REG_H
+
+/*	S1	*/
+#define STB0899_DEV_ID				0xf000
+#define STB0899_CHIP_ID				(0x0f << 4)
+#define STB0899_OFFST_CHIP_ID			4
+#define STB0899_WIDTH_CHIP_ID			4
+#define STB0899_CHIP_REL			(0x0f << 0)
+#define STB0899_OFFST_CHIP_REL			0
+#define STB0899_WIDTH_CHIP_REL			4
+
+#define STB0899_DEMOD				0xf40e
+#define STB0899_MODECOEFF			(0x01 << 0)
+#define STB0899_OFFST_MODECOEFF			0
+#define STB0899_WIDTH_MODECOEFF			1
+
+#define STB0899_RCOMPC				0xf410
+#define STB0899_AGC1CN				0xf412
+#define STB0899_AGC1REF				0xf413
+#define STB0899_RTC				0xf417
+#define STB0899_TMGCFG				0xf418
+#define STB0899_AGC2REF				0xf419
+#define STB0899_TLSR				0xf41a
+
+#define STB0899_CFD				0xf41b
+#define STB0899_CFD_ON				(0x01 << 7)
+#define STB0899_OFFST_CFD_ON			7
+#define STB0899_WIDTH_CFD_ON			1
+
+#define STB0899_ACLC				0xf41c
+
+#define STB0899_BCLC				0xf41d
+#define STB0899_OFFST_ALGO			6
+#define STB0899_WIDTH_ALGO_QPSK2		2
+#define STB0899_ALGO_QPSK2			(2 << 6)
+#define STB0899_ALGO_QPSK1			(1 << 6)
+#define STB0899_ALGO_BPSK			(0 << 6)
+#define STB0899_OFFST_BETA			0
+#define STB0899_WIDTH_BETA			6
+
+#define STB0899_EQON				0xf41e
+#define STB0899_LDT				0xf41f
+#define STB0899_LDT2				0xf420
+#define STB0899_EQUALREF			0xf425
+#define STB0899_TMGRAMP				0xf426
+#define STB0899_TMGTHD				0xf427
+#define STB0899_IDCCOMP				0xf428
+#define STB0899_QDCCOMP				0xf429
+#define STB0899_POWERI				0xf42a
+#define STB0899_POWERQ				0xf42b
+#define STB0899_RCOMP				0xf42c
+
+#define STB0899_AGCIQIN				0xf42e
+#define STB0899_AGCIQVALUE			(0xff << 0)
+#define STB0899_OFFST_AGCIQVALUE		0
+#define STB0899_WIDTH_AGCIQVALUE		8
+
+#define STB0899_AGC2I1				0xf436
+#define STB0899_AGC2I2				0xf437
+
+#define STB0899_TLIR				0xf438
+#define STB0899_TLIR_TMG_LOCK_IND		(0xff << 0)
+#define STB0899_OFFST_TLIR_TMG_LOCK_IND		0
+#define STB0899_WIDTH_TLIR_TMG_LOCK_IND		8
+
+#define STB0899_RTF				0xf439
+#define STB0899_RTF_TIMING_LOOP_FREQ		(0xff << 0)
+#define STB0899_OFFST_RTF_TIMING_LOOP_FREQ	0
+#define STB0899_WIDTH_RTF_TIMING_LOOP_FREQ	8
+
+#define STB0899_DSTATUS				0xf43a
+#define STB0899_CARRIER_FOUND			(0x01 << 7)
+#define STB0899_OFFST_CARRIER_FOUND		7
+#define STB0899_WIDTH_CARRIER_FOUND		1
+#define STB0899_TMG_LOCK			(0x01 << 6)
+#define STB0899_OFFST_TMG_LOCK			6
+#define STB0899_WIDTH_TMG_LOCK			1
+#define STB0899_DEMOD_LOCK			(0x01 << 5)
+#define STB0899_OFFST_DEMOD_LOCK		5
+#define STB0899_WIDTH_DEMOD_LOCK		1
+#define STB0899_TMG_AUTO			(0x01 << 4)
+#define STB0899_OFFST_TMG_AUTO			4
+#define STB0899_WIDTH_TMG_AUTO			1
+#define STB0899_END_MAIN			(0x01 << 3)
+#define STB0899_OFFST_END_MAIN			3
+#define STB0899_WIDTH_END_MAIN			1
+
+#define STB0899_LDI				0xf43b
+#define STB0899_OFFST_LDI			0
+#define STB0899_WIDTH_LDI			8
+
+#define STB0899_CFRM				0xf43e
+#define STB0899_OFFST_CFRM			0
+#define STB0899_WIDTH_CFRM			8
+
+#define STB0899_CFRL				0xf43f
+#define STB0899_OFFST_CFRL			0
+#define STB0899_WIDTH_CFRL			8
+
+#define STB0899_NIRM				0xf440
+#define STB0899_OFFST_NIRM			0
+#define STB0899_WIDTH_NIRM			8
+
+#define STB0899_NIRL				0xf441
+#define STB0899_OFFST_NIRL			0
+#define STB0899_WIDTH_NIRL			8
+
+#define STB0899_ISYMB				0xf444
+#define STB0899_QSYMB				0xf445
+
+#define STB0899_SFRH				0xf446
+#define STB0899_OFFST_SFRH			0
+#define STB0899_WIDTH_SFRH			8
+
+#define STB0899_SFRM				0xf447
+#define STB0899_OFFST_SFRM			0
+#define STB0899_WIDTH_SFRM			8
+
+#define STB0899_SFRL				0xf448
+#define STB0899_OFFST_SFRL			4
+#define STB0899_WIDTH_SFRL			4
+
+#define STB0899_SFRUPH				0xf44c
+#define STB0899_SFRUPM				0xf44d
+#define STB0899_SFRUPL				0xf44e
+
+#define STB0899_EQUAI1				0xf4e0
+#define STB0899_EQUAQ1				0xf4e1
+#define STB0899_EQUAI2				0xf4e2
+#define STB0899_EQUAQ2				0xf4e3
+#define STB0899_EQUAI3				0xf4e4
+#define STB0899_EQUAQ3				0xf4e5
+#define STB0899_EQUAI4				0xf4e6
+#define STB0899_EQUAQ4				0xf4e7
+#define STB0899_EQUAI5				0xf4e8
+#define STB0899_EQUAQ5				0xf4e9
+
+#define STB0899_DSTATUS2			0xf50c
+#define STB0899_DS2_TMG_AUTOSRCH		(0x01 << 7)
+#define STB8999_OFFST_DS2_TMG_AUTOSRCH		7
+#define STB0899_WIDTH_DS2_TMG_AUTOSRCH		1
+#define STB0899_DS2_END_MAINLOOP		(0x01 << 6)
+#define STB0899_OFFST_DS2_END_MAINLOOP		6
+#define STB0899_WIDTH_DS2_END_MAINLOOP		1
+#define STB0899_DS2_CFSYNC			(0x01 << 5)
+#define STB0899_OFFST_DS2_CFSYNC		5
+#define STB0899_WIDTH_DS2_CFSYNC		1
+#define STB0899_DS2_TMGLOCK			(0x01 << 4)
+#define STB0899_OFFST_DS2_TMGLOCK		4
+#define STB0899_WIDTH_DS2_TMGLOCK		1
+#define STB0899_DS2_DEMODWAIT			(0x01 << 3)
+#define STB0899_OFFST_DS2_DEMODWAIT		3
+#define STB0899_WIDTH_DS2_DEMODWAIT		1
+#define STB0899_DS2_FECON			(0x01 << 1)
+#define STB0899_OFFST_DS2_FECON			1
+#define STB0899_WIDTH_DS2_FECON			1
+
+/*	S1 FEC	*/
+#define STB0899_VSTATUS				0xf50d
+#define STB0899_VSTATUS_VITERBI_ON		(0x01 << 7)
+#define STB0899_OFFST_VSTATUS_VITERBI_ON	7
+#define STB0899_WIDTH_VSTATUS_VITERBI_ON	1
+#define STB0899_VSTATUS_END_LOOPVIT		(0x01 << 6)
+#define STB0899_OFFST_VSTATUS_END_LOOPVIT	6
+#define STB0899_WIDTH_VSTATUS_END_LOOPVIT	1
+#define STB0899_VSTATUS_PRFVIT			(0x01 << 4)
+#define STB0899_OFFST_VSTATUS_PRFVIT		4
+#define STB0899_WIDTH_VSTATUS_PRFVIT		1
+#define STB0899_VSTATUS_LOCKEDVIT		(0x01 << 3)
+#define STB0899_OFFST_VSTATUS_LOCKEDVIT		3
+#define STB0899_WIDTH_VSTATUS_LOCKEDVIT		1
+
+#define STB0899_VERROR				0xf50f
+
+#define STB0899_IQSWAP				0xf523
+#define STB0899_SYM				(0x01 << 3)
+#define STB0899_OFFST_SYM			3
+#define STB0899_WIDTH_SYM			1
+
+#define STB0899_FECAUTO1			0xf530
+#define STB0899_DSSSRCH				(0x01 << 3)
+#define STB0899_OFFST_DSSSRCH			3
+#define STB0899_WIDTH_DSSSRCH			1
+#define STB0899_SYMSRCH				(0x01 << 2)
+#define STB0899_OFFST_SYMSRCH			2
+#define STB0899_WIDTH_SYMSRCH			1
+#define STB0899_QPSKSRCH			(0x01 << 1)
+#define STB0899_OFFST_QPSKSRCH			1
+#define STB0899_WIDTH_QPSKSRCH			1
+#define STB0899_BPSKSRCH			(0x01 << 0)
+#define STB0899_OFFST_BPSKSRCH			0
+#define STB0899_WIDTH_BPSKSRCH			1
+
+#define STB0899_FECM				0xf533
+#define STB0899_FECM_NOT_DVB			(0x01 << 7)
+#define STB0899_OFFST_FECM_NOT_DVB		7
+#define STB0899_WIDTH_FECM_NOT_DVB		1
+#define STB0899_FECM_RSVD1			(0x07 << 4)
+#define STB0899_OFFST_FECM_RSVD1		4
+#define STB0899_WIDTH_FECM_RSVD1		3
+#define STB0899_FECM_VITERBI_ON			(0x01 << 3)
+#define STB0899_OFFST_FECM_VITERBI_ON		3
+#define STB0899_WIDTH_FECM_VITERBI_ON		1
+#define STB0899_FECM_RSVD0			(0x01 << 2)
+#define STB0899_OFFST_FECM_RSVD0		2
+#define STB0899_WIDTH_FECM_RSVD0		1
+#define STB0899_FECM_SYNCDIS			(0x01 << 1)
+#define STB0899_OFFST_FECM_SYNCDIS		1
+#define STB0899_WIDTH_FECM_SYNCDIS		1
+#define STB0899_FECM_SYMI			(0x01 << 0)
+#define STB0899_OFFST_FECM_SYMI			1
+#define STB0899_WIDTH_FECM_SYMI			1
+
+#define STB0899_VTH12				0xf534
+#define STB0899_VTH23				0xf535
+#define STB0899_VTH34				0xf536
+#define STB0899_VTH56				0xf537
+#define STB0899_VTH67				0xf538
+#define STB0899_VTH78				0xf539
+
+#define STB0899_PRVIT				0xf53c
+#define STB0899_PR_7_8				(0x01 << 5)
+#define STB0899_OFFST_PR_7_8			5
+#define STB0899_WIDTH_PR_7_8			1
+#define STB0899_PR_6_7				(0x01 << 4)
+#define STB0899_OFFST_PR_6_7			4
+#define STB0899_WIDTH_PR_6_7			1
+#define STB0899_PR_5_6				(0x01 << 3)
+#define STB0899_OFFST_PR_5_6			3
+#define STB0899_WIDTH_PR_5_6			1
+#define STB0899_PR_3_4				(0x01 << 2)
+#define STB0899_OFFST_PR_3_4			2
+#define STB0899_WIDTH_PR_3_4			1
+#define STB0899_PR_2_3				(0x01 << 1)
+#define STB0899_OFFST_PR_2_3			1
+#define STB0899_WIDTH_PR_2_3			1
+#define STB0899_PR_1_2				(0x01 << 0)
+#define STB0899_OFFST_PR_1_2			0
+#define STB0899_WIDTH_PR_1_2			1
+
+#define STB0899_VITSYNC				0xf53d
+#define STB0899_AM				(0x01 << 7)
+#define STB0899_OFFST_AM			7
+#define STB0899_WIDTH_AM			1
+#define STB0899_FREEZE				(0x01 << 6)
+#define STB0899_OFFST_FREEZE			6
+#define STB0899_WIDTH_FREEZE			1
+#define STB0899_SN_65536			(0x03 << 4)
+#define STB0899_OFFST_SN_65536			4
+#define STB0899_WIDTH_SN_65536			2
+#define STB0899_SN_16384			(0x01 << 5)
+#define STB0899_OFFST_SN_16384			5
+#define STB0899_WIDTH_SN_16384			1
+#define STB0899_SN_4096				(0x01 << 4)
+#define STB0899_OFFST_SN_4096			4
+#define STB0899_WIDTH_SN_4096			1
+#define STB0899_SN_1024				(0x00 << 4)
+#define STB0899_OFFST_SN_1024			4
+#define STB0899_WIDTH_SN_1024			0
+#define STB0899_TO_128				(0x03 << 2)
+#define STB0899_OFFST_TO_128			2
+#define STB0899_WIDTH_TO_128			2
+#define STB0899_TO_64				(0x01 << 3)
+#define STB0899_OFFST_TO_64			3
+#define STB0899_WIDTH_TO_64			1
+#define STB0899_TO_32				(0x01 << 2)
+#define STB0899_OFFST_TO_32			2
+#define STB0899_WIDTH_TO_32			1
+#define STB0899_TO_16				(0x00 << 2)
+#define STB0899_OFFST_TO_16			2
+#define STB0899_WIDTH_TO_16			0
+#define STB0899_HYST_128			(0x03 << 1)
+#define STB0899_OFFST_HYST_128			1
+#define STB0899_WIDTH_HYST_128			2
+#define STB0899_HYST_64				(0x01 << 1)
+#define STB0899_OFFST_HYST_64			1
+#define STB0899_WIDTH_HYST_64			1
+#define STB0899_HYST_32				(0x01 << 0)
+#define STB0899_OFFST_HYST_32			0
+#define STB0899_WIDTH_HYST_32			1
+#define STB0899_HYST_16				(0x00 << 0)
+#define STB0899_OFFST_HYST_16			0
+#define STB0899_WIDTH_HYST_16			0
+
+#define STB0899_RSULC				0xf548
+#define STB0899_ULDIL_ON			(0x01 << 7)
+#define STB0899_OFFST_ULDIL_ON			7
+#define STB0899_WIDTH_ULDIL_ON			1
+#define STB0899_ULAUTO_ON			(0x01 << 6)
+#define STB0899_OFFST_ULAUTO_ON			6
+#define STB0899_WIDTH_ULAUTO_ON			1
+#define STB0899_ULRS_ON				(0x01 << 5)
+#define STB0899_OFFST_ULRS_ON			5
+#define STB0899_WIDTH_ULRS_ON			1
+#define STB0899_ULDESCRAM_ON			(0x01 << 4)
+#define STB0899_OFFST_ULDESCRAM_ON		4
+#define STB0899_WIDTH_ULDESCRAM_ON		1
+#define STB0899_UL_DISABLE			(0x01 << 2)
+#define STB0899_OFFST_UL_DISABLE		2
+#define STB0899_WIDTH_UL_DISABLE		1
+#define STB0899_NOFTHRESHOLD			(0x01 << 0)
+#define STB0899_OFFST_NOFTHRESHOLD		0
+#define STB0899_WIDTH_NOFTHRESHOLD		1
+
+#define STB0899_RSLLC				0xf54a
+#define STB0899_DEMAPVIT			0xf583
+#define STB0899_DEMAPVIT_RSVD			(0x01 << 7)
+#define STB0899_OFFST_DEMAPVIT_RSVD		7
+#define STB0899_WIDTH_DEMAPVIT_RSVD		1
+#define STB0899_DEMAPVIT_KDIVIDER		(0x7f << 0)
+#define STB0899_OFFST_DEMAPVIT_KDIVIDER		0
+#define STB0899_WIDTH_DEMAPVIT_KDIVIDER		7
+
+#define STB0899_PLPARM				0xf58c
+#define STB0899_VITMAPPING			(0x07 << 5)
+#define STB0899_OFFST_VITMAPPING		5
+#define STB0899_WIDTH_VITMAPPING		3
+#define STB0899_VITMAPPING_BPSK			(0x01 << 5)
+#define STB0899_OFFST_VITMAPPING_BPSK		5
+#define STB0899_WIDTH_VITMAPPING_BPSK		1
+#define STB0899_VITMAPPING_QPSK			(0x00 << 5)
+#define STB0899_OFFST_VITMAPPING_QPSK		5
+#define STB0899_WIDTH_VITMAPPING_QPSK		0
+#define STB0899_VITCURPUN			(0x1f << 0)
+#define STB0899_OFFST_VITCURPUN			0
+#define STB0899_WIDTH_VITCURPUN			5
+#define STB0899_VITCURPUN_1_2			(0x0d << 0)
+#define STB0899_VITCURPUN_2_3			(0x12 << 0)
+#define STB0899_VITCURPUN_3_4			(0x15 << 0)
+#define STB0899_VITCURPUN_5_6			(0x18 << 0)
+#define STB0899_VITCURPUN_6_7			(0x19 << 0)
+#define STB0899_VITCURPUN_7_8			(0x1a << 0)
+
+/*	S2 DEMOD	*/
+#define STB0899_OFF0_DMD_STATUS			0xf300
+#define STB0899_BASE_DMD_STATUS			0x00000000
+#define STB0899_IF_AGC_LOCK			(0x01 << 0)
+#define STB0899_OFFST_IF_AGC_LOCK		0
+#define STB0899_WIDTH_IF_AGC_LOCK		1
+
+#define STB0899_OFF0_CRL_FREQ			0xf304
+#define STB0899_BASE_CRL_FREQ			0x00000000
+#define STB0899_CARR_FREQ			(0x1fffffff << 0)
+#define STB0899_OFFST_CARR_FREQ			0
+#define STB0899_WIDTH_CARR_FREQ			30
+
+#define STB0899_OFF0_BTR_FREQ			0xf308
+#define STB0899_BASE_BTR_FREQ			0x00000000
+#define STB0899_BTR_FREQ			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_FREQ			0
+#define STB0899_WIDTH_BTR_FREQ			28
+
+#define STB0899_OFF0_IF_AGC_GAIN		0xf30c
+#define STB0899_BASE_IF_AGC_GAIN		0x00000000
+#define STB0899_IF_AGC_GAIN			(0x3fff < 0)
+#define STB0899_OFFST_IF_AGC_GAIN		0
+#define STB0899_WIDTH_IF_AGC_GAIN		14
+
+#define STB0899_OFF0_BB_AGC_GAIN		0xf310
+#define STB0899_BASE_BB_AGC_GAIN		0x00000000
+#define STB0899_BB_AGC_GAIN			(0x3fff < 0)
+#define STB0899_OFFST_BB_AGC_GAIN		0
+#define STB0899_WIDTH_BB_AGC_GAIN		14
+
+#define STB0899_OFF0_DC_OFFSET			0xf314
+#define STB0899_BASE_DC_OFFSET			0x00000000
+#define STB0899_I				(0xff < 8)
+#define STB0899_OFFST_I				8
+#define STB0899_WIDTH_I				8
+#define STB0899_Q				(0xff < 0)
+#define STB0899_OFFST_Q				8
+#define STB0899_WIDTH_Q				8
+
+#define STB0899_OFF0_DMD_CNTRL			0xf31c
+#define STB0899_BASE_DMD_CNTRL			0x00000000
+#define STB0899_ADC0_PINS1IN			(0x01 << 6)
+#define STB0899_OFFST_ADC0_PINS1IN              6
+#define STB0899_WIDTH_ADC0_PINS1IN              1
+#define STB0899_IN2COMP1_OFFBIN0		(0x01 << 3)
+#define STB0899_OFFST_IN2COMP1_OFFBIN0          3
+#define STB0899_WIDTH_IN2COMP1_OFFBIN0          1
+#define STB0899_DC_COMP				(0x01 << 2)
+#define STB0899_OFFST_DC_COMP			2
+#define STB0899_WIDTH_DC_COMP			1
+#define STB0899_MODMODE				(0x03 << 0)
+#define STB0899_OFFST_MODMODE			0
+#define STB0899_WIDTH_MODMODE			2
+
+#define STB0899_OFF0_IF_AGC_CNTRL		0xf320
+#define STB0899_BASE_IF_AGC_CNTRL		0x00000000
+#define STB0899_IF_GAIN_INIT			(0x3fff << 13)
+#define STB0899_OFFST_IF_GAIN_INIT		13
+#define STB0899_WIDTH_IF_GAIN_INIT		14
+#define STB0899_IF_GAIN_SENSE			(0x01 << 12)
+#define STB0899_OFFST_IF_GAIN_SENSE		12
+#define STB0899_WIDTH_IF_GAIN_SENSE		1
+#define STB0899_IF_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_IF_LOOP_GAIN		8
+#define STB0899_WIDTH_IF_LOOP_GAIN		4
+#define STB0899_IF_LD_GAIN_INIT			(0x01 << 7)
+#define STB0899_OFFST_IF_LD_GAIN_INIT		7
+#define STB0899_WIDTH_IF_LD_GAIN_INIT		1
+#define STB0899_IF_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_IF_AGC_REF		0
+#define STB0899_WIDTH_IF_AGC_REF		7
+
+#define STB0899_OFF0_BB_AGC_CNTRL		0xf324
+#define STB0899_BASE_BB_AGC_CNTRL		0x00000000
+#define STB0899_BB_GAIN_INIT			(0x3fff << 12)
+#define STB0899_OFFST_BB_GAIN_INIT		12
+#define STB0899_WIDTH_BB_GAIN_INIT		14
+#define STB0899_BB_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_BB_LOOP_GAIN		8
+#define STB0899_WIDTH_BB_LOOP_GAIN		4
+#define STB0899_BB_LD_GAIN_INIT			(0x01 << 7)
+#define STB0899_OFFST_BB_LD_GAIN_INIT		7
+#define STB0899_WIDTH_BB_LD_GAIN_INIT		1
+#define STB0899_BB_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_BB_AGC_REF		0
+#define STB0899_WIDTH_BB_AGC_REF		7
+
+#define STB0899_OFF0_CRL_CNTRL			0xf328
+#define STB0899_BASE_CRL_CNTRL			0x00000000
+#define STB0899_CRL_LOCK_CLEAR			(0x01 << 5)
+#define STB0899_OFFST_CRL_LOCK_CLEAR		5
+#define STB0899_WIDTH_CRL_LOCK_CLEAR		1
+#define STB0899_CRL_SWPR_CLEAR			(0x01 << 4)
+#define STB0899_OFFST_CRL_SWPR_CLEAR		4
+#define STB0899_WIDTH_CRL_SWPR_CLEAR		1
+#define STB0899_CRL_SWP_ENA			(0x01 << 3)
+#define STB0899_OFFST_CRL_SWP_ENA		3
+#define STB0899_WIDTH_CRL_SWP_ENA		1
+#define STB0899_CRL_DET_SEL			(0x01 << 2)
+#define STB0899_OFFST_CRL_DET_SEL		2
+#define STB0899_WIDTH_CRL_DET_SEL		1
+#define STB0899_CRL_SENSE			(0x01 << 1)
+#define STB0899_OFFST_CRL_SENSE			1
+#define STB0899_WIDTH_CRL_SENSE			1
+#define STB0899_CRL_PHSERR_CLEAR		(0x01 << 0)
+#define STB0899_OFFST_CRL_PHSERR_CLEAR		0
+#define STB0899_WIDTH_CRL_PHSERR_CLEAR		1
+
+#define STB0899_OFF0_CRL_PHS_INIT		0xf32c
+#define STB0899_BASE_CRL_PHS_INIT		0x00000000
+#define STB0899_CRL_PHS_INIT_31			(0x1 << 30)
+#define STB0899_OFFST_CRL_PHS_INIT_31		30
+#define STB0899_WIDTH_CRL_PHS_INIT_31		1
+#define STB0899_CRL_LD_INIT_PHASE		(0x1 << 24)
+#define STB0899_OFFST_CRL_LD_INIT_PHASE		24
+#define STB0899_WIDTH_CRL_LD_INIT_PHASE		1
+#define STB0899_CRL_INIT_PHASE			(0xffffff << 0)
+#define STB0899_OFFST_CRL_INIT_PHASE		0
+#define STB0899_WIDTH_CRL_INIT_PHASE		24
+
+#define STB0899_OFF0_CRL_FREQ_INIT		0xf330
+#define STB0899_BASE_CRL_FREQ_INIT		0x00000000
+#define STB0899_CRL_FREQ_INIT_31		(0x1 << 30)
+#define STB0899_OFFST_CRL_FREQ_INIT_31		30
+#define STB0899_WIDTH_CRL_FREQ_INIT_31		1
+#define STB0899_CRL_LD_FREQ_INIT		(0x1 << 24)
+#define STB0899_OFFST_CRL_LD_FREQ_INIT		24
+#define STB0899_WIDTH_CRL_LD_FREQ_INIT		1
+#define STB0899_CRL_FREQ_INIT			(0xffffff << 0)
+#define STB0899_OFFST_CRL_FREQ_INIT		0
+#define STB0899_WIDTH_CRL_FREQ_INIT		24
+
+#define STB0899_OFF0_CRL_LOOP_GAIN		0xf334
+#define STB0899_BASE_CRL_LOOP_GAIN		0x00000000
+#define STB0899_KCRL2_RSHFT			(0xf << 16)
+#define STB0899_OFFST_KCRL2_RSHFT		16
+#define STB0899_WIDTH_KCRL2_RSHFT		4
+#define STB0899_KCRL1				(0xf << 12)
+#define STB0899_OFFST_KCRL1			12
+#define STB0899_WIDTH_KCRL1			4
+#define STB0899_KCRL1_RSHFT			(0xf << 8)
+#define STB0899_OFFST_KCRL1_RSHFT		8
+#define STB0899_WIDTH_KCRL1_RSHFT		4
+#define STB0899_KCRL0				(0xf << 4)
+#define STB0899_OFFST_KCRL0			4
+#define STB0899_WIDTH_KCRL0			4
+#define STB0899_KCRL0_RSHFT			(0xf << 0)
+#define STB0899_OFFST_KCRL0_RSHFT		0
+#define STB0899_WIDTH_KCRL0_RSHFT		4
+
+#define STB0899_OFF0_CRL_NOM_FREQ		0xf338
+#define STB0899_BASE_CRL_NOM_FREQ		0x00000000
+#define STB0899_CRL_NOM_FREQ			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_NOM_FREQ		0
+#define STB0899_WIDTH_CRL_NOM_FREQ		30
+
+#define STB0899_OFF0_CRL_SWP_RATE		0xf33c
+#define STB0899_BASE_CRL_SWP_RATE		0x00000000
+#define STB0899_CRL_SWP_RATE			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_SWP_RATE		0
+#define STB0899_WIDTH_CRL_SWP_RATE		30
+
+#define STB0899_OFF0_CRL_MAX_SWP		0xf340
+#define STB0899_BASE_CRL_MAX_SWP		0x00000000
+#define STB0899_CRL_MAX_SWP			(0x3fffffff << 0)
+#define STB0899_OFFST_CRL_MAX_SWP		0
+#define STB0899_WIDTH_CRL_MAX_SWP		30
+
+#define STB0899_OFF0_CRL_LK_CNTRL		0xf344
+#define STB0899_BASE_CRL_LK_CNTRL		0x00000000
+
+#define STB0899_OFF0_DECIM_CNTRL		0xf348
+#define STB0899_BASE_DECIM_CNTRL		0x00000000
+#define STB0899_BAND_LIMIT_B			(0x01 << 5)
+#define STB0899_OFFST_BAND_LIMIT_B		5
+#define STB0899_WIDTH_BAND_LIMIT_B		1
+#define STB0899_WIN_SEL				(0x03 << 3)
+#define STB0899_OFFST_WIN_SEL			3
+#define STB0899_WIDTH_WIN_SEL			2
+#define STB0899_DECIM_RATE			(0x07 << 0)
+#define STB0899_OFFST_DECIM_RATE		0
+#define STB0899_WIDTH_DECIM_RATE		3
+
+#define STB0899_OFF0_BTR_CNTRL			0xf34c
+#define STB0899_BASE_BTR_CNTRL			0x00000000
+#define STB0899_BTR_FREQ_CORR			(0x7ff << 4)
+#define STB0899_OFFST_BTR_FREQ_CORR		4
+#define STB0899_WIDTH_BTR_FREQ_CORR		11
+#define STB0899_BTR_CLR_LOCK			(0x01 << 3)
+#define STB0899_OFFST_BTR_CLR_LOCK		3
+#define STB0899_WIDTH_BTR_CLR_LOCK		1
+#define STB0899_BTR_SENSE			(0x01 << 2)
+#define STB0899_OFFST_BTR_SENSE			2
+#define STB0899_WIDTH_BTR_SENSE			1
+#define STB0899_BTR_ERR_ENA			(0x01 << 1)
+#define STB0899_OFFST_BTR_ERR_ENA		1
+#define STB0899_WIDTH_BTR_ERR_ENA		1
+#define STB0899_INTRP_PHS_SENSE			(0x01 << 0)
+#define STB0899_OFFST_INTRP_PHS_SENSE		0
+#define STB0899_WIDTH_INTRP_PHS_SENSE		1
+
+#define STB0899_OFF0_BTR_LOOP_GAIN		0xf350
+#define STB0899_BASE_BTR_LOOP_GAIN		0x00000000
+#define STB0899_KBTR2_RSHFT			(0x0f << 16)
+#define STB0899_OFFST_KBTR2_RSHFT		16
+#define STB0899_WIDTH_KBTR2_RSHFT		4
+#define STB0899_KBTR1				(0x0f << 12)
+#define STB0899_OFFST_KBTR1			12
+#define STB0899_WIDTH_KBTR1			4
+#define STB0899_KBTR1_RSHFT			(0x0f << 8)
+#define STB0899_OFFST_KBTR1_RSHFT		8
+#define STB0899_WIDTH_KBTR1_RSHFT		4
+#define STB0899_KBTR0				(0x0f << 4)
+#define STB0899_OFFST_KBTR0			4
+#define STB0899_WIDTH_KBTR0			4
+#define STB0899_KBTR0_RSHFT			(0x0f << 0)
+#define STB0899_OFFST_KBTR0_RSHFT		0
+#define STB0899_WIDTH_KBTR0_RSHFT		4
+
+#define STB0899_OFF0_BTR_PHS_INIT		0xf354
+#define STB0899_BASE_BTR_PHS_INIT		0x00000000
+#define STB0899_BTR_LD_PHASE_INIT		(0x01 << 28)
+#define STB0899_OFFST_BTR_LD_PHASE_INIT		28
+#define STB0899_WIDTH_BTR_LD_PHASE_INIT		1
+#define STB0899_BTR_INIT_PHASE			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_INIT_PHASE		0
+#define STB0899_WIDTH_BTR_INIT_PHASE		28
+
+#define STB0899_OFF0_BTR_FREQ_INIT		0xf358
+#define STB0899_BASE_BTR_FREQ_INIT		0x00000000
+#define STB0899_BTR_LD_FREQ_INIT		(1 << 28)
+#define STB0899_OFFST_BTR_LD_FREQ_INIT		28
+#define STB0899_WIDTH_BTR_LD_FREQ_INIT		1
+#define STB0899_BTR_FREQ_INIT			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_FREQ_INIT		0
+#define STB0899_WIDTH_BTR_FREQ_INIT		28
+
+#define STB0899_OFF0_BTR_NOM_FREQ		0xf35c
+#define STB0899_BASE_BTR_NOM_FREQ		0x00000000
+#define STB0899_BTR_NOM_FREQ			(0xfffffff << 0)
+#define STB0899_OFFST_BTR_NOM_FREQ		0
+#define STB0899_WIDTH_BTR_NOM_FREQ		28
+
+#define STB0899_OFF0_BTR_LK_CNTRL		0xf360
+#define STB0899_BASE_BTR_LK_CNTRL		0x00000000
+#define STB0899_BTR_MIN_ENERGY			(0x0f << 24)
+#define STB0899_OFFST_BTR_MIN_ENERGY		24
+#define STB0899_WIDTH_BTR_MIN_ENERGY		4
+#define STB0899_BTR_LOCK_TH_LO			(0xff << 16)
+#define STB0899_OFFST_BTR_LOCK_TH_LO		16
+#define STB0899_WIDTH_BTR_LOCK_TH_LO		8
+#define STB0899_BTR_LOCK_TH_HI			(0xff << 8)
+#define STB0899_OFFST_BTR_LOCK_TH_HI		8
+#define STB0899_WIDTH_BTR_LOCK_TH_HI		8
+#define STB0899_BTR_LOCK_GAIN			(0x03 << 6)
+#define STB0899_OFFST_BTR_LOCK_GAIN		6
+#define STB0899_WIDTH_BTR_LOCK_GAIN		2
+#define STB0899_BTR_LOCK_LEAK			(0x3f << 0)
+#define STB0899_OFFST_BTR_LOCK_LEAK		0
+#define STB0899_WIDTH_BTR_LOCK_LEAK		6
+
+#define STB0899_OFF0_DECN_CNTRL			0xf364
+#define STB0899_BASE_DECN_CNTRL			0x00000000
+
+#define STB0899_OFF0_TP_CNTRL			0xf368
+#define STB0899_BASE_TP_CNTRL			0x00000000
+
+#define STB0899_OFF0_TP_BUF_STATUS		0xf36c
+#define STB0899_BASE_TP_BUF_STATUS		0x00000000
+#define STB0899_TP_BUFFER_FULL                  (1 << 0)
+
+#define STB0899_OFF0_DC_ESTIM			0xf37c
+#define STB0899_BASE_DC_ESTIM			0x0000
+#define STB0899_I_DC_ESTIMATE			(0xff << 8)
+#define STB0899_OFFST_I_DC_ESTIMATE		8
+#define STB0899_WIDTH_I_DC_ESTIMATE		8
+#define STB0899_Q_DC_ESTIMATE			(0xff << 0)
+#define STB0899_OFFST_Q_DC_ESTIMATE		0
+#define STB0899_WIDTH_Q_DC_ESTIMATE		8
+
+#define STB0899_OFF0_FLL_CNTRL			0xf310
+#define STB0899_BASE_FLL_CNTRL			0x00000020
+#define STB0899_CRL_FLL_ACC			(0x01 << 4)
+#define STB0899_OFFST_CRL_FLL_ACC		4
+#define STB0899_WIDTH_CRL_FLL_ACC		1
+#define STB0899_FLL_AVG_PERIOD			(0x0f << 0)
+#define STB0899_OFFST_FLL_AVG_PERIOD		0
+#define STB0899_WIDTH_FLL_AVG_PERIOD		4
+
+#define STB0899_OFF0_FLL_FREQ_WD		0xf314
+#define STB0899_BASE_FLL_FREQ_WD		0x00000020
+#define STB0899_FLL_FREQ_WD			(0xffffffff << 0)
+#define STB0899_OFFST_FLL_FREQ_WD		0
+#define STB0899_WIDTH_FLL_FREQ_WD		32
+
+#define STB0899_OFF0_ANTI_ALIAS_SEL		0xf358
+#define STB0899_BASE_ANTI_ALIAS_SEL		0x00000020
+#define STB0899_ANTI_ALIAS_SELB			(0x03 << 0)
+#define STB0899_OFFST_ANTI_ALIAS_SELB		0
+#define STB0899_WIDTH_ANTI_ALIAS_SELB		2
+
+#define STB0899_OFF0_RRC_ALPHA			0xf35c
+#define STB0899_BASE_RRC_ALPHA			0x00000020
+#define STB0899_RRC_ALPHA			(0x03 << 0)
+#define STB0899_OFFST_RRC_ALPHA			0
+#define STB0899_WIDTH_RRC_ALPHA			2
+
+#define STB0899_OFF0_DC_ADAPT_LSHFT		0xf360
+#define STB0899_BASE_DC_ADAPT_LSHFT		0x00000020
+#define STB0899_DC_ADAPT_LSHFT			(0x077 << 0)
+#define STB0899_OFFST_DC_ADAPT_LSHFT		0
+#define STB0899_WIDTH_DC_ADAPT_LSHFT		3
+
+#define STB0899_OFF0_IMB_OFFSET			0xf364
+#define STB0899_BASE_IMB_OFFSET			0x00000020
+#define STB0899_PHS_IMB_COMP			(0xff << 8)
+#define STB0899_OFFST_PHS_IMB_COMP		8
+#define STB0899_WIDTH_PHS_IMB_COMP		8
+#define STB0899_AMPL_IMB_COMP			(0xff << 0)
+#define STB0899_OFFST_AMPL_IMB_COMP		0
+#define STB0899_WIDTH_AMPL_IMB_COMP		8
+
+#define STB0899_OFF0_IMB_ESTIMATE		0xf368
+#define STB0899_BASE_IMB_ESTIMATE		0x00000020
+#define STB0899_PHS_IMB_ESTIMATE		(0xff << 8)
+#define STB0899_OFFST_PHS_IMB_ESTIMATE		8
+#define STB0899_WIDTH_PHS_IMB_ESTIMATE		8
+#define STB0899_AMPL_IMB_ESTIMATE		(0xff << 0)
+#define STB0899_OFFST_AMPL_IMB_ESTIMATE		0
+#define STB0899_WIDTH_AMPL_IMB_ESTIMATE		8
+
+#define STB0899_OFF0_IMB_CNTRL			0xf36c
+#define STB0899_BASE_IMB_CNTRL			0x00000020
+#define STB0899_PHS_ADAPT_LSHFT			(0x07 << 4)
+#define STB0899_OFFST_PHS_ADAPT_LSHFT		4
+#define STB0899_WIDTH_PHS_ADAPT_LSHFT		3
+#define STB0899_AMPL_ADAPT_LSHFT		(0x07 << 1)
+#define STB0899_OFFST_AMPL_ADAPT_LSHFT		1
+#define STB0899_WIDTH_AMPL_ADAPT_LSHFT		3
+#define STB0899_IMB_COMP			(0x01 << 0)
+#define STB0899_OFFST_IMB_COMP			0
+#define STB0899_WIDTH_IMB_COMP			1
+
+#define STB0899_OFF0_IF_AGC_CNTRL2		0xf374
+#define STB0899_BASE_IF_AGC_CNTRL2		0x00000020
+#define STB0899_IF_AGC_LOCK_TH			(0xff << 11)
+#define STB0899_OFFST_IF_AGC_LOCK_TH		11
+#define STB0899_WIDTH_IF_AGC_LOCK_TH		8
+#define STB0899_IF_AGC_SD_DIV			(0xff << 3)
+#define STB0899_OFFST_IF_AGC_SD_DIV		3
+#define STB0899_WIDTH_IF_AGC_SD_DIV		8
+#define STB0899_IF_AGC_DUMP_PER			(0x07 << 0)
+#define STB0899_OFFST_IF_AGC_DUMP_PER		0
+#define STB0899_WIDTH_IF_AGC_DUMP_PER		3
+
+#define STB0899_OFF0_DMD_CNTRL2			0xf378
+#define STB0899_BASE_DMD_CNTRL2			0x00000020
+#define STB0899_SPECTRUM_INVERT			(0x01 << 2)
+#define STB0899_OFFST_SPECTRUM_INVERT		2
+#define STB0899_WIDTH_SPECTRUM_INVERT		1
+#define STB0899_AGC_MODE			(0x01 << 1)
+#define STB0899_OFFST_AGC_MODE			1
+#define STB0899_WIDTH_AGC_MODE			1
+#define STB0899_CRL_FREQ_ADJ			(0x01 << 0)
+#define STB0899_OFFST_CRL_FREQ_ADJ		0
+#define STB0899_WIDTH_CRL_FREQ_ADJ		1
+
+#define STB0899_OFF0_TP_BUFFER			0xf300
+#define STB0899_BASE_TP_BUFFER			0x00000040
+#define STB0899_TP_BUFFER_IN			(0xffff << 0)
+#define STB0899_OFFST_TP_BUFFER_IN		0
+#define STB0899_WIDTH_TP_BUFFER_IN		16
+
+#define STB0899_OFF0_TP_BUFFER1			0xf304
+#define STB0899_BASE_TP_BUFFER1			0x00000040
+#define STB0899_OFF0_TP_BUFFER2			0xf308
+#define STB0899_BASE_TP_BUFFER2			0x00000040
+#define STB0899_OFF0_TP_BUFFER3			0xf30c
+#define STB0899_BASE_TP_BUFFER3			0x00000040
+#define STB0899_OFF0_TP_BUFFER4			0xf310
+#define STB0899_BASE_TP_BUFFER4			0x00000040
+#define STB0899_OFF0_TP_BUFFER5			0xf314
+#define STB0899_BASE_TP_BUFFER5			0x00000040
+#define STB0899_OFF0_TP_BUFFER6			0xf318
+#define STB0899_BASE_TP_BUFFER6			0x00000040
+#define STB0899_OFF0_TP_BUFFER7			0xf31c
+#define STB0899_BASE_TP_BUFFER7			0x00000040
+#define STB0899_OFF0_TP_BUFFER8			0xf320
+#define STB0899_BASE_TP_BUFFER8			0x00000040
+#define STB0899_OFF0_TP_BUFFER9			0xf324
+#define STB0899_BASE_TP_BUFFER9			0x00000040
+#define STB0899_OFF0_TP_BUFFER10		0xf328
+#define STB0899_BASE_TP_BUFFER10		0x00000040
+#define STB0899_OFF0_TP_BUFFER11		0xf32c
+#define STB0899_BASE_TP_BUFFER11		0x00000040
+#define STB0899_OFF0_TP_BUFFER12		0xf330
+#define STB0899_BASE_TP_BUFFER12		0x00000040
+#define STB0899_OFF0_TP_BUFFER13		0xf334
+#define STB0899_BASE_TP_BUFFER13		0x00000040
+#define STB0899_OFF0_TP_BUFFER14		0xf338
+#define STB0899_BASE_TP_BUFFER14		0x00000040
+#define STB0899_OFF0_TP_BUFFER15		0xf33c
+#define STB0899_BASE_TP_BUFFER15		0x00000040
+#define STB0899_OFF0_TP_BUFFER16		0xf340
+#define STB0899_BASE_TP_BUFFER16		0x00000040
+#define STB0899_OFF0_TP_BUFFER17		0xf344
+#define STB0899_BASE_TP_BUFFER17		0x00000040
+#define STB0899_OFF0_TP_BUFFER18		0xf348
+#define STB0899_BASE_TP_BUFFER18		0x00000040
+#define STB0899_OFF0_TP_BUFFER19		0xf34c
+#define STB0899_BASE_TP_BUFFER19		0x00000040
+#define STB0899_OFF0_TP_BUFFER20		0xf350
+#define STB0899_BASE_TP_BUFFER20		0x00000040
+#define STB0899_OFF0_TP_BUFFER21		0xf354
+#define STB0899_BASE_TP_BUFFER21		0x00000040
+#define STB0899_OFF0_TP_BUFFER22		0xf358
+#define STB0899_BASE_TP_BUFFER22		0x00000040
+#define STB0899_OFF0_TP_BUFFER23		0xf35c
+#define STB0899_BASE_TP_BUFFER23		0x00000040
+#define STB0899_OFF0_TP_BUFFER24		0xf360
+#define STB0899_BASE_TP_BUFFER24		0x00000040
+#define STB0899_OFF0_TP_BUFFER25		0xf364
+#define STB0899_BASE_TP_BUFFER25		0x00000040
+#define STB0899_OFF0_TP_BUFFER26		0xf368
+#define STB0899_BASE_TP_BUFFER26		0x00000040
+#define STB0899_OFF0_TP_BUFFER27		0xf36c
+#define STB0899_BASE_TP_BUFFER27		0x00000040
+#define STB0899_OFF0_TP_BUFFER28		0xf370
+#define STB0899_BASE_TP_BUFFER28		0x00000040
+#define STB0899_OFF0_TP_BUFFER29		0xf374
+#define STB0899_BASE_TP_BUFFER29		0x00000040
+#define STB0899_OFF0_TP_BUFFER30		0xf378
+#define STB0899_BASE_TP_BUFFER30		0x00000040
+#define STB0899_OFF0_TP_BUFFER31		0xf37c
+#define STB0899_BASE_TP_BUFFER31		0x00000040
+#define STB0899_OFF0_TP_BUFFER32		0xf300
+#define STB0899_BASE_TP_BUFFER32		0x00000060
+#define STB0899_OFF0_TP_BUFFER33		0xf304
+#define STB0899_BASE_TP_BUFFER33		0x00000060
+#define STB0899_OFF0_TP_BUFFER34		0xf308
+#define STB0899_BASE_TP_BUFFER34		0x00000060
+#define STB0899_OFF0_TP_BUFFER35		0xf30c
+#define STB0899_BASE_TP_BUFFER35		0x00000060
+#define STB0899_OFF0_TP_BUFFER36		0xf310
+#define STB0899_BASE_TP_BUFFER36		0x00000060
+#define STB0899_OFF0_TP_BUFFER37		0xf314
+#define STB0899_BASE_TP_BUFFER37		0x00000060
+#define STB0899_OFF0_TP_BUFFER38		0xf318
+#define STB0899_BASE_TP_BUFFER38		0x00000060
+#define STB0899_OFF0_TP_BUFFER39		0xf31c
+#define STB0899_BASE_TP_BUFFER39		0x00000060
+#define STB0899_OFF0_TP_BUFFER40		0xf320
+#define STB0899_BASE_TP_BUFFER40		0x00000060
+#define STB0899_OFF0_TP_BUFFER41		0xf324
+#define STB0899_BASE_TP_BUFFER41		0x00000060
+#define STB0899_OFF0_TP_BUFFER42		0xf328
+#define STB0899_BASE_TP_BUFFER42		0x00000060
+#define STB0899_OFF0_TP_BUFFER43		0xf32c
+#define STB0899_BASE_TP_BUFFER43		0x00000060
+#define STB0899_OFF0_TP_BUFFER44		0xf330
+#define STB0899_BASE_TP_BUFFER44		0x00000060
+#define STB0899_OFF0_TP_BUFFER45		0xf334
+#define STB0899_BASE_TP_BUFFER45		0x00000060
+#define STB0899_OFF0_TP_BUFFER46		0xf338
+#define STB0899_BASE_TP_BUFFER46		0x00000060
+#define STB0899_OFF0_TP_BUFFER47		0xf33c
+#define STB0899_BASE_TP_BUFFER47		0x00000060
+#define STB0899_OFF0_TP_BUFFER48		0xf340
+#define STB0899_BASE_TP_BUFFER48		0x00000060
+#define STB0899_OFF0_TP_BUFFER49		0xf344
+#define STB0899_BASE_TP_BUFFER49		0x00000060
+#define STB0899_OFF0_TP_BUFFER50		0xf348
+#define STB0899_BASE_TP_BUFFER50		0x00000060
+#define STB0899_OFF0_TP_BUFFER51		0xf34c
+#define STB0899_BASE_TP_BUFFER51		0x00000060
+#define STB0899_OFF0_TP_BUFFER52		0xf350
+#define STB0899_BASE_TP_BUFFER52		0x00000060
+#define STB0899_OFF0_TP_BUFFER53		0xf354
+#define STB0899_BASE_TP_BUFFER53		0x00000060
+#define STB0899_OFF0_TP_BUFFER54		0xf358
+#define STB0899_BASE_TP_BUFFER54		0x00000060
+#define STB0899_OFF0_TP_BUFFER55		0xf35c
+#define STB0899_BASE_TP_BUFFER55		0x00000060
+#define STB0899_OFF0_TP_BUFFER56		0xf360
+#define STB0899_BASE_TP_BUFFER56		0x00000060
+#define STB0899_OFF0_TP_BUFFER57		0xf364
+#define STB0899_BASE_TP_BUFFER57		0x00000060
+#define STB0899_OFF0_TP_BUFFER58		0xf368
+#define STB0899_BASE_TP_BUFFER58		0x00000060
+#define STB0899_OFF0_TP_BUFFER59		0xf36c
+#define STB0899_BASE_TP_BUFFER59		0x00000060
+#define STB0899_OFF0_TP_BUFFER60		0xf370
+#define STB0899_BASE_TP_BUFFER60		0x00000060
+#define STB0899_OFF0_TP_BUFFER61		0xf374
+#define STB0899_BASE_TP_BUFFER61		0x00000060
+#define STB0899_OFF0_TP_BUFFER62		0xf378
+#define STB0899_BASE_TP_BUFFER62		0x00000060
+#define STB0899_OFF0_TP_BUFFER63		0xf37c
+#define STB0899_BASE_TP_BUFFER63		0x00000060
+
+#define STB0899_OFF0_RESET_CNTRL		0xf300
+#define STB0899_BASE_RESET_CNTRL		0x00000400
+#define STB0899_DVBS2_RESET			(0x01 << 0)
+#define STB0899_OFFST_DVBS2_RESET		0
+#define STB0899_WIDTH_DVBS2_RESET		1
+
+#define STB0899_OFF0_ACM_ENABLE			0xf304
+#define STB0899_BASE_ACM_ENABLE			0x00000400
+#define STB0899_ACM_ENABLE			1
+
+#define STB0899_OFF0_DESCR_CNTRL		0xf30c
+#define STB0899_BASE_DESCR_CNTRL		0x00000400
+#define STB0899_OFFST_DESCR_CNTRL               0
+#define STB0899_WIDTH_DESCR_CNTRL               16
+
+#define STB0899_OFF0_UWP_CNTRL1			0xf320
+#define STB0899_BASE_UWP_CNTRL1			0x00000400
+#define STB0899_UWP_TH_SOF			(0x7fff << 11)
+#define STB0899_OFFST_UWP_TH_SOF		11
+#define STB0899_WIDTH_UWP_TH_SOF		15
+#define STB0899_UWP_ESN0_QUANT			(0xff << 3)
+#define STB0899_OFFST_UWP_ESN0_QUANT		3
+#define STB0899_WIDTH_UWP_ESN0_QUANT		8
+#define STB0899_UWP_ESN0_AVE			(0x03 << 1)
+#define STB0899_OFFST_UWP_ESN0_AVE		1
+#define STB0899_WIDTH_UWP_ESN0_AVE		2
+#define STB0899_UWP_START			(0x01 << 0)
+#define STB0899_OFFST_UWP_START			0
+#define STB0899_WIDTH_UWP_START			1
+
+#define STB0899_OFF0_UWP_CNTRL2			0xf324
+#define STB0899_BASE_UWP_CNTRL2			0x00000400
+#define STB0899_UWP_MISS_TH			(0xff << 16)
+#define STB0899_OFFST_UWP_MISS_TH		16
+#define STB0899_WIDTH_UWP_MISS_TH		8
+#define STB0899_FE_FINE_TRK			(0xff << 8)
+#define STB0899_OFFST_FE_FINE_TRK		8
+#define STB0899_WIDTH_FE_FINE_TRK		8
+#define STB0899_FE_COARSE_TRK			(0xff << 0)
+#define STB0899_OFFST_FE_COARSE_TRK		0
+#define STB0899_WIDTH_FE_COARSE_TRK		8
+
+#define STB0899_OFF0_UWP_STAT1			0xf328
+#define STB0899_BASE_UWP_STAT1			0x00000400
+#define STB0899_UWP_STATE			(0x03ff << 15)
+#define STB0899_OFFST_UWP_STATE			15
+#define STB0899_WIDTH_UWP_STATE			10
+#define STB0899_UW_MAX_PEAK			(0x7fff << 0)
+#define STB0899_OFFST_UW_MAX_PEAK		0
+#define STB0899_WIDTH_UW_MAX_PEAK		15
+
+#define STB0899_OFF0_UWP_STAT2			0xf32c
+#define STB0899_BASE_UWP_STAT2			0x00000400
+#define STB0899_ESNO_EST			(0x07ffff << 7)
+#define STB0899_OFFST_ESN0_EST			7
+#define STB0899_WIDTH_ESN0_EST			19
+#define STB0899_UWP_DECODE_MOD			(0x7f << 0)
+#define STB0899_OFFST_UWP_DECODE_MOD		0
+#define STB0899_WIDTH_UWP_DECODE_MOD		7
+
+#define STB0899_OFF0_DMD_CORE_ID		0xf334
+#define STB0899_BASE_DMD_CORE_ID		0x00000400
+#define STB0899_CORE_ID				(0xffffffff << 0)
+#define STB0899_OFFST_CORE_ID			0
+#define STB0899_WIDTH_CORE_ID			32
+
+#define STB0899_OFF0_DMD_VERSION_ID		0xf33c
+#define STB0899_BASE_DMD_VERSION_ID		0x00000400
+#define STB0899_VERSION_ID			(0xff << 0)
+#define STB0899_OFFST_VERSION_ID		0
+#define STB0899_WIDTH_VERSION_ID		8
+
+#define STB0899_OFF0_DMD_STAT2			0xf340
+#define STB0899_BASE_DMD_STAT2			0x00000400
+#define STB0899_CSM_LOCK			(0x01 << 1)
+#define STB0899_OFFST_CSM_LOCK			1
+#define STB0899_WIDTH_CSM_LOCK			1
+#define STB0899_UWP_LOCK			(0x01 << 0)
+#define STB0899_OFFST_UWP_LOCK			0
+#define STB0899_WIDTH_UWP_LOCK			1
+
+#define STB0899_OFF0_FREQ_ADJ_SCALE		0xf344
+#define STB0899_BASE_FREQ_ADJ_SCALE		0x00000400
+#define STB0899_FREQ_ADJ_SCALE			(0x0fff << 0)
+#define STB0899_OFFST_FREQ_ADJ_SCALE		0
+#define STB0899_WIDTH_FREQ_ADJ_SCALE		12
+
+#define STB0899_OFF0_UWP_CNTRL3			0xf34c
+#define STB0899_BASE_UWP_CNTRL3			0x00000400
+#define STB0899_UWP_TH_TRACK			(0x7fff << 15)
+#define STB0899_OFFST_UWP_TH_TRACK		15
+#define STB0899_WIDTH_UWP_TH_TRACK		15
+#define STB0899_UWP_TH_ACQ			(0x7fff << 0)
+#define STB0899_OFFST_UWP_TH_ACQ		0
+#define STB0899_WIDTH_UWP_TH_ACQ		15
+
+#define STB0899_OFF0_SYM_CLK_SEL		0xf350
+#define STB0899_BASE_SYM_CLK_SEL		0x00000400
+#define STB0899_SYM_CLK_SEL			(0x03 << 0)
+#define STB0899_OFFST_SYM_CLK_SEL		0
+#define STB0899_WIDTH_SYM_CLK_SEL		2
+
+#define STB0899_OFF0_SOF_SRCH_TO		0xf354
+#define STB0899_BASE_SOF_SRCH_TO		0x00000400
+#define STB0899_SOF_SEARCH_TIMEOUT		(0x3fffff << 0)
+#define STB0899_OFFST_SOF_SEARCH_TIMEOUT	0
+#define STB0899_WIDTH_SOF_SEARCH_TIMEOUT	22
+
+#define STB0899_OFF0_ACQ_CNTRL1			0xf358
+#define STB0899_BASE_ACQ_CNTRL1			0x00000400
+#define STB0899_FE_FINE_ACQ			(0xff << 8)
+#define STB0899_OFFST_FE_FINE_ACQ		8
+#define STB0899_WIDTH_FE_FINE_ACQ		8
+#define STB0899_FE_COARSE_ACQ			(0xff << 0)
+#define STB0899_OFFST_FE_COARSE_ACQ		0
+#define STB0899_WIDTH_FE_COARSE_ACQ		8
+
+#define STB0899_OFF0_ACQ_CNTRL2			0xf35c
+#define STB0899_BASE_ACQ_CNTRL2			0x00000400
+#define STB0899_ZIGZAG				(0x01 << 25)
+#define STB0899_OFFST_ZIGZAG			25
+#define STB0899_WIDTH_ZIGZAG			1
+#define STB0899_NUM_STEPS			(0xff << 17)
+#define STB0899_OFFST_NUM_STEPS			17
+#define STB0899_WIDTH_NUM_STEPS			8
+#define STB0899_FREQ_STEPSIZE			(0x1ffff << 0)
+#define STB0899_OFFST_FREQ_STEPSIZE		0
+#define STB0899_WIDTH_FREQ_STEPSIZE		17
+
+#define STB0899_OFF0_ACQ_CNTRL3			0xf360
+#define STB0899_BASE_ACQ_CNTRL3			0x00000400
+#define STB0899_THRESHOLD_SCL			(0x3f << 23)
+#define STB0899_OFFST_THRESHOLD_SCL		23
+#define STB0899_WIDTH_THRESHOLD_SCL		6
+#define STB0899_UWP_TH_SRCH			(0x7fff << 8)
+#define STB0899_OFFST_UWP_TH_SRCH		8
+#define STB0899_WIDTH_UWP_TH_SRCH		15
+#define STB0899_AUTO_REACQUIRE			(0x01 << 7)
+#define STB0899_OFFST_AUTO_REACQUIRE		7
+#define STB0899_WIDTH_AUTO_REACQUIRE		1
+#define STB0899_TRACK_LOCK_SEL			(0x01 << 6)
+#define STB0899_OFFST_TRACK_LOCK_SEL		6
+#define STB0899_WIDTH_TRACK_LOCK_SEL		1
+#define STB0899_ACQ_SEARCH_MODE			(0x03 << 4)
+#define STB0899_OFFST_ACQ_SEARCH_MODE		4
+#define STB0899_WIDTH_ACQ_SEARCH_MODE		2
+#define STB0899_CONFIRM_FRAMES			(0x0f << 0)
+#define STB0899_OFFST_CONFIRM_FRAMES		0
+#define STB0899_WIDTH_CONFIRM_FRAMES		4
+
+#define STB0899_OFF0_FE_SETTLE			0xf364
+#define STB0899_BASE_FE_SETTLE			0x00000400
+#define STB0899_SETTLING_TIME			(0x3fffff << 0)
+#define STB0899_OFFST_SETTLING_TIME		0
+#define STB0899_WIDTH_SETTLING_TIME		22
+
+#define STB0899_OFF0_AC_DWELL			0xf368
+#define STB0899_BASE_AC_DWELL			0x00000400
+#define STB0899_DWELL_TIME			(0x3fffff << 0)
+#define STB0899_OFFST_DWELL_TIME		0
+#define STB0899_WIDTH_DWELL_TIME		22
+
+#define STB0899_OFF0_ACQUIRE_TRIG		0xf36c
+#define STB0899_BASE_ACQUIRE_TRIG		0x00000400
+#define STB0899_ACQUIRE				(0x01 << 0)
+#define STB0899_OFFST_ACQUIRE			0
+#define STB0899_WIDTH_ACQUIRE			1
+
+#define STB0899_OFF0_LOCK_LOST			0xf370
+#define STB0899_BASE_LOCK_LOST			0x00000400
+#define STB0899_LOCK_LOST			(0x01 << 0)
+#define STB0899_OFFST_LOCK_LOST			0
+#define STB0899_WIDTH_LOCK_LOST			1
+
+#define STB0899_OFF0_ACQ_STAT1			0xf374
+#define STB0899_BASE_ACQ_STAT1			0x00000400
+#define STB0899_STEP_FREQ			(0x1fffff << 11)
+#define STB0899_OFFST_STEP_FREQ			11
+#define STB0899_WIDTH_STEP_FREQ			21
+#define STB0899_ACQ_STATE			(0x07 << 8)
+#define STB0899_OFFST_ACQ_STATE			8
+#define STB0899_WIDTH_ACQ_STATE			3
+#define STB0899_UW_DETECT_COUNT			(0xff << 0)
+#define STB0899_OFFST_UW_DETECT_COUNT		0
+#define STB0899_WIDTH_UW_DETECT_COUNT		8
+
+#define STB0899_OFF0_ACQ_TIMEOUT		0xf378
+#define STB0899_BASE_ACQ_TIMEOUT		0x00000400
+#define STB0899_ACQ_TIMEOUT			(0x3fffff << 0)
+#define STB0899_OFFST_ACQ_TIMEOUT		0
+#define STB0899_WIDTH_ACQ_TIMEOUT		22
+
+#define STB0899_OFF0_ACQ_TIME			0xf37c
+#define STB0899_BASE_ACQ_TIME			0x00000400
+#define STB0899_ACQ_TIME_SYM			(0xffffff << 0)
+#define STB0899_OFFST_ACQ_TIME_SYM		0
+#define STB0899_WIDTH_ACQ_TIME_SYM		24
+
+#define STB0899_OFF0_FINAL_AGC_CNTRL		0xf308
+#define STB0899_BASE_FINAL_AGC_CNTRL		0x00000440
+#define STB0899_FINAL_GAIN_INIT			(0x3fff << 12)
+#define STB0899_OFFST_FINAL_GAIN_INIT		12
+#define STB0899_WIDTH_FINAL_GAIN_INIT		14
+#define STB0899_FINAL_LOOP_GAIN			(0x0f << 8)
+#define STB0899_OFFST_FINAL_LOOP_GAIN		8
+#define STB0899_WIDTH_FINAL_LOOP_GAIN		4
+#define STB0899_FINAL_LD_GAIN_INIT		(0x01 << 7)
+#define STB0899_OFFST_FINAL_LD_GAIN_INIT	7
+#define STB0899_WIDTH_FINAL_LD_GAIN_INIT	1
+#define STB0899_FINAL_AGC_REF			(0x7f << 0)
+#define STB0899_OFFST_FINAL_AGC_REF		0
+#define STB0899_WIDTH_FINAL_AGC_REF		7
+
+#define STB0899_OFF0_FINAL_AGC_GAIN		0xf30c
+#define STB0899_BASE_FINAL_AGC_GAIN		0x00000440
+#define STB0899_FINAL_AGC_GAIN			(0x3fff << 0)
+#define STB0899_OFFST_FINAL_AGC_GAIN		0
+#define STB0899_WIDTH_FINAL_AGC_GAIN		14
+
+#define STB0899_OFF0_EQUALIZER_INIT		0xf310
+#define STB0899_BASE_EQUALIZER_INIT		0x00000440
+#define STB0899_EQ_SRST				(0x01 << 1)
+#define STB0899_OFFST_EQ_SRST			1
+#define STB0899_WIDTH_EQ_SRST			1
+#define STB0899_EQ_INIT				(0x01 << 0)
+#define STB0899_OFFST_EQ_INIT			0
+#define STB0899_WIDTH_EQ_INIT			1
+
+#define STB0899_OFF0_EQ_CNTRL			0xf314
+#define STB0899_BASE_EQ_CNTRL			0x00000440
+#define STB0899_EQ_ADAPT_MODE			(0x01 << 18)
+#define STB0899_OFFST_EQ_ADAPT_MODE		18
+#define STB0899_WIDTH_EQ_ADAPT_MODE		1
+#define STB0899_EQ_DELAY			(0x0f << 14)
+#define STB0899_OFFST_EQ_DELAY			14
+#define STB0899_WIDTH_EQ_DELAY			4
+#define STB0899_EQ_QUANT_LEVEL			(0xff << 6)
+#define STB0899_OFFST_EQ_QUANT_LEVEL		6
+#define STB0899_WIDTH_EQ_QUANT_LEVEL		8
+#define STB0899_EQ_DISABLE_UPDATE		(0x01 << 5)
+#define STB0899_OFFST_EQ_DISABLE_UPDATE		5
+#define STB0899_WIDTH_EQ_DISABLE_UPDATE		1
+#define STB0899_EQ_BYPASS			(0x01 << 4)
+#define STB0899_OFFST_EQ_BYPASS			4
+#define STB0899_WIDTH_EQ_BYPASS			1
+#define STB0899_EQ_SHIFT			(0x0f << 0)
+#define STB0899_OFFST_EQ_SHIFT			0
+#define STB0899_WIDTH_EQ_SHIFT			4
+
+#define STB0899_OFF0_EQ_I_INIT_COEFF_0		0xf320
+#define STB0899_OFF1_EQ_I_INIT_COEFF_1		0xf324
+#define STB0899_OFF2_EQ_I_INIT_COEFF_2		0xf328
+#define STB0899_OFF3_EQ_I_INIT_COEFF_3		0xf32c
+#define STB0899_OFF4_EQ_I_INIT_COEFF_4		0xf330
+#define STB0899_OFF5_EQ_I_INIT_COEFF_5		0xf334
+#define STB0899_OFF6_EQ_I_INIT_COEFF_6		0xf338
+#define STB0899_OFF7_EQ_I_INIT_COEFF_7		0xf33c
+#define STB0899_OFF8_EQ_I_INIT_COEFF_8		0xf340
+#define STB0899_OFF9_EQ_I_INIT_COEFF_9		0xf344
+#define STB0899_OFFa_EQ_I_INIT_COEFF_10		0xf348
+#define STB0899_BASE_EQ_I_INIT_COEFF_N		0x00000440
+#define STB0899_EQ_I_INIT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_I_INIT_COEFF_N		0
+#define STB0899_WIDTH_EQ_I_INIT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_Q_INIT_COEFF_0		0xf350
+#define STB0899_OFF1_EQ_Q_INIT_COEFF_1		0xf354
+#define STB0899_OFF2_EQ_Q_INIT_COEFF_2		0xf358
+#define STB0899_OFF3_EQ_Q_INIT_COEFF_3		0xf35c
+#define STB0899_OFF4_EQ_Q_INIT_COEFF_4		0xf360
+#define STB0899_OFF5_EQ_Q_INIT_COEFF_5		0xf364
+#define STB0899_OFF6_EQ_Q_INIT_COEFF_6		0xf368
+#define STB0899_OFF7_EQ_Q_INIT_COEFF_7		0xf36c
+#define STB0899_OFF8_EQ_Q_INIT_COEFF_8		0xf370
+#define STB0899_OFF9_EQ_Q_INIT_COEFF_9		0xf374
+#define STB0899_OFFa_EQ_Q_INIT_COEFF_10		0xf378
+#define STB0899_BASE_EQ_Q_INIT_COEFF_N		0x00000440
+#define STB0899_EQ_Q_INIT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_Q_INIT_COEFF_N		0
+#define STB0899_WIDTH_EQ_Q_INIT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_I_OUT_COEFF_0		0xf300
+#define STB0899_OFF1_EQ_I_OUT_COEFF_1		0xf304
+#define STB0899_OFF2_EQ_I_OUT_COEFF_2		0xf308
+#define STB0899_OFF3_EQ_I_OUT_COEFF_3		0xf30c
+#define STB0899_OFF4_EQ_I_OUT_COEFF_4		0xf310
+#define STB0899_OFF5_EQ_I_OUT_COEFF_5		0xf314
+#define STB0899_OFF6_EQ_I_OUT_COEFF_6		0xf318
+#define STB0899_OFF7_EQ_I_OUT_COEFF_7		0xf31c
+#define STB0899_OFF8_EQ_I_OUT_COEFF_8		0xf320
+#define STB0899_OFF9_EQ_I_OUT_COEFF_9		0xf324
+#define STB0899_OFFa_EQ_I_OUT_COEFF_10		0xf328
+#define STB0899_BASE_EQ_I_OUT_COEFF_N		0x00000460
+#define STB0899_EQ_I_OUT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_I_OUT_COEFF_N		0
+#define STB0899_WIDTH_EQ_I_OUT_COEFF_N		12
+
+#define STB0899_OFF0_EQ_Q_OUT_COEFF_0		0xf330
+#define STB0899_OFF1_EQ_Q_OUT_COEFF_1		0xf334
+#define STB0899_OFF2_EQ_Q_OUT_COEFF_2		0xf338
+#define STB0899_OFF3_EQ_Q_OUT_COEFF_3		0xf33c
+#define STB0899_OFF4_EQ_Q_OUT_COEFF_4		0xf340
+#define STB0899_OFF5_EQ_Q_OUT_COEFF_5		0xf344
+#define STB0899_OFF6_EQ_Q_OUT_COEFF_6		0xf348
+#define STB0899_OFF7_EQ_Q_OUT_COEFF_7		0xf34c
+#define STB0899_OFF8_EQ_Q_OUT_COEFF_8		0xf350
+#define STB0899_OFF9_EQ_Q_OUT_COEFF_9		0xf354
+#define STB0899_OFFa_EQ_Q_OUT_COEFF_10		0xf358
+#define STB0899_BASE_EQ_Q_OUT_COEFF_N		0x00000460
+#define STB0899_EQ_Q_OUT_COEFF_N		(0x0fff << 0)
+#define STB0899_OFFST_EQ_Q_OUT_COEFF_N		0
+#define STB0899_WIDTH_EQ_Q_OUT_COEFF_N		12
+
+/*	S2 FEC	*/
+#define STB0899_OFF0_BLOCK_LNGTH		0xfa04
+#define STB0899_BASE_BLOCK_LNGTH		0x00000000
+#define STB0899_BLOCK_LENGTH			(0xff << 0)
+#define STB0899_OFFST_BLOCK_LENGTH		0
+#define STB0899_WIDTH_BLOCK_LENGTH		8
+
+#define STB0899_OFF0_ROW_STR			0xfa08
+#define STB0899_BASE_ROW_STR			0x00000000
+#define STB0899_ROW_STRIDE			(0xff << 0)
+#define STB0899_OFFST_ROW_STRIDE		0
+#define STB0899_WIDTH_ROW_STRIDE		8
+
+#define STB0899_OFF0_MAX_ITER			0xfa0c
+#define STB0899_BASE_MAX_ITER			0x00000000
+#define STB0899_MAX_ITERATIONS			(0xff << 0)
+#define STB0899_OFFST_MAX_ITERATIONS		0
+#define STB0899_WIDTH_MAX_ITERATIONS		8
+
+#define STB0899_OFF0_BN_END_ADDR		0xfa10
+#define STB0899_BASE_BN_END_ADDR		0x00000000
+#define STB0899_BN_END_ADDR			(0x0fff << 0)
+#define STB0899_OFFST_BN_END_ADDR		0
+#define STB0899_WIDTH_BN_END_ADDR		12
+
+#define STB0899_OFF0_CN_END_ADDR		0xfa14
+#define STB0899_BASE_CN_END_ADDR		0x00000000
+#define STB0899_CN_END_ADDR			(0x0fff << 0)
+#define STB0899_OFFST_CN_END_ADDR		0
+#define STB0899_WIDTH_CN_END_ADDR		12
+
+#define STB0899_OFF0_INFO_LENGTH		0xfa1c
+#define STB0899_BASE_INFO_LENGTH		0x00000000
+#define STB0899_INFO_LENGTH			(0xff << 0)
+#define STB0899_OFFST_INFO_LENGTH		0
+#define STB0899_WIDTH_INFO_LENGTH		8
+
+#define STB0899_OFF0_BOT_ADDR			0xfa20
+#define STB0899_BASE_BOT_ADDR			0x00000000
+#define STB0899_BOTTOM_BASE_ADDR		(0x03ff << 0)
+#define STB0899_OFFST_BOTTOM_BASE_ADDR		0
+#define STB0899_WIDTH_BOTTOM_BASE_ADDR		10
+
+#define STB0899_OFF0_BCH_BLK_LN			0xfa24
+#define STB0899_BASE_BCH_BLK_LN			0x00000000
+#define STB0899_BCH_BLOCK_LENGTH		(0xffff << 0)
+#define STB0899_OFFST_BCH_BLOCK_LENGTH		0
+#define STB0899_WIDTH_BCH_BLOCK_LENGTH		16
+
+#define STB0899_OFF0_BCH_T			0xfa28
+#define STB0899_BASE_BCH_T			0x00000000
+#define STB0899_BCH_T				(0x0f << 0)
+#define STB0899_OFFST_BCH_T			0
+#define STB0899_WIDTH_BCH_T			4
+
+#define STB0899_OFF0_CNFG_MODE			0xfa00
+#define STB0899_BASE_CNFG_MODE			0x00000800
+#define STB0899_MODCOD				(0x1f << 2)
+#define STB0899_OFFST_MODCOD			2
+#define STB0899_WIDTH_MODCOD			5
+#define STB0899_MODCOD_SEL			(0x01 << 1)
+#define STB0899_OFFST_MODCOD_SEL		1
+#define STB0899_WIDTH_MODCOD_SEL		1
+#define STB0899_CONFIG_MODE			(0x01 << 0)
+#define STB0899_OFFST_CONFIG_MODE		0
+#define STB0899_WIDTH_CONFIG_MODE		1
+
+#define STB0899_OFF0_LDPC_STAT			0xfa04
+#define STB0899_BASE_LDPC_STAT			0x00000800
+#define STB0899_ITERATION			(0xff << 3)
+#define STB0899_OFFST_ITERATION			3
+#define STB0899_WIDTH_ITERATION			8
+#define STB0899_LDPC_DEC_STATE			(0x07 << 0)
+#define STB0899_OFFST_LDPC_DEC_STATE		0
+#define STB0899_WIDTH_LDPC_DEC_STATE		3
+
+#define STB0899_OFF0_ITER_SCALE			0xfa08
+#define STB0899_BASE_ITER_SCALE			0x00000800
+#define STB0899_ITERATION_SCALE			(0xff << 0)
+#define STB0899_OFFST_ITERATION_SCALE		0
+#define STB0899_WIDTH_ITERATION_SCALE		8
+
+#define STB0899_OFF0_INPUT_MODE			0xfa0c
+#define STB0899_BASE_INPUT_MODE			0x00000800
+#define STB0899_SD_BLOCK1_STREAM0		(0x01 << 0)
+#define STB0899_OFFST_SD_BLOCK1_STREAM0		0
+#define STB0899_WIDTH_SD_BLOCK1_STREAM0		1
+
+#define STB0899_OFF0_LDPCDECRST			0xfa10
+#define STB0899_BASE_LDPCDECRST			0x00000800
+#define STB0899_LDPC_DEC_RST			(0x01 << 0)
+#define STB0899_OFFST_LDPC_DEC_RST		0
+#define STB0899_WIDTH_LDPC_DEC_RST		1
+
+#define STB0899_OFF0_CLK_PER_BYTE_RW		0xfa14
+#define STB0899_BASE_CLK_PER_BYTE_RW		0x00000800
+#define STB0899_CLKS_PER_BYTE			(0x0f << 0)
+#define STB0899_OFFST_CLKS_PER_BYTE		0
+#define STB0899_WIDTH_CLKS_PER_BYTE		5
+
+#define STB0899_OFF0_BCH_ERRORS			0xfa18
+#define STB0899_BASE_BCH_ERRORS			0x00000800
+#define STB0899_BCH_ERRORS			(0x0f << 0)
+#define STB0899_OFFST_BCH_ERRORS		0
+#define STB0899_WIDTH_BCH_ERRORS		4
+
+#define STB0899_OFF0_LDPC_ERRORS		0xfa1c
+#define STB0899_BASE_LDPC_ERRORS		0x00000800
+#define STB0899_LDPC_ERRORS			(0xffff << 0)
+#define STB0899_OFFST_LDPC_ERRORS		0
+#define STB0899_WIDTH_LDPC_ERRORS		16
+
+#define STB0899_OFF0_BCH_MODE			0xfa20
+#define STB0899_BASE_BCH_MODE			0x00000800
+#define STB0899_BCH_CORRECT_N			(0x01 << 1)
+#define STB0899_OFFST_BCH_CORRECT_N		1
+#define STB0899_WIDTH_BCH_CORRECT_N		1
+#define STB0899_FULL_BYPASS			(0x01 << 0)
+#define STB0899_OFFST_FULL_BYPASS		0
+#define STB0899_WIDTH_FULL_BYPASS		1
+
+#define STB0899_OFF0_ERR_ACC_PER		0xfa24
+#define STB0899_BASE_ERR_ACC_PER		0x00000800
+#define STB0899_BCH_ERR_ACC_PERIOD		(0x0f << 0)
+#define STB0899_OFFST_BCH_ERR_ACC_PERIOD	0
+#define STB0899_WIDTH_BCH_ERR_ACC_PERIOD	4
+
+#define STB0899_OFF0_BCH_ERR_ACC		0xfa28
+#define STB0899_BASE_BCH_ERR_ACC		0x00000800
+#define STB0899_BCH_ERR_ACCUM			(0xff << 0)
+#define STB0899_OFFST_BCH_ERR_ACCUM		0
+#define STB0899_WIDTH_BCH_ERR_ACCUM		8
+
+#define STB0899_OFF0_FEC_CORE_ID_REG		0xfa2c
+#define STB0899_BASE_FEC_CORE_ID_REG		0x00000800
+#define STB0899_FEC_CORE_ID			(0xffffffff << 0)
+#define STB0899_OFFST_FEC_CORE_ID		0
+#define STB0899_WIDTH_FEC_CORE_ID		32
+
+#define STB0899_OFF0_FEC_VER_ID_REG		0xfa34
+#define STB0899_BASE_FEC_VER_ID_REG		0x00000800
+#define STB0899_FEC_VER_ID			(0xff << 0)
+#define STB0899_OFFST_FEC_VER_ID		0
+#define STB0899_WIDTH_FEC_VER_ID		8
+
+#define STB0899_OFF0_FEC_TP_SEL			0xfa38
+#define STB0899_BASE_FEC_TP_SEL			0x00000800
+
+#define STB0899_OFF0_CSM_CNTRL1			0xf310
+#define STB0899_BASE_CSM_CNTRL1			0x00000400
+#define STB0899_CSM_FORCE_FREQLOCK		(0x01 << 19)
+#define STB0899_OFFST_CSM_FORCE_FREQLOCK	19
+#define STB0899_WIDTH_CSM_FORCE_FREQLOCK	1
+#define STB0899_CSM_FREQ_LOCKSTATE		(0x01 << 18)
+#define STB0899_OFFST_CSM_FREQ_LOCKSTATE	18
+#define STB0899_WIDTH_CSM_FREQ_LOCKSTATE	1
+#define STB0899_CSM_AUTO_PARAM			(0x01 << 17)
+#define STB0899_OFFST_CSM_AUTO_PARAM		17
+#define STB0899_WIDTH_CSM_AUTO_PARAM		1
+#define STB0899_FE_LOOP_SHIFT			(0x07 << 14)
+#define STB0899_OFFST_FE_LOOP_SHIFT		14
+#define STB0899_WIDTH_FE_LOOP_SHIFT		3
+#define STB0899_CSM_AGC_SHIFT			(0x07 << 11)
+#define STB0899_OFFST_CSM_AGC_SHIFT		11
+#define STB0899_WIDTH_CSM_AGC_SHIFT		3
+#define STB0899_CSM_AGC_GAIN			(0x09 << 2)
+#define STB0899_OFFST_CSM_AGC_GAIN		2
+#define STB0899_WIDTH_CSM_AGC_GAIN		9
+#define STB0899_CSM_TWO_PASS			(0x01 << 1)
+#define STB0899_OFFST_CSM_TWO_PASS		1
+#define STB0899_WIDTH_CSM_TWO_PASS		1
+#define STB0899_CSM_DVT_TABLE			(0x01 << 0)
+#define STB0899_OFFST_CSM_DVT_TABLE		0
+#define STB0899_WIDTH_CSM_DVT_TABLE		1
+
+#define STB0899_OFF0_CSM_CNTRL2			0xf314
+#define STB0899_BASE_CSM_CNTRL2			0x00000400
+#define STB0899_CSM_GAMMA_RHO_ACQ		(0x09 << 9)
+#define STB0899_OFFST_CSM_GAMMA_RHOACQ		9
+#define STB0899_WIDTH_CSM_GAMMA_RHOACQ		9
+#define STB0899_CSM_GAMMA_ACQ			(0x09 << 0)
+#define STB0899_OFFST_CSM_GAMMA_ACQ		0
+#define STB0899_WIDTH_CSM_GAMMA_ACQ		9
+
+#define STB0899_OFF0_CSM_CNTRL3			0xf320
+#define STB0899_BASE_CSM_CNTRL3			0x00000400
+#define STB0899_CSM_GAMMA_RHO_TRACK		(0x09 << 9)
+#define STB0899_OFFST_CSM_GAMMA_RHOTRACK	9
+#define STB0899_WIDTH_CSM_GAMMA_RHOTRACK	9
+#define STB0899_CSM_GAMMA_TRACK			(0x09 << 0)
+#define STB0899_OFFST_CSM_GAMMA_TRACK		0
+#define STB0899_WIDTH_CSM_GAMMA_TRACK		9
+
+#define STB0899_OFF0_CSM_CNTRL4			0xf324
+#define STB0899_BASE_CSM_CNTRL4			0x00000400
+#define STB0899_CSM_PHASEDIFF_THRESH		(0x0f << 8)
+#define STB0899_OFFST_CSM_PHASEDIFF_THRESH	8
+#define STB0899_WIDTH_CSM_PHASEDIFF_THRESH	4
+#define STB0899_CSM_LOCKCOUNT_THRESH		(0xff << 0)
+#define STB0899_OFFST_CSM_LOCKCOUNT_THRESH	0
+#define STB0899_WIDTH_CSM_LOCKCOUNT_THRESH	8
+
+/*	Check on chapter 8 page 42	*/
+#define STB0899_ERRCTRL1			0xf574
+#define STB0899_ERRCTRL2			0xf575
+#define STB0899_ERRCTRL3			0xf576
+#define STB0899_ERR_SRC_S1			(0x1f << 3)
+#define STB0899_OFFST_ERR_SRC_S1		3
+#define STB0899_WIDTH_ERR_SRC_S1		5
+#define STB0899_ERR_SRC_S2			(0x0f << 0)
+#define STB0899_OFFST_ERR_SRC_S2		0
+#define STB0899_WIDTH_ERR_SRC_S2		4
+#define STB0899_NOE				(0x07 << 0)
+#define STB0899_OFFST_NOE			0
+#define STB0899_WIDTH_NOE			3
+
+#define STB0899_ECNT1M				0xf524
+#define STB0899_ECNT1L				0xf525
+#define STB0899_ECNT2M				0xf526
+#define STB0899_ECNT2L				0xf527
+#define STB0899_ECNT3M				0xf528
+#define STB0899_ECNT3L				0xf529
+
+#define STB0899_DMONMSK1			0xf57b
+#define STB0899_DMONMSK1_WAIT_1STEP		(1 << 7)
+#define STB0899_DMONMSK1_FREE_14		(1 << 6)
+#define STB0899_DMONMSK1_AVRGVIT_CALC		(1 << 5)
+#define STB0899_DMONMSK1_FREE_12		(1 << 4)
+#define STB0899_DMONMSK1_FREE_11		(1 << 3)
+#define STB0899_DMONMSK1_B0DIV_CALC		(1 << 2)
+#define STB0899_DMONMSK1_KDIVB1_CALC		(1 << 1)
+#define STB0899_DMONMSK1_KDIVB2_CALC		(1 << 0)
+
+#define STB0899_DMONMSK0			0xf57c
+#define STB0899_DMONMSK0_SMOTTH_CALC		(1 << 7)
+#define STB0899_DMONMSK0_FREE_6			(1 << 6)
+#define STB0899_DMONMSK0_SIGPOWER_CALC		(1 << 5)
+#define STB0899_DMONMSK0_QSEUIL_CALC		(1 << 4)
+#define STB0899_DMONMSK0_FREE_3			(1 << 3)
+#define STB0899_DMONMSK0_FREE_2			(1 << 2)
+#define STB0899_DMONMSK0_KVDIVB1_CALC		(1 << 1)
+#define STB0899_DMONMSK0_KVDIVB2_CALC		(1 << 0)
+
+#define STB0899_TSULC				0xf549
+#define STB0899_ULNOSYNCBYTES			(0x01 << 7)
+#define STB0899_OFFST_ULNOSYNCBYTES		7
+#define STB0899_WIDTH_ULNOSYNCBYTES		1
+#define STB0899_ULPARITY_ON			(0x01 << 6)
+#define STB0899_OFFST_ULPARITY_ON		6
+#define STB0899_WIDTH_ULPARITY_ON		1
+#define STB0899_ULSYNCOUTRS			(0x01 << 5)
+#define STB0899_OFFST_ULSYNCOUTRS		5
+#define STB0899_WIDTH_ULSYNCOUTRS		1
+#define STB0899_ULDSS_PACKETS			(0x01 << 0)
+#define STB0899_OFFST_ULDSS_PACKETS		0
+#define STB0899_WIDTH_ULDSS_PACKETS		1
+
+#define STB0899_TSLPL				0xf54b
+#define STB0899_LLDVBS2_MODE			(0x01 << 4)
+#define STB0899_OFFST_LLDVBS2_MODE		4
+#define STB0899_WIDTH_LLDVBS2_MODE		1
+#define STB0899_LLISSYI_ON			(0x01 << 3)
+#define STB0899_OFFST_LLISSYI_ON		3
+#define STB0899_WIDTH_LLISSYI_ON		1
+#define STB0899_LLNPD_ON			(0x01 << 2)
+#define STB0899_OFFST_LLNPD_ON			2
+#define STB0899_WIDTH_LLNPD_ON			1
+#define STB0899_LLCRC8_ON			(0x01 << 1)
+#define STB0899_OFFST_LLCRC8_ON			1
+#define STB0899_WIDTH_LLCRC8_ON			1
+
+#define STB0899_TSCFGH				0xf54c
+#define STB0899_OUTRS_PS			(0x01 << 6)
+#define STB0899_OFFST_OUTRS_PS			6
+#define STB0899_WIDTH_OUTRS_PS			1
+#define STB0899_SYNCBYTE			(0x01 << 5)
+#define STB0899_OFFST_SYNCBYTE			5
+#define STB0899_WIDTH_SYNCBYTE			1
+#define STB0899_PFBIT				(0x01 << 4)
+#define STB0899_OFFST_PFBIT			4
+#define STB0899_WIDTH_PFBIT			1
+#define STB0899_ERR_BIT				(0x01 << 3)
+#define STB0899_OFFST_ERR_BIT			3
+#define STB0899_WIDTH_ERR_BIT			1
+#define STB0899_MPEG				(0x01 << 2)
+#define STB0899_OFFST_MPEG			2
+#define STB0899_WIDTH_MPEG			1
+#define STB0899_CLK_POL				(0x01 << 1)
+#define STB0899_OFFST_CLK_POL			1
+#define STB0899_WIDTH_CLK_POL			1
+#define STB0899_FORCE0				(0x01 << 0)
+#define STB0899_OFFST_FORCE0			0
+#define STB0899_WIDTH_FORCE0			1
+
+#define STB0899_TSCFGM				0xf54d
+#define STB0899_LLPRIORITY			(0x01 << 3)
+#define STB0899_OFFST_LLPRIORIY			3
+#define STB0899_WIDTH_LLPRIORITY		1
+#define STB0899_EN188				(0x01 << 2)
+#define STB0899_OFFST_EN188			2
+#define STB0899_WIDTH_EN188			1
+
+#define STB0899_TSCFGL				0xf54e
+#define STB0899_DEL_ERRPCK			(0x01 << 7)
+#define STB0899_OFFST_DEL_ERRPCK		7
+#define STB0899_WIDTH_DEL_ERRPCK		1
+#define STB0899_ERRFLAGSTD			(0x01 << 5)
+#define STB0899_OFFST_ERRFLAGSTD		5
+#define STB0899_WIDTH_ERRFLAGSTD		1
+#define STB0899_MPEGERR				(0x01 << 4)
+#define STB0899_OFFST_MPEGERR			4
+#define STB0899_WIDTH_MPEGERR			1
+#define STB0899_BCH_CHK				(0x01 << 3)
+#define STB0899_OFFST_BCH_CHK			5
+#define STB0899_WIDTH_BCH_CHK			1
+#define STB0899_CRC8CHK				(0x01 << 2)
+#define STB0899_OFFST_CRC8CHK			2
+#define STB0899_WIDTH_CRC8CHK			1
+#define STB0899_SPEC_INFO			(0x01 << 1)
+#define STB0899_OFFST_SPEC_INFO			1
+#define STB0899_WIDTH_SPEC_INFO			1
+#define STB0899_LOW_PRIO_CLK			(0x01 << 0)
+#define STB0899_OFFST_LOW_PRIO_CLK		0
+#define STB0899_WIDTH_LOW_PRIO_CLK		1
+#define STB0899_ERROR_NORM			(0x00 << 0)
+#define STB0899_OFFST_ERROR_NORM		0
+#define STB0899_WIDTH_ERROR_NORM		0
+
+#define STB0899_TSOUT				0xf54f
+#define STB0899_RSSYNCDEL			0xf550
+#define STB0899_TSINHDELH			0xf551
+#define STB0899_TSINHDELM			0xf552
+#define STB0899_TSINHDELL			0xf553
+#define STB0899_TSLLSTKM			0xf55a
+#define STB0899_TSLLSTKL			0xf55b
+#define STB0899_TSULSTKM			0xf55c
+#define STB0899_TSULSTKL			0xf55d
+#define STB0899_TSSTATUS			0xf561
+
+#define STB0899_PDELCTRL			0xf600
+#define STB0899_INVERT_RES			(0x01 << 7)
+#define STB0899_OFFST_INVERT_RES		7
+#define STB0899_WIDTH_INVERT_RES		1
+#define STB0899_FORCE_ACCEPTED			(0x01 << 6)
+#define STB0899_OFFST_FORCE_ACCEPTED		6
+#define STB0899_WIDTH_FORCE_ACCEPTED		1
+#define STB0899_FILTER_EN			(0x01 << 5)
+#define STB0899_OFFST_FILTER_EN			5
+#define STB0899_WIDTH_FILTER_EN			1
+#define STB0899_LOCKFALL_THRESH			(0x01 << 4)
+#define STB0899_OFFST_LOCKFALL_THRESH		4
+#define STB0899_WIDTH_LOCKFALL_THRESH		1
+#define STB0899_HYST_EN				(0x01 << 3)
+#define STB0899_OFFST_HYST_EN			3
+#define STB0899_WIDTH_HYST_EN			1
+#define STB0899_HYST_SWRST			(0x01 << 2)
+#define STB0899_OFFST_HYST_SWRST		2
+#define STB0899_WIDTH_HYST_SWRST		1
+#define STB0899_ALGO_EN				(0x01 << 1)
+#define STB0899_OFFST_ALGO_EN			1
+#define STB0899_WIDTH_ALGO_EN			1
+#define STB0899_ALGO_SWRST			(0x01 << 0)
+#define STB0899_OFFST_ALGO_SWRST		0
+#define STB0899_WIDTH_ALGO_SWRST		1
+
+#define STB0899_PDELCTRL2			0xf601
+#define STB0899_BBHCTRL1			0xf602
+#define STB0899_BBHCTRL2			0xf603
+#define STB0899_HYSTTHRESH			0xf604
+
+#define STB0899_MATCSTM				0xf605
+#define STB0899_MATCSTL				0xf606
+#define STB0899_UPLCSTM				0xf607
+#define STB0899_UPLCSTL				0xf608
+#define STB0899_DFLCSTM				0xf609
+#define STB0899_DFLCSTL				0xf60a
+#define STB0899_SYNCCST				0xf60b
+#define STB0899_SYNCDCSTM			0xf60c
+#define STB0899_SYNCDCSTL			0xf60d
+#define STB0899_ISI_ENTRY			0xf60e
+#define STB0899_ISI_BIT_EN			0xf60f
+#define STB0899_MATSTRM				0xf610
+#define STB0899_MATSTRL				0xf611
+#define STB0899_UPLSTRM				0xf612
+#define STB0899_UPLSTRL				0xf613
+#define STB0899_DFLSTRM				0xf614
+#define STB0899_DFLSTRL				0xf615
+#define STB0899_SYNCSTR				0xf616
+#define STB0899_SYNCDSTRM			0xf617
+#define STB0899_SYNCDSTRL			0xf618
+
+#define STB0899_CFGPDELSTATUS1			0xf619
+#define STB0899_BADDFL				(0x01 << 6)
+#define STB0899_OFFST_BADDFL			6
+#define STB0899_WIDTH_BADDFL			1
+#define STB0899_CONTINUOUS_STREAM		(0x01 << 5)
+#define STB0899_OFFST_CONTINUOUS_STREAM		5
+#define STB0899_WIDTH_CONTINUOUS_STREAM		1
+#define STB0899_ACCEPTED_STREAM			(0x01 << 4)
+#define STB0899_OFFST_ACCEPTED_STREAM		4
+#define STB0899_WIDTH_ACCEPTED_STREAM		1
+#define STB0899_BCH_ERRFLAG			(0x01 << 3)
+#define STB0899_OFFST_BCH_ERRFLAG		3
+#define STB0899_WIDTH_BCH_ERRFLAG		1
+#define STB0899_CRCRES				(0x01 << 2)
+#define STB0899_OFFST_CRCRES			2
+#define STB0899_WIDTH_CRCRES			1
+#define STB0899_CFGPDELSTATUS_LOCK		(0x01 << 1)
+#define STB0899_OFFST_CFGPDELSTATUS_LOCK	1
+#define STB0899_WIDTH_CFGPDELSTATUS_LOCK	1
+#define STB0899_1STLOCK				(0x01 << 0)
+#define STB0899_OFFST_1STLOCK			0
+#define STB0899_WIDTH_1STLOCK			1
+
+#define STB0899_CFGPDELSTATUS2			0xf61a
+#define STB0899_BBFERRORM			0xf61b
+#define STB0899_BBFERRORL			0xf61c
+#define STB0899_UPKTERRORM			0xf61d
+#define STB0899_UPKTERRORL			0xf61e
+
+#define STB0899_TSTCK				0xff10
+
+#define STB0899_TSTRES				0xff11
+#define STB0899_FRESLDPC			(0x01 << 7)
+#define STB0899_OFFST_FRESLDPC			7
+#define STB0899_WIDTH_FRESLDPC			1
+#define STB0899_FRESRS				(0x01 << 6)
+#define STB0899_OFFST_FRESRS			6
+#define STB0899_WIDTH_FRESRS			1
+#define STB0899_FRESVIT				(0x01 << 5)
+#define STB0899_OFFST_FRESVIT			5
+#define STB0899_WIDTH_FRESVIT			1
+#define STB0899_FRESMAS1_2			(0x01 << 4)
+#define STB0899_OFFST_FRESMAS1_2		4
+#define STB0899_WIDTH_FRESMAS1_2		1
+#define STB0899_FRESACS				(0x01 << 3)
+#define STB0899_OFFST_FRESACS			3
+#define STB0899_WIDTH_FRESACS			1
+#define STB0899_FRESSYM				(0x01 << 2)
+#define STB0899_OFFST_FRESSYM			2
+#define STB0899_WIDTH_FRESSYM			1
+#define STB0899_FRESMAS				(0x01 << 1)
+#define STB0899_OFFST_FRESMAS			1
+#define STB0899_WIDTH_FRESMAS			1
+#define STB0899_FRESINT				(0x01 << 0)
+#define STB0899_OFFST_FRESINIT			0
+#define STB0899_WIDTH_FRESINIT			1
+
+#define STB0899_TSTOUT				0xff12
+#define STB0899_EN_SIGNATURE			(0x01 << 7)
+#define STB0899_OFFST_EN_SIGNATURE		7
+#define STB0899_WIDTH_EN_SIGNATURE		1
+#define STB0899_BCLK_CLK			(0x01 << 6)
+#define STB0899_OFFST_BCLK_CLK			6
+#define STB0899_WIDTH_BCLK_CLK			1
+#define STB0899_SGNL_OUT			(0x01 << 5)
+#define STB0899_OFFST_SGNL_OUT			5
+#define STB0899_WIDTH_SGNL_OUT			1
+#define STB0899_TS				(0x01 << 4)
+#define STB0899_OFFST_TS			4
+#define STB0899_WIDTH_TS			1
+#define STB0899_CTEST				(0x01 << 0)
+#define STB0899_OFFST_CTEST			0
+#define STB0899_WIDTH_CTEST			1
+
+#define STB0899_TSTIN				0xff13
+#define STB0899_TEST_IN				(0x01 << 7)
+#define STB0899_OFFST_TEST_IN			7
+#define STB0899_WIDTH_TEST_IN			1
+#define STB0899_EN_ADC				(0x01 << 6)
+#define STB0899_OFFST_EN_ADC			6
+#define STB0899_WIDTH_ENADC			1
+#define STB0899_SGN_ADC				(0x01 << 5)
+#define STB0899_OFFST_SGN_ADC			5
+#define STB0899_WIDTH_SGN_ADC			1
+#define STB0899_BCLK_IN				(0x01 << 4)
+#define STB0899_OFFST_BCLK_IN			4
+#define STB0899_WIDTH_BCLK_IN			1
+#define STB0899_JETONIN_MODE			(0x01 << 3)
+#define STB0899_OFFST_JETONIN_MODE		3
+#define STB0899_WIDTH_JETONIN_MODE		1
+#define STB0899_BCLK_VALUE			(0x01 << 2)
+#define STB0899_OFFST_BCLK_VALUE		2
+#define STB0899_WIDTH_BCLK_VALUE		1
+#define STB0899_SGNRST_T12			(0x01 << 1)
+#define STB0899_OFFST_SGNRST_T12		1
+#define STB0899_WIDTH_SGNRST_T12		1
+#define STB0899_LOWSP_ENAX			(0x01 << 0)
+#define STB0899_OFFST_LOWSP_ENAX		0
+#define STB0899_WIDTH_LOWSP_ENAX		1
+
+#define STB0899_TSTSYS				0xff14
+#define STB0899_TSTCHIP				0xff15
+#define STB0899_TSTFREE				0xff16
+#define STB0899_TSTI2C				0xff17
+#define STB0899_BITSPEEDM			0xff1c
+#define STB0899_BITSPEEDL			0xff1d
+#define STB0899_TBUSBIT				0xff1e
+#define STB0899_TSTDIS				0xff24
+#define STB0899_TSTDISRX			0xff25
+#define STB0899_TSTJETON			0xff28
+#define STB0899_TSTDCADJ			0xff40
+#define STB0899_TSTAGC1				0xff41
+#define STB0899_TSTAGC1N			0xff42
+#define STB0899_TSTPOLYPH			0xff48
+#define STB0899_TSTR				0xff49
+#define STB0899_TSTAGC2				0xff4a
+#define STB0899_TSTCTL1				0xff4b
+#define STB0899_TSTCTL2				0xff4c
+#define STB0899_TSTCTL3				0xff4d
+#define STB0899_TSTDEMAP			0xff50
+#define STB0899_TSTDEMAP2			0xff51
+#define STB0899_TSTDEMMON			0xff52
+#define STB0899_TSTRATE				0xff53
+#define STB0899_TSTSELOUT			0xff54
+#define STB0899_TSYNC				0xff55
+#define STB0899_TSTERR				0xff56
+#define STB0899_TSTRAM1				0xff58
+#define STB0899_TSTVSELOUT			0xff59
+#define STB0899_TSTFORCEIN			0xff5a
+#define STB0899_TSTRS1				0xff5c
+#define STB0899_TSTRS2				0xff5d
+#define STB0899_TSTRS3				0xff53
+
+#define STB0899_INTBUFSTATUS			0xf200
+#define STB0899_INTBUFCTRL			0xf201
+#define STB0899_PCKLENUL			0xf55e
+#define STB0899_PCKLENLL			0xf55f
+#define STB0899_RSPCKLEN			0xf560
+
+/*	2 registers	*/
+#define STB0899_SYNCDCST			0xf60c
+
+/*	DiSEqC	*/
+#define STB0899_DISCNTRL1			0xf0a0
+#define STB0899_TIMOFF				(0x01 << 7)
+#define STB0899_OFFST_TIMOFF			7
+#define STB0899_WIDTH_TIMOFF			1
+#define STB0899_DISEQCRESET			(0x01 << 6)
+#define STB0899_OFFST_DISEQCRESET		6
+#define STB0899_WIDTH_DISEQCRESET		1
+#define STB0899_TIMCMD				(0x03 << 4)
+#define STB0899_OFFST_TIMCMD			4
+#define STB0899_WIDTH_TIMCMD			2
+#define STB0899_DISPRECHARGE			(0x01 << 2)
+#define STB0899_OFFST_DISPRECHARGE		2
+#define STB0899_WIDTH_DISPRECHARGE		1
+#define STB0899_DISEQCMODE			(0x01 << 0)
+#define STB0899_OFFST_DISEQCMODE		0
+#define STB0899_WIDTH_DISEQCMODE		2
+
+#define STB0899_DISCNTRL2			0xf0a1
+#define STB0899_RECEIVER_ON			(0x01 << 7)
+#define STB0899_OFFST_RECEIVER_ON		7
+#define STB0899_WIDTH_RECEIVER_ON		1
+#define STB0899_IGNO_SHORT_22K			(0x01 << 6)
+#define STB0899_OFFST_IGNO_SHORT_22K		6
+#define STB0899_WIDTH_IGNO_SHORT_22K		1
+#define STB0899_ONECHIP_TRX			(0x01 << 5)
+#define STB0899_OFFST_ONECHIP_TRX		5
+#define STB0899_WIDTH_ONECHIP_TRX		1
+#define STB0899_EXT_ENVELOP			(0x01 << 4)
+#define STB0899_OFFST_EXT_ENVELOP		4
+#define STB0899_WIDTH_EXT_ENVELOP		1
+#define STB0899_PIN_SELECT			(0x03 << 2)
+#define STB0899_OFFST_PIN_SELCT			2
+#define STB0899_WIDTH_PIN_SELCT			2
+#define STB0899_IRQ_RXEND			(0x01 << 1)
+#define STB0899_OFFST_IRQ_RXEND			1
+#define STB0899_WIDTH_IRQ_RXEND			1
+#define STB0899_IRQ_4NBYTES			(0x01 << 0)
+#define STB0899_OFFST_IRQ_4NBYTES		0
+#define STB0899_WIDTH_IRQ_4NBYTES		1
+
+#define STB0899_DISRX_ST0			0xf0a4
+#define STB0899_RXEND				(0x01 << 7)
+#define STB0899_OFFST_RXEND			7
+#define STB0899_WIDTH_RXEND			1
+#define STB0899_RXACTIVE			(0x01 << 6)
+#define STB0899_OFFST_RXACTIVE			6
+#define STB0899_WIDTH_RXACTIVE			1
+#define STB0899_SHORT22K			(0x01 << 5)
+#define STB0899_OFFST_SHORT22K			5
+#define STB0899_WIDTH_SHORT22K			1
+#define STB0899_CONTTONE			(0x01 << 4)
+#define STB0899_OFFST_CONTTONE			4
+#define STB0899_WIDTH_CONTONE			1
+#define STB0899_4BFIFOREDY			(0x01 << 3)
+#define STB0899_OFFST_4BFIFOREDY		3
+#define STB0899_WIDTH_4BFIFOREDY		1
+#define STB0899_FIFOEMPTY			(0x01 << 2)
+#define STB0899_OFFST_FIFOEMPTY			2
+#define STB0899_WIDTH_FIFOEMPTY			1
+#define STB0899_ABORTTRX			(0x01 << 0)
+#define STB0899_OFFST_ABORTTRX			0
+#define STB0899_WIDTH_ABORTTRX			1
+
+#define STB0899_DISRX_ST1			0xf0a5
+#define STB0899_RXFAIL				(0x01 << 7)
+#define STB0899_OFFST_RXFAIL			7
+#define STB0899_WIDTH_RXFAIL			1
+#define STB0899_FIFOPFAIL			(0x01 << 6)
+#define STB0899_OFFST_FIFOPFAIL			6
+#define STB0899_WIDTH_FIFOPFAIL			1
+#define STB0899_RXNONBYTES			(0x01 << 5)
+#define STB0899_OFFST_RXNONBYTES		5
+#define STB0899_WIDTH_RXNONBYTES		1
+#define STB0899_FIFOOVF				(0x01 << 4)
+#define STB0899_OFFST_FIFOOVF			4
+#define STB0899_WIDTH_FIFOOVF			1
+#define STB0899_FIFOBYTENBR			(0x0f << 0)
+#define STB0899_OFFST_FIFOBYTENBR		0
+#define STB0899_WIDTH_FIFOBYTENBR		4
+
+#define STB0899_DISPARITY			0xf0a6
+
+#define STB0899_DISFIFO				0xf0a7
+
+#define STB0899_DISSTATUS			0xf0a8
+#define STB0899_FIFOFULL			(0x01 << 6)
+#define STB0899_OFFST_FIFOFULL			6
+#define STB0899_WIDTH_FIFOFULL			1
+#define STB0899_TXIDLE				(0x01 << 5)
+#define STB0899_OFFST_TXIDLE			5
+#define STB0899_WIDTH_TXIDLE			1
+#define STB0899_GAPBURST			(0x01 << 4)
+#define STB0899_OFFST_GAPBURST			4
+#define STB0899_WIDTH_GAPBURST			1
+#define STB0899_TXFIFOBYTES			(0x0f << 0)
+#define STB0899_OFFST_TXFIFOBYTES		0
+#define STB0899_WIDTH_TXFIFOBYTES		4
+#define STB0899_DISF22				0xf0a9
+
+#define STB0899_DISF22RX			0xf0aa
+
+/*	General Purpose	*/
+#define STB0899_SYSREG				0xf101
+#define STB0899_ACRPRESC			0xf110
+#define STB0899_ACRDIV1				0xf111
+#define STB0899_ACRDIV2				0xf112
+#define STB0899_DACR1				0xf113
+#define STB0899_DACR2				0xf114
+#define STB0899_OUTCFG				0xf11c
+#define STB0899_MODECFG				0xf11d
+#define STB0899_NCOARSE				0xf1b3
+
+#define STB0899_SYNTCTRL			0xf1b6
+#define STB0899_STANDBY				(0x01 << 7)
+#define STB0899_OFFST_STANDBY			7
+#define STB0899_WIDTH_STANDBY			1
+#define STB0899_BYPASSPLL			(0x01 << 6)
+#define STB0899_OFFST_BYPASSPLL			6
+#define STB0899_WIDTH_BYPASSPLL			1
+#define STB0899_SEL1XRATIO			(0x01 << 5)
+#define STB0899_OFFST_SEL1XRATIO		5
+#define STB0899_WIDTH_SEL1XRATIO		1
+#define STB0899_SELOSCI				(0x01 << 1)
+#define STB0899_OFFST_SELOSCI			1
+#define STB0899_WIDTH_SELOSCI			1
+
+#define STB0899_FILTCTRL			0xf1b7
+#define STB0899_SYSCTRL				0xf1b8
+
+#define STB0899_STOPCLK1			0xf1c2
+#define STB0899_STOP_CKINTBUF108		(0x01 << 7)
+#define STB0899_OFFST_STOP_CKINTBUF108		7
+#define STB0899_WIDTH_STOP_CKINTBUF108		1
+#define STB0899_STOP_CKINTBUF216		(0x01 << 6)
+#define STB0899_OFFST_STOP_CKINTBUF216		6
+#define STB0899_WIDTH_STOP_CKINTBUF216		1
+#define STB0899_STOP_CHK8PSK			(0x01 << 5)
+#define STB0899_OFFST_STOP_CHK8PSK		5
+#define STB0899_WIDTH_STOP_CHK8PSK		1
+#define STB0899_STOP_CKFEC108			(0x01 << 4)
+#define STB0899_OFFST_STOP_CKFEC108		4
+#define STB0899_WIDTH_STOP_CKFEC108		1
+#define STB0899_STOP_CKFEC216			(0x01 << 3)
+#define STB0899_OFFST_STOP_CKFEC216		3
+#define STB0899_WIDTH_STOP_CKFEC216		1
+#define STB0899_STOP_CKCORE216			(0x01 << 2)
+#define STB0899_OFFST_STOP_CKCORE216		2
+#define STB0899_WIDTH_STOP_CKCORE216		1
+#define STB0899_STOP_CKADCI108			(0x01 << 1)
+#define STB0899_OFFST_STOP_CKADCI108		1
+#define STB0899_WIDTH_STOP_CKADCI108		1
+#define STB0899_STOP_INVCKADCI108		(0x01 << 0)
+#define STB0899_OFFST_STOP_INVCKADCI108		0
+#define STB0899_WIDTH_STOP_INVCKADCI108		1
+
+#define STB0899_STOPCLK2			0xf1c3
+#define STB0899_STOP_CKS2DMD108			(0x01 << 2)
+#define STB0899_OFFST_STOP_CKS2DMD108		2
+#define STB0899_WIDTH_STOP_CKS2DMD108		1
+#define STB0899_STOP_CKPKDLIN108		(0x01 << 1)
+#define STB0899_OFFST_STOP_CKPKDLIN108		1
+#define STB0899_WIDTH_STOP_CKPKDLIN108		1
+#define STB0899_STOP_CKPKDLIN216		(0x01 << 0)
+#define STB0899_OFFST_STOP_CKPKDLIN216		0
+#define STB0899_WIDTH_STOP_CKPKDLIN216		1
+
+#define STB0899_TSTTNR1				0xf1e0
+#define STB0899_BYPASS_ADC			(0x01 << 7)
+#define STB0899_OFFST_BYPASS_ADC		7
+#define STB0899_WIDTH_BYPASS_ADC		1
+#define STB0899_INVADCICKOUT			(0x01 << 6)
+#define STB0899_OFFST_INVADCICKOUT		6
+#define STB0899_WIDTH_INVADCICKOUT		1
+#define STB0899_ADCTEST_VOLTAGE			(0x03 << 4)
+#define STB0899_OFFST_ADCTEST_VOLTAGE		4
+#define STB0899_WIDTH_ADCTEST_VOLTAGE		1
+#define STB0899_ADC_RESET			(0x01 << 3)
+#define STB0899_OFFST_ADC_RESET			3
+#define STB0899_WIDTH_ADC_RESET			1
+#define STB0899_TSTTNR1_2			(0x01 << 2)
+#define STB0899_OFFST_TSTTNR1_2			2
+#define STB0899_WIDTH_TSTTNR1_2			1
+#define STB0899_ADCPON				(0x01 << 1)
+#define STB0899_OFFST_ADCPON			1
+#define STB0899_WIDTH_ADCPON			1
+#define STB0899_ADCIN_MODE			(0x01 << 0)
+#define STB0899_OFFST_ADCIN_MODE		0
+#define STB0899_WIDTH_ADCIN_MODE		1
+
+#define STB0899_TSTTNR2				0xf1e1
+#define STB0899_TSTTNR2_7			(0x01 << 7)
+#define STB0899_OFFST_TSTTNR2_7			7
+#define STB0899_WIDTH_TSTTNR2_7			1
+#define STB0899_NOT_DISRX_WIRED			(0x01 << 6)
+#define STB0899_OFFST_NOT_DISRX_WIRED		6
+#define STB0899_WIDTH_NOT_DISRX_WIRED		1
+#define STB0899_DISEQC_DCURRENT			(0x01 << 5)
+#define STB0899_OFFST_DISEQC_DCURRENT		5
+#define STB0899_WIDTH_DISEQC_DCURRENT		1
+#define STB0899_DISEQC_ZCURRENT			(0x01 << 4)
+#define STB0899_OFFST_DISEQC_ZCURRENT		4
+#define STB0899_WIDTH_DISEQC_ZCURRENT		1
+#define STB0899_DISEQC_SINC_SOURCE		(0x03 << 2)
+#define STB0899_OFFST_DISEQC_SINC_SOURCE	2
+#define STB0899_WIDTH_DISEQC_SINC_SOURCE	2
+#define STB0899_SELIQSRC			(0x03 << 0)
+#define STB0899_OFFST_SELIQSRC			0
+#define STB0899_WIDTH_SELIQSRC			2
+
+#define STB0899_TSTTNR3				0xf1e2
+
+#define STB0899_I2CCFG				0xf129
+#define STB0899_I2CCFGRSVD			(0x0f << 4)
+#define STB0899_OFFST_I2CCFGRSVD		4
+#define STB0899_WIDTH_I2CCFGRSVD		4
+#define STB0899_I2CFASTMODE			(0x01 << 3)
+#define STB0899_OFFST_I2CFASTMODE		3
+#define STB0899_WIDTH_I2CFASTMODE		1
+#define STB0899_STATUSWR			(0x01 << 2)
+#define STB0899_OFFST_STATUSWR			2
+#define STB0899_WIDTH_STATUSWR			1
+#define STB0899_I2CADDRINC			(0x03 << 0)
+#define STB0899_OFFST_I2CADDRINC		0
+#define STB0899_WIDTH_I2CADDRINC		2
+
+#define STB0899_I2CRPT				0xf12a
+#define STB0899_I2CTON				(0x01 << 7)
+#define STB0899_OFFST_I2CTON			7
+#define STB0899_WIDTH_I2CTON			1
+#define STB0899_ENARPTLEVEL			(0x01 << 6)
+#define STB0899_OFFST_ENARPTLEVEL		6
+#define STB0899_WIDTH_ENARPTLEVEL		2
+#define STB0899_SCLTDELAY			(0x01 << 3)
+#define STB0899_OFFST_SCLTDELAY			3
+#define STB0899_WIDTH_SCLTDELAY			1
+#define STB0899_STOPENA				(0x01 << 2)
+#define STB0899_OFFST_STOPENA			2
+#define STB0899_WIDTH_STOPENA			1
+#define STB0899_STOPSDAT2SDA			(0x01 << 1)
+#define STB0899_OFFST_STOPSDAT2SDA		1
+#define STB0899_WIDTH_STOPSDAT2SDA		1
+
+#define STB0899_IOPVALUE8			0xf136
+#define STB0899_IOPVALUE7			0xf137
+#define STB0899_IOPVALUE6			0xf138
+#define STB0899_IOPVALUE5			0xf139
+#define STB0899_IOPVALUE4			0xf13a
+#define STB0899_IOPVALUE3			0xf13b
+#define STB0899_IOPVALUE2			0xf13c
+#define STB0899_IOPVALUE1			0xf13d
+#define STB0899_IOPVALUE0			0xf13e
+
+#define STB0899_GPIO00CFG			0xf140
+
+#define STB0899_GPIO01CFG			0xf141
+#define STB0899_GPIO02CFG			0xf142
+#define STB0899_GPIO03CFG			0xf143
+#define STB0899_GPIO04CFG			0xf144
+#define STB0899_GPIO05CFG			0xf145
+#define STB0899_GPIO06CFG			0xf146
+#define STB0899_GPIO07CFG			0xf147
+#define STB0899_GPIO08CFG			0xf148
+#define STB0899_GPIO09CFG			0xf149
+#define STB0899_GPIO10CFG			0xf14a
+#define STB0899_GPIO11CFG			0xf14b
+#define STB0899_GPIO12CFG			0xf14c
+#define STB0899_GPIO13CFG			0xf14d
+#define STB0899_GPIO14CFG			0xf14e
+#define STB0899_GPIO15CFG			0xf14f
+#define STB0899_GPIO16CFG			0xf150
+#define STB0899_GPIO17CFG			0xf151
+#define STB0899_GPIO18CFG			0xf152
+#define STB0899_GPIO19CFG			0xf153
+#define STB0899_GPIO20CFG			0xf154
+
+#define STB0899_SDATCFG				0xf155
+#define STB0899_SCLTCFG				0xf156
+#define STB0899_AGCRFCFG			0xf157
+#define STB0899_GPIO22				0xf158	/* AGCBB2CFG	*/
+#define STB0899_GPIO21				0xf159  /* AGCBB1CFG	*/
+#define STB0899_DIRCLKCFG			0xf15a
+#define STB0899_CLKOUT27CFG			0xf15b
+#define STB0899_STDBYCFG			0xf15c
+#define STB0899_CS0CFG				0xf15d
+#define STB0899_CS1CFG				0xf15e
+#define STB0899_DISEQCOCFG			0xf15f
+
+#define STB0899_GPIO32CFG			0xf160
+#define STB0899_GPIO33CFG			0xf161
+#define STB0899_GPIO34CFG			0xf162
+#define STB0899_GPIO35CFG			0xf163
+#define STB0899_GPIO36CFG			0xf164
+#define STB0899_GPIO37CFG			0xf165
+#define STB0899_GPIO38CFG			0xf166
+#define STB0899_GPIO39CFG			0xf167
+
+#define STB0899_IRQSTATUS_3			0xf120
+#define STB0899_IRQSTATUS_2			0xf121
+#define STB0899_IRQSTATUS_1			0xf122
+#define STB0899_IRQSTATUS_0			0xf123
+
+#define STB0899_IRQMSK_3			0xf124
+#define STB0899_IRQMSK_2			0xf125
+#define STB0899_IRQMSK_1			0xf126
+#define STB0899_IRQMSK_0			0xf127
+
+#define STB0899_IRQCFG				0xf128
+
+#define STB0899_GHOSTREG			0xf000
+
+#define STB0899_S2DEMOD				0xf3fc
+#define STB0899_S2FEC				0xfafc
+
+
+#endif
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/stb6100.c linux-2.6.22.1-new/drivers/media/dvb/frontends/stb6100.c
--- linux-2.6.22.1/drivers/media/dvb/frontends/stb6100.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/stb6100.c	2007-07-28 01:17:12.000000000 +0200
@@ -0,0 +1,589 @@
+/*
+	STB6100 Silicon Tuner
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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/string.h>
+
+#include "dvb_frontend.h"
+#include "stb6100.h"
+
+//static unsigned int verbose;
+static unsigned int verbose = 0;
+module_param(verbose, int, 0644);
+
+#define FE_ERROR		0
+#define FE_NOTICE		1
+#define FE_INFO			2
+#define FE_DEBUG		3
+
+#define dprintk(x, y, z, format, arg...) do {						\
+	if (z) {									\
+		if	((x > FE_ERROR) && (x > y))					\
+			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\
+		else if	((x > FE_NOTICE) && (x > y))					\
+			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\
+		else if ((x > FE_INFO) && (x > y))					\
+			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\
+		else if ((x > FE_DEBUG) && (x > y))					\
+			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\
+	} else {									\
+		if (x > y)								\
+			printk(format, ##arg);						\
+	}										\
+} while(0)
+
+struct stb6100_lkup {
+	u32 val_low;
+	u32 val_high;
+	u8   reg;
+};
+
+static int stb6100_release(struct dvb_frontend *fe);
+
+static const struct stb6100_lkup lkup[] = {
+	{       0,  950000, 0x0a },
+	{  950000, 1000000, 0x0a },
+	{ 1000000, 1075000, 0x0c },
+	{ 1075000, 1200000, 0x00 },
+	{ 1200000, 1300000, 0x01 },
+	{ 1300000, 1370000, 0x02 },
+	{ 1370000, 1470000, 0x04 },
+	{ 1470000, 1530000, 0x05 },
+	{ 1530000, 1650000, 0x06 },
+	{ 1650000, 1800000, 0x08 },
+	{ 1800000, 1950000, 0x0a },
+	{ 1950000, 2150000, 0x0c },
+	{ 2150000, 9999999, 0x0c },
+	{       0,       0, 0x00 }
+};
+
+/* Register names for easy debugging.	*/
+static const char *stb6100_regnames[] = {
+	[STB6100_LD]		= "LD",
+	[STB6100_VCO]		= "VCO",
+	[STB6100_NI]		= "NI",
+	[STB6100_NF_LSB]	= "NF",
+	[STB6100_K]		= "K",
+	[STB6100_G]		= "G",
+	[STB6100_F]		= "F",
+	[STB6100_DLB]		= "DLB",
+	[STB6100_TEST1]		= "TEST1",
+	[STB6100_FCCK]		= "FCCK",
+	[STB6100_LPEN]		= "LPEN",
+	[STB6100_TEST3]		= "TEST3",
+};
+
+/* Template for normalisation, i.e. setting unused or undocumented
+ * bits as required according to the documentation.
+ */
+struct stb6100_regmask {
+	u8 mask;
+	u8 set;
+};
+
+static const struct stb6100_regmask stb6100_template[] = {
+	[STB6100_LD]		= { 0xff, 0x00 },
+	[STB6100_VCO]		= { 0xff, 0x00 },
+	[STB6100_NI]		= { 0xff, 0x00 },
+	[STB6100_NF_LSB]	= { 0xff, 0x00 },
+	[STB6100_K]		= { 0xc7, 0x38 },
+	[STB6100_G]		= { 0xef, 0x10 },
+	[STB6100_F]		= { 0x1f, 0xc0 },
+	[STB6100_DLB]		= { 0x38, 0xc4 },
+	[STB6100_TEST1]		= { 0x00, 0x8f },
+	[STB6100_FCCK]		= { 0x40, 0x0d },
+	[STB6100_LPEN]		= { 0xf0, 0x0b },
+	[STB6100_TEST3]		= { 0x00, 0xde },
+};
+
+static void stb6100_normalise_regs(u8 regs[])
+{
+	int i;
+
+	for (i = 0; i < STB6100_NUMREGS; i++)
+		regs[i] = (regs[i] & stb6100_template[i].mask) | stb6100_template[i].set;
+}
+
+static int stb6100_read_regs(struct stb6100_state *state, u8 regs[])
+{
+	int rc;
+	struct i2c_msg msg = {
+		.addr	= state->config->tuner_address,
+		.flags	= I2C_M_RD,
+		.buf	= regs,
+		.len	= STB6100_NUMREGS
+	};
+
+	if (state->frontend->ops.i2c_gate_ctrl)
+		if ((rc = state->frontend->ops.i2c_gate_ctrl(state->frontend, 1)) < 0)
+			return rc;
+
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (state->frontend->ops.i2c_gate_ctrl) {
+		int rc2;
+		if ((rc2 = state->frontend->ops.i2c_gate_ctrl(state->frontend, 0)) < 0)
+			return rc2;
+	}
+	if (unlikely(rc != 1)) {
+		dprintk(verbose, FE_ERROR, 1, "Read (0x%x) err, rc=[%d]",
+			state->config->tuner_address, rc);
+
+		return -EREMOTEIO;
+	}
+	if (unlikely(verbose > FE_DEBUG)) {
+		int i;
+
+		dprintk(verbose, FE_DEBUG, 1, "    Read from 0x%02x", state->config->tuner_address);
+		for (i = 0; i < STB6100_NUMREGS; i++)
+			dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[i], regs[i]);
+	}
+	return 0;
+}
+
+static int stb6100_read_reg(struct stb6100_state *state, u8 reg)
+{
+	u8 regs[STB6100_NUMREGS];
+	int rc;
+
+	if (unlikely(reg >= STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
+		return -EINVAL;
+	}
+	if ((rc = stb6100_read_regs(state, regs)) < 0)
+		return rc;
+	return (unsigned int)regs[reg];
+}
+
+static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len)
+{
+	int rc;
+	u8 cmdbuf[len + 1];
+	struct i2c_msg msg = {
+		.addr	= state->config->tuner_address,
+		.flags	= 0,
+		.buf	= cmdbuf,
+		.len	= len + 1
+	};
+
+	if (unlikely(start < 1 || start + len > STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register range %d:%d",
+			start, len);
+		return -EINVAL;
+	}
+	memcpy(&cmdbuf[1], buf, len);
+	cmdbuf[0] = start;
+
+	if (unlikely(verbose > FE_DEBUG)) {
+		int i;
+
+		dprintk(verbose, FE_DEBUG, 1, "    Write @ 0x%02x: [%d:%d]", state->config->tuner_address, start, len);
+		for (i = 0; i < len; i++)
+			dprintk(verbose, FE_DEBUG, 1, "        %s: 0x%02x", stb6100_regnames[start + i], buf[i]);
+	}
+	if (state->frontend->ops.i2c_gate_ctrl)
+		if ((rc = state->frontend->ops.i2c_gate_ctrl(state->frontend, 1)) < 0)
+			return rc;
+	rc = i2c_transfer(state->i2c, &msg, 1);
+	if (state->frontend->ops.i2c_gate_ctrl) {
+		int rc2;
+		if ((rc2 = state->frontend->ops.i2c_gate_ctrl(state->frontend, 0)) < 0)
+			return rc2;
+	}
+	if (unlikely(rc != 1)) {
+		dprintk(verbose, FE_ERROR, 1, "(0x%x) write err [%d:%d], rc=[%d]",
+			(unsigned int)state->config->tuner_address, start, len,	rc);
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
+static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
+{
+	if (unlikely(reg >= STB6100_NUMREGS)) {
+		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
+		return -EREMOTEIO;
+	}
+	data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
+	return stb6100_write_reg_range(state, &data, reg, 1);
+}
+
+static int stb6100_write_regs(struct stb6100_state *state, u8 regs[])
+{
+	stb6100_normalise_regs(regs);
+	return stb6100_write_reg_range(state, &regs[1], 1, STB6100_NUMREGS - 1);
+}
+
+static int stb6100_get_status(struct dvb_frontend *fe, u32 *status)
+{
+	int rc;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	if ((rc = stb6100_read_reg(state, STB6100_LD)) < 0)
+		return rc;
+
+	return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0;
+}
+
+static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	int rc;
+	u8 f;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	if ((rc = stb6100_read_reg(state, STB6100_F)) < 0)
+		return rc;
+	f = rc & STB6100_F_F;
+
+	state->status.bandwidth = (f + 5) * 2000;	/* x2 for ZIF	*/
+
+	*bandwidth = state->bandwidth = state->status.bandwidth * 1000;
+	dprintk(verbose, FE_DEBUG, 1, "bandwidth = %u Hz", state->bandwidth);
+	return 0;
+}
+
+static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	u32 tmp;
+	int rc;
+	struct stb6100_state *state = fe->tuner_priv;
+
+	dprintk(verbose, FE_DEBUG, 1, "set bandwidth to %u kHz", bandwidth);
+
+	bandwidth *= 1000 / 2;	/* kHz -> Hz, bw / 2 */
+
+	if (bandwidth > 36000000)	/* F[4:0] BW/2 max =31+5=36 mhz for F=31	*/
+		tmp = 31;
+	if (bandwidth < 5000000)	/* bw/2 min = 5Mhz for F=0			*/
+		tmp = 0;
+	else				/* if 5 < bw/2 < 36				*/
+		tmp = bandwidth / 1000000 - 5;
+
+	/* Turn on LPF bandwidth setting clock control,
+	 * set bandwidth, wait 10ms, turn off.
+	 */
+	if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK)) < 0)
+		return rc;
+	if ((rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp)) < 0)
+		return rc;
+	msleep(1);
+	if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d)) < 0)
+		return rc;
+
+	return 0;
+}
+
+static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	int rc;
+	u32 nint, nfrac, fvco;
+	int psd2, odiv;
+	struct stb6100_state *state = fe->tuner_priv;
+	u8 regs[STB6100_NUMREGS];
+
+	if ((rc = stb6100_read_regs(state, regs)) < 0)
+		return rc;
+
+	odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT;
+	psd2 = (regs[STB6100_K] & STB6100_K_PSD2) >> STB6100_K_PSD2_SHIFT;
+	nint = regs[STB6100_NI];
+	nfrac = ((regs[STB6100_K] & STB6100_K_NF_MSB) << 8) | regs[STB6100_NF_LSB];
+	fvco = (nfrac * state->reference >> (9 - psd2)) + (nint * state->reference << psd2);
+	*frequency = state->frequency = fvco >> (odiv + 1);
+
+	dprintk(verbose, FE_DEBUG, 1,
+		"frequency = %u kHz, odiv = %u, psd2 = %u, fxtal = %u kHz, fvco = %u kHz, N(I) = %u, N(F) = %u",
+		state->frequency, odiv, psd2, state->reference,	fvco, nint, nfrac);
+	return 0;
+}
+
+#if 0
+static int stb6100_set_rfgain(struct dvb_frontend *fe, u32 rfgain)
+{
+
+	return 0;
+}
+#endif
+
+static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	int rc;
+	const struct stb6100_lkup *ptr;
+	struct stb6100_state *state = fe->tuner_priv;
+	struct dvbfe_params params;
+
+	u32 srate = 0, fvco, nint, nfrac;
+	u8 regs[STB6100_NUMREGS];
+	u8 g, psd2, odiv;
+
+	if ((rc = stb6100_read_regs(state, regs)) < 0)
+		return rc;
+	if (fe->ops.get_params) {
+		dprintk(verbose, FE_DEBUG, 1, "Get Frontend parameters");
+		fe->ops.get_params(fe, &params);
+	}
+	switch (params.delivery) {
+	case DVBFE_DELSYS_DVBS:
+		srate = params.delsys.dvbs.symbol_rate;
+		dprintk(verbose, FE_DEBUG, 1, "Delivery system = DVB-S, Symbol Rate=[%d]", srate);
+		break;
+	case DVBFE_DELSYS_DSS:
+		dprintk(verbose, FE_DEBUG, 1, "Delivery system = DSS, Symbol Rate=[%d]", srate);
+		srate = params.delsys.dss.symbol_rate;
+		break;
+	case DVBFE_DELSYS_DVBS2:
+		dprintk(verbose, FE_DEBUG, 1, "Delivery system = DVB-S2, Symbol Rate=[%d]", srate);
+		srate = params.delsys.dvbs2.symbol_rate;
+		break;
+	default:
+		dprintk(verbose, FE_NOTICE, 1, "symbol rate unknown!");
+		srate = 22000000; /* just a typical default value	*/
+	}
+
+	/* Baseband gain.	*/
+	if (srate >= 15000000)
+		g = 8;
+	else if (state->srate >= 5000000)
+		g = 12;
+	else
+		g = 14;
+	regs[STB6100_G] = (regs[STB6100_G] & ~STB6100_G_G) | g;
+
+	/* VCO divide ratio (LO divide ratio, VCO prescaler enable).	*/
+	if (frequency <= 1075000)
+		odiv = 1;
+	else
+		odiv = 0;
+	regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_ODIV) | (odiv << STB6100_VCO_ODIV_SHIFT);
+
+	if ((frequency > 1075000) && (frequency <= 1325000))
+		psd2 = 0;
+	else
+		psd2 = 1;
+	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT);
+
+	/* OSM	*/
+	for (ptr = lkup;
+	     (ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high);
+	     ptr++);
+	if (ptr->val_high == 0) {
+		printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency);
+		return -EINVAL;
+	}
+	regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg;
+
+	/* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4)			*/
+	fvco = frequency << (1 + odiv);
+	/* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1)))	*/
+	nint = fvco / (state->reference << psd2);
+	/* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9	*/
+	nfrac = (((fvco - (nint * state->reference << psd2)) << (9 - psd2)) + state->reference / 2) / state->reference;
+	dprintk(verbose, FE_DEBUG, 1,
+		"frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u",
+		frequency, srate, (unsigned int)g, (unsigned int)odiv,
+		(unsigned int)psd2, state->reference,
+		ptr->reg, fvco, nint, nfrac);
+	regs[STB6100_NI] = nint;
+	regs[STB6100_NF_LSB] = nfrac;
+	regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB);
+	regs[STB6100_VCO] |= STB6100_VCO_OSCH;		/* VCO search enabled		*/
+	regs[STB6100_VCO] |= STB6100_VCO_OCK;		/* VCO search clock off		*/
+	regs[STB6100_FCCK] |= STB6100_FCCK_FCCK;	/* LPF BW setting clock enabled	*/
+	regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN;	/* PLL loop disabled		*/
+	/* Power up. */
+	regs[STB6100_LPEN] |= STB6100_LPEN_SYNP	| STB6100_LPEN_OSCP | STB6100_LPEN_BEN;
+
+	if ((rc = stb6100_write_regs(state, regs)) < 0)
+		return rc;
+
+	regs[STB6100_LPEN] |= STB6100_LPEN_LPEN;	/* PLL loop enabled		*/
+	if ((rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN])) < 0)
+		return rc;
+
+	regs[STB6100_VCO] &= ~STB6100_VCO_OCK;		/* VCO fast search		*/
+	if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
+		return rc;
+
+///XXX
+	{
+		int rc;
+		unsigned long start = jiffies;
+
+		while ((rc = stb6100_read_reg(state, STB6100_LD)) >=0) {
+			if (rc & STB6100_LD_LOCK)
+				break;
+			if (jiffies - start > 100)
+				break;
+			msleep(10);
+		}
+	}
+
+	msleep(5);					/* wait for LO to lock		*/
+	regs[STB6100_VCO] &= ~STB6100_VCO_OSCH;		/* vco search disabled		*/
+	regs[STB6100_VCO] |= STB6100_VCO_OCK;		/* search clock off		*/
+	if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0)
+		return rc;
+	regs[STB6100_FCCK] &= ~STB6100_FCCK_FCCK;       /* LPF BW clock disabled	*/
+	if ((rc = stb6100_write_reg(state, STB6100_FCCK, regs[STB6100_FCCK])) < 0)
+		return rc;
+
+	return 0;
+}
+
+static int stb6100_sleep(struct dvb_frontend *fe)
+{
+	/* TODO: power down	*/
+	return 0;
+}
+
+static int stb6100_init(struct dvb_frontend *fe)
+{
+	struct stb6100_state *state = fe->tuner_priv;
+	struct tuner_state *status = &state->status;
+	
+	printk("%s:\n",__func__);
+
+	status->tunerstep	= 125000;
+	status->ifreq		= 0;
+	status->refclock	= 27000000;	/* Hz	*/
+	status->iqsense		= 1;
+	status->bandwidth	= 36000;	/* kHz	*/
+	state->bandwidth	= status->bandwidth * 1000;	/* MHz	*/
+	state->reference	= status->refclock / 1000;	/* kHz	*/
+
+	/* Set default bandwidth.	*/
+	return stb6100_set_bandwidth(fe, status->bandwidth);
+}
+
+static int stb6100_get_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *state)
+{
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		stb6100_get_frequency(fe, &state->frequency);
+		break;
+	case DVBFE_TUNER_TUNERSTEP:
+		break;
+	case DVBFE_TUNER_IFFREQ:
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		stb6100_get_bandwidth(fe, &state->bandwidth);
+		break;
+	case DVBFE_TUNER_REFCLOCK:
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int stb6100_set_state(struct dvb_frontend *fe,
+			     enum tuner_param param,
+			     struct tuner_state *state)
+{
+	struct stb6100_state *tstate = fe->tuner_priv;
+
+	switch (param) {
+	case DVBFE_TUNER_FREQUENCY:
+		stb6100_set_frequency(fe, state->frequency);
+		state->frequency = tstate->frequency;
+		break;
+	case DVBFE_TUNER_TUNERSTEP:
+		break;
+	case DVBFE_TUNER_IFFREQ:
+		break;
+	case DVBFE_TUNER_BANDWIDTH:
+		stb6100_set_bandwidth(fe, state->bandwidth);
+		state->bandwidth = tstate->bandwidth;
+		break;
+	case DVBFE_TUNER_REFCLOCK:
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static struct dvb_tuner_ops stb6100_ops = {
+	.info = {
+		.name			= "STB6100 Silicon Tuner",
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_step		= 0,
+	},
+
+	.init		= stb6100_init,
+	.sleep          = stb6100_sleep,
+	.get_status	= stb6100_get_status,
+	.get_state	= stb6100_get_state,
+	.set_state	= stb6100_set_state,
+	.get_frequency	= stb6100_get_frequency,
+	.get_bandwidth	= stb6100_get_bandwidth,
+	.release	= stb6100_release
+};
+
+struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+				    struct stb6100_config *config,
+				    struct i2c_adapter *i2c)
+{
+	struct stb6100_state *state = NULL;
+
+	state = kmalloc(sizeof (struct stb6100_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+
+	state->config		= config;
+	state->i2c		= i2c;
+	state->frontend		= fe;
+	state->reference	= config->refclock;
+	fe->tuner_priv		= state;
+	fe->ops.tuner_ops	= stb6100_ops;
+	
+	printk("%s: Attaching STB6100\n", __func__);
+	return fe;
+
+error:
+	kfree(state);
+
+	return NULL;
+}
+
+static int stb6100_release(struct dvb_frontend *fe)
+{
+	struct stb6100_state *state = fe->tuner_priv;
+
+	fe->tuner_priv = NULL;
+	memset(&fe->ops.tuner_ops, 0, sizeof (fe->ops.tuner_ops));
+	kfree(state);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(stb6100_attach);
+MODULE_PARM_DESC(verbose, "Set Verbosity level");
+
+MODULE_AUTHOR("Manu Abraham");
+MODULE_DESCRIPTION("STB6100 Silicon tuner");
+MODULE_LICENSE("GPL");
diff -urNp linux-2.6.22.1/drivers/media/dvb/frontends/stb6100.h linux-2.6.22.1-new/drivers/media/dvb/frontends/stb6100.h
--- linux-2.6.22.1/drivers/media/dvb/frontends/stb6100.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/frontends/stb6100.h	2007-07-28 01:17:12.000000000 +0200
@@ -0,0 +1,101 @@
+/*
+	STB6100 Silicon Tuner
+	Copyright (C) Manu Abraham (abraham.manu@gmail.com)
+
+	Copyright (C) ST Microelectronics
+
+	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 __STB_6100_REG_H
+#define __STB_6100_REG_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+#define STB6100_LD			0x00
+#define STB6100_LD_LOCK			(1 << 0)
+
+#define STB6100_VCO			0x01
+#define STB6100_VCO_OSCH		(0x01 << 7)
+#define STB6100_VCO_OSCH_SHIFT		7
+#define STB6100_VCO_OCK			(0x03 << 5)
+#define STB6100_VCO_OCK_SHIFT		5
+#define STB6100_VCO_ODIV		(0x01 << 4)
+#define STB6100_VCO_ODIV_SHIFT		4
+#define STB6100_VCO_OSM			(0x0f << 0)
+
+#define STB6100_NI			0x02
+#define STB6100_NF_LSB			0x03
+
+#define STB6100_K			0x04
+#define STB6100_K_PSD2			(0x01 << 2)
+#define STB6100_K_PSD2_SHIFT            2
+#define STB6100_K_NF_MSB		(0x03 << 0)
+
+#define STB6100_G			0x05
+#define STB6100_G_G			(0x0f << 0)
+#define STB6100_G_GCT			(0x07 << 5)
+
+#define STB6100_F			0x06
+#define STB6100_F_F			(0x1f << 0)
+
+#define STB6100_DLB			0x07
+
+#define STB6100_TEST1			0x08
+
+#define STB6100_FCCK			0x09
+#define STB6100_FCCK_FCCK		(0x01 << 6)
+
+#define STB6100_LPEN			0x0a
+#define STB6100_LPEN_LPEN		(0x01 << 4)
+#define STB6100_LPEN_SYNP		(0x01 << 5)
+#define STB6100_LPEN_OSCP		(0x01 << 6)
+#define STB6100_LPEN_BEN		(0x01 << 7)
+
+#define STB6100_TEST3			0x0b
+
+#define STB6100_NUMREGS                 0x0c
+
+
+#define INRANGE(val, x, y)		(((x <= val) && (val <= y)) ||		\
+					 ((y <= val) && (val <= x)) ? 1 : 0)
+
+#define CHKRANGE(val, x, y)		(((val >= x) && (val < y)) ? 1 : 0)
+
+struct stb6100_config {
+	u8	tuner_address;
+	u32	refclock;
+};
+
+struct stb6100_state {
+	struct i2c_adapter *i2c;
+
+	const struct stb6100_config	*config;
+	struct dvb_tuner_ops		ops;
+	struct dvb_frontend		*frontend;
+	struct tuner_state		status;
+
+	u32 frequency;
+	u32 srate;
+	u32 bandwidth;
+	u32 reference;
+};
+
+struct dvb_frontend *stb6100_attach(struct dvb_frontend *fe,
+				    struct stb6100_config* config,
+				    struct i2c_adapter *i2c);
+
+#endif
diff -urNp linux-2.6.22.1/drivers/media/dvb/ttpci/budget-av.c linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget-av.c
--- linux-2.6.22.1/drivers/media/dvb/ttpci/budget-av.c	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget-av.c	2007-07-28 01:17:12.000000000 +0200
@@ -35,6 +35,8 @@
 
 #include "budget.h"
 #include "stv0299.h"
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
 #include "tda1002x.h"
 #include "tda1004x.h"
 #include "tua6100.h"
@@ -898,6 +900,585 @@ static struct stv0299_config philips_sd1
 	.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
 };
 
+/* KNC1 DVB-S (STB0899) Inittab	*/
+static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {
+
+//	 0x0000000b ,	/* SYSREG */
+	{ STB0899_DEV_ID		, 0x81 },
+	{ 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		, 0x8c },
+	{ STB0899_DISF22RX		, 0x9a },
+	//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		, 0x30 },
+	{ STB0899_IRQSTATUS_2		, 0x00 },
+	{ STB0899_IRQSTATUS_1		, 0x00 },
+	{ STB0899_IRQSTATUS_0		, 0x00 },
+	{ STB0899_IRQMSK_3		, 0xf3 },
+	{ STB0899_IRQMSK_2		, 0xfc },
+	{ STB0899_IRQMSK_1		, 0xff },
+	{ STB0899_IRQMSK_0		, 0xff },
+	{ STB0899_IRQCFG		, 0x00 },
+	{ STB0899_I2CCFG		, 0x88 },
+	{ STB0899_I2CRPT		, 0x5c },
+	{ STB0899_IOPVALUE5		, 0x00 },
+	{ STB0899_IOPVALUE4		, 0x20 },
+	{ STB0899_IOPVALUE3		, 0xc9 },
+	{ STB0899_IOPVALUE2		, 0x90 },
+	{ STB0899_IOPVALUE1		, 0x40 },
+	{ 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		, 0x15 }, // 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		, 0x00 },
+	{ STB0899_STOPCLK1		, 0x20 },
+	{ STB0899_STOPCLK2		, 0x00 },
+	{ STB0899_INTBUFSTATUS		, 0x00 },
+	{ STB0899_INTBUFCTRL		, 0x0a },
+	{ 0xffff			, 0xff },
+};
+
+static const struct stb0899_s2_reg  knc1_stb0899_s2_init_2[] = {
+
+	{ STB0899_OFF0_DMD_STATUS	, STB0899_BASE_DMD_STATUS	, 0x00000103 },	/* DMDSTATUS	*/
+	{ STB0899_OFF0_CRL_FREQ		, STB0899_BASE_CRL_FREQ		, 0x3ed1da56 },	/* CRLFREQ	*/
+	{ STB0899_OFF0_BTR_FREQ		, STB0899_BASE_BTR_FREQ		, 0x00004000 },	/* BTRFREQ	*/
+	{ STB0899_OFF0_IF_AGC_GAIN	, STB0899_BASE_IF_AGC_GAIN	, 0x00002ade },	/* IFAGCGAIN	*/
+	{ STB0899_OFF0_BB_AGC_GAIN	, STB0899_BASE_BB_AGC_GAIN	, 0x000001bc },	/* BBAGCGAIN	*/
+	{ STB0899_OFF0_DC_OFFSET	, STB0899_BASE_DC_OFFSET	, 0x00000200 },	/* DCOFFSET	*/
+	{ STB0899_OFF0_DMD_CNTRL	, STB0899_BASE_DMD_CNTRL	, 0x0000000f },	/* DMDCNTRL	*/
+
+	{ STB0899_OFF0_IF_AGC_CNTRL	, STB0899_BASE_IF_AGC_CNTRL	, 0x03fb4a20 },	/* IFAGCCNTRL	*/
+	{ STB0899_OFF0_BB_AGC_CNTRL	, STB0899_BASE_BB_AGC_CNTRL	, 0x00200c97 },	/* BBAGCCNTRL	*/
+
+	{ STB0899_OFF0_CRL_CNTRL	, STB0899_BASE_CRL_CNTRL	, 0x00000016 },	/* CRLCNTRL	*/
+	{ STB0899_OFF0_CRL_PHS_INIT	, STB0899_BASE_CRL_PHS_INIT	, 0x00000000 },	/* CRLPHSINIT	*/
+	{ STB0899_OFF0_CRL_FREQ_INIT	, STB0899_BASE_CRL_FREQ_INIT	, 0x00000000 },	/* CRLFREQINIT	*/
+	{ STB0899_OFF0_CRL_LOOP_GAIN	, STB0899_BASE_CRL_LOOP_GAIN	, 0x00000000 },	/* CRLLOOPGAIN	*/
+	{ STB0899_OFF0_CRL_NOM_FREQ	, STB0899_BASE_CRL_NOM_FREQ	, 0x3ed097b6 },	/* CRLNOMFREQ	*/
+	{ STB0899_OFF0_CRL_SWP_RATE	, STB0899_BASE_CRL_SWP_RATE	, 0x00000000 },	/* CRLSWPRATE	*/
+	{ STB0899_OFF0_CRL_MAX_SWP	, STB0899_BASE_CRL_MAX_SWP	, 0x00000000 },	/* CRLMAXSWP	*/
+	{ STB0899_OFF0_CRL_LK_CNTRL	, STB0899_BASE_CRL_LK_CNTRL	, 0x0f6cdc01 },	/* CRLLKCNTRL	*/
+	{ STB0899_OFF0_DECIM_CNTRL	, STB0899_BASE_DECIM_CNTRL	, 0x00000000 },	/* DECIMCNTRL	*/
+	{ STB0899_OFF0_BTR_CNTRL	, STB0899_BASE_BTR_CNTRL	, 0x00003993 },	/* BTRCNTRL	*/
+	{ STB0899_OFF0_BTR_LOOP_GAIN	, STB0899_BASE_BTR_LOOP_GAIN	, 0x000d3c6f },	/* BTRLOOPGAIN	*/
+	{ STB0899_OFF0_BTR_PHS_INIT	, STB0899_BASE_BTR_PHS_INIT	, 0x00000000 },	/* BTRPHSINIT	*/
+	{ STB0899_OFF0_BTR_FREQ_INIT	, STB0899_BASE_BTR_FREQ_INIT	, 0x00000000 },	/* BTRFREQINIT	*/
+	{ STB0899_OFF0_BTR_NOM_FREQ	, STB0899_BASE_BTR_NOM_FREQ	, 0x0238e38e },	/* BTRNOMFREQ	*/
+	{ STB0899_OFF0_BTR_LK_CNTRL	, STB0899_BASE_BTR_LK_CNTRL	, 0x00000000 },	/* BTRLKCNTRL	*/
+	{ STB0899_OFF0_DECN_CNTRL	, STB0899_BASE_DECN_CNTRL	, 0x00000000 },	/* DECNCNTRL	*/
+	{ STB0899_OFF0_TP_CNTRL		, STB0899_BASE_TP_CNTRL		, 0x00000000 },	/* TPCNTRL	*/
+	{ STB0899_OFF0_TP_BUF_STATUS	, STB0899_BASE_TP_BUF_STATUS	, 0x00000000 },	/* TPBUFSTATUS	*/
+	{ STB0899_OFF0_DC_ESTIM		, STB0899_BASE_DC_ESTIM		, 0x00000000 },	/* DCESTIM	*/
+	{ STB0899_OFF0_FLL_CNTRL	, STB0899_BASE_FLL_CNTRL	, 0x00000000 },	/* FLLCNTRL	*/
+	{ STB0899_OFF0_FLL_FREQ_WD	, STB0899_BASE_FLL_FREQ_WD	, 0x40070000 },	/* FLLFREQWD	*/
+	{ STB0899_OFF0_ANTI_ALIAS_SEL	, STB0899_BASE_ANTI_ALIAS_SEL	, 0x00000001 },	/* ANTIALIASSEL */
+	{ STB0899_OFF0_RRC_ALPHA	, STB0899_BASE_RRC_ALPHA	, 0x00000002 },	/* RRCALPHA	*/
+	{ STB0899_OFF0_DC_ADAPT_LSHFT	, STB0899_BASE_DC_ADAPT_LSHFT	, 0x00000000 },	/* DCADAPTISHFT */
+	{ STB0899_OFF0_IMB_OFFSET	, STB0899_BASE_IMB_OFFSET	, 0x0000fe01 },	/* IMBOFFSET	*/
+	{ STB0899_OFF0_IMB_ESTIMATE	, STB0899_BASE_IMB_ESTIMATE	, 0x00000000 },	/* IMBESTIMATE	*/
+	{ STB0899_OFF0_IMB_CNTRL	, STB0899_BASE_IMB_CNTRL	, 0x00000001 },	/* IMBCNTRL	*/
+	{ STB0899_OFF0_IF_AGC_CNTRL2	, STB0899_BASE_IF_AGC_CNTRL2	, 0x00005007 },	/* IFAGCCNTRL2	*/
+	{ STB0899_OFF0_DMD_CNTRL2	, STB0899_BASE_DMD_CNTRL2	, 0x00000002 },	/* DMDCNTRL2	*/
+	{ STB0899_OFF0_TP_BUFFER	, STB0899_BASE_TP_BUFFER	, 0x00000000 },	/* TPBUFFER	*/
+	{ STB0899_OFF0_TP_BUFFER1	, STB0899_BASE_TP_BUFFER1	, 0x00000000 },	/* TPBUFFER1	*/
+	{ STB0899_OFF0_TP_BUFFER2	, STB0899_BASE_TP_BUFFER2	, 0x00000000 },	/* TPBUFFER2	*/
+	{ STB0899_OFF0_TP_BUFFER3	, STB0899_BASE_TP_BUFFER3	, 0x00000000 },	/* TPBUFFER3	*/
+	{ STB0899_OFF0_TP_BUFFER4	, STB0899_BASE_TP_BUFFER4	, 0x00000000 },	/* TPBUFFER4	*/
+	{ STB0899_OFF0_TP_BUFFER5	, STB0899_BASE_TP_BUFFER5	, 0x00000000 },	/* TPBUFFER5	*/
+	{ STB0899_OFF0_TP_BUFFER6	, STB0899_BASE_TP_BUFFER6	, 0x00000000 },	/* TPBUFFER6	*/
+	{ STB0899_OFF0_TP_BUFFER7	, STB0899_BASE_TP_BUFFER7	, 0x00000000 },	/* TPBUFFER7	*/
+	{ STB0899_OFF0_TP_BUFFER8	, STB0899_BASE_TP_BUFFER8	, 0x00000000 },	/* TPBUFFER8	*/
+	{ STB0899_OFF0_TP_BUFFER9	, STB0899_BASE_TP_BUFFER9	, 0x00000000 },	/* TPBUFFER9	*/
+	{ STB0899_OFF0_TP_BUFFER10	, STB0899_BASE_TP_BUFFER10	, 0x00000000 },	/* TPBUFFER10	*/
+	{ STB0899_OFF0_TP_BUFFER11	, STB0899_BASE_TP_BUFFER11	, 0x00000000 },	/* TPBUFFER11	*/
+	{ STB0899_OFF0_TP_BUFFER12	, STB0899_BASE_TP_BUFFER12	, 0x00000000 },	/* TPBUFFER12	*/
+	{ STB0899_OFF0_TP_BUFFER13	, STB0899_BASE_TP_BUFFER13	, 0x00000000 },	/* TPBUFFER13	*/
+	{ STB0899_OFF0_TP_BUFFER14	, STB0899_BASE_TP_BUFFER14	, 0x00000000 },	/* TPBUFFER14	*/
+	{ STB0899_OFF0_TP_BUFFER15	, STB0899_BASE_TP_BUFFER15	, 0x00000000 },	/* TPBUFFER15	*/
+	{ STB0899_OFF0_TP_BUFFER16	, STB0899_BASE_TP_BUFFER16	, 0x0000ff00 },	/* TPBUFFER16	*/
+	{ STB0899_OFF0_TP_BUFFER17	, STB0899_BASE_TP_BUFFER17	, 0x00000100 },	/* TPBUFFER17	*/
+	{ STB0899_OFF0_TP_BUFFER18	, STB0899_BASE_TP_BUFFER18	, 0x0000fe01 },	/* TPBUFFER18	*/
+	{ STB0899_OFF0_TP_BUFFER19	, STB0899_BASE_TP_BUFFER19	, 0x000004fe },	/* TPBUFFER19	*/
+	{ STB0899_OFF0_TP_BUFFER20	, STB0899_BASE_TP_BUFFER20	, 0x0000cfe7 },	/* TPBUFFER20	*/
+	{ STB0899_OFF0_TP_BUFFER21	, STB0899_BASE_TP_BUFFER21	, 0x0000bec6 },	/* TPBUFFER21	*/
+	{ STB0899_OFF0_TP_BUFFER22	, STB0899_BASE_TP_BUFFER22	, 0x0000c2bf },	/* TPBUFFER22	*/
+	{ STB0899_OFF0_TP_BUFFER23	, STB0899_BASE_TP_BUFFER23	, 0x0000c1c1 },	/* TPBUFFER23	*/
+	{ STB0899_OFF0_TP_BUFFER24	, STB0899_BASE_TP_BUFFER24	, 0x0000c1c1 },	/* TPBUFFER24	*/
+	{ STB0899_OFF0_TP_BUFFER25	, STB0899_BASE_TP_BUFFER25	, 0x0000c1c1 },	/* TPBUFFER25	*/
+	{ STB0899_OFF0_TP_BUFFER26	, STB0899_BASE_TP_BUFFER26	, 0x0000c1c1 },	/* TPBUFFER26	*/
+	{ STB0899_OFF0_TP_BUFFER27	, STB0899_BASE_TP_BUFFER27	, 0x0000c1c0 },	/* TPBUFFER27	*/
+	{ STB0899_OFF0_TP_BUFFER28	, STB0899_BASE_TP_BUFFER28	, 0x0000c0c0 },	/* TPBUFFER28	*/
+	{ STB0899_OFF0_TP_BUFFER29	, STB0899_BASE_TP_BUFFER29	, 0x0000c1c1 },	/* TPBUFFER29	*/
+	{ STB0899_OFF0_TP_BUFFER30	, STB0899_BASE_TP_BUFFER30	, 0x0000c1c1 },	/* TPBUFFER30	*/
+	{ STB0899_OFF0_TP_BUFFER31	, STB0899_BASE_TP_BUFFER31	, 0x0000c0c1 },	/* TPBUFFER31	*/
+	{ STB0899_OFF0_TP_BUFFER32	, STB0899_BASE_TP_BUFFER32	, 0x0000c0c1 },	/* TPBUFFER32	*/
+	{ STB0899_OFF0_TP_BUFFER33	, STB0899_BASE_TP_BUFFER33	, 0x0000c1c1 },	/* TPBUFFER33	*/
+	{ STB0899_OFF0_TP_BUFFER34	, STB0899_BASE_TP_BUFFER34	, 0x0000c1c1 },	/* TPBUFFER34	*/
+	{ STB0899_OFF0_TP_BUFFER35	, STB0899_BASE_TP_BUFFER35	, 0x0000c0c1 },	/* TPBUFFER35	*/
+	{ STB0899_OFF0_TP_BUFFER36	, STB0899_BASE_TP_BUFFER36	, 0x0000c1c1 },	/* TPBUFFER36	*/
+	{ STB0899_OFF0_TP_BUFFER37	, STB0899_BASE_TP_BUFFER37	, 0x0000c0c1 },	/* TPBUFFER37	*/
+	{ STB0899_OFF0_TP_BUFFER38	, STB0899_BASE_TP_BUFFER38	, 0x0000c1c1 },	/* TPBUFFER38	*/
+	{ STB0899_OFF0_TP_BUFFER39	, STB0899_BASE_TP_BUFFER39	, 0x0000c0c0 },	/* TPBUFFER39	*/
+	{ STB0899_OFF0_TP_BUFFER40	, STB0899_BASE_TP_BUFFER40	, 0x0000c1c0 },	/* TPBUFFER40	*/
+	{ STB0899_OFF0_TP_BUFFER41	, STB0899_BASE_TP_BUFFER41	, 0x0000c1c1 },	/* TPBUFFER41	*/
+	{ STB0899_OFF0_TP_BUFFER42	, STB0899_BASE_TP_BUFFER42	, 0x0000c0c0 },	/* TPBUFFER42	*/
+	{ STB0899_OFF0_TP_BUFFER43	, STB0899_BASE_TP_BUFFER43	, 0x0000c1c0 },	/* TPBUFFER43	*/
+	{ STB0899_OFF0_TP_BUFFER44	, STB0899_BASE_TP_BUFFER44	, 0x0000c0c1 },	/* TPBUFFER44	*/
+	{ STB0899_OFF0_TP_BUFFER45	, STB0899_BASE_TP_BUFFER45	, 0x0000c1be },	/* TPBUFFER45	*/
+	{ STB0899_OFF0_TP_BUFFER46	, STB0899_BASE_TP_BUFFER46	, 0x0000c1c9 },	/* TPBUFFER46	*/
+	{ STB0899_OFF0_TP_BUFFER47	, STB0899_BASE_TP_BUFFER47	, 0x0000c0da },	/* TPBUFFER47	*/
+	{ STB0899_OFF0_TP_BUFFER48	, STB0899_BASE_TP_BUFFER48	, 0x0000c0ba },	/* TPBUFFER48	*/
+	{ STB0899_OFF0_TP_BUFFER49	, STB0899_BASE_TP_BUFFER49	, 0x0000c1c4 },	/* TPBUFFER49	*/
+	{ STB0899_OFF0_TP_BUFFER50	, STB0899_BASE_TP_BUFFER50	, 0x0000c1bf },	/* TPBUFFER50	*/
+	{ STB0899_OFF0_TP_BUFFER51	, STB0899_BASE_TP_BUFFER51	, 0x0000c0c1 },	/* TPBUFFER51	*/
+	{ STB0899_OFF0_TP_BUFFER52	, STB0899_BASE_TP_BUFFER52	, 0x0000c1c0 },	/* TPBUFFER52	*/
+	{ STB0899_OFF0_TP_BUFFER53	, STB0899_BASE_TP_BUFFER53	, 0x0000c0c1 },	/* TPBUFFER53	*/
+	{ STB0899_OFF0_TP_BUFFER54	, STB0899_BASE_TP_BUFFER54	, 0x0000c1c1 },	/* TPBUFFER54	*/
+	{ STB0899_OFF0_TP_BUFFER55	, STB0899_BASE_TP_BUFFER55	, 0x0000c1c1 },	/* TPBUFFER55	*/
+	{ STB0899_OFF0_TP_BUFFER56	, STB0899_BASE_TP_BUFFER56	, 0x0000c1c1 },	/* TPBUFFER56	*/
+	{ STB0899_OFF0_TP_BUFFER57	, STB0899_BASE_TP_BUFFER57	, 0x0000c1c1 },	/* TPBUFFER57	*/
+	{ STB0899_OFF0_TP_BUFFER58	, STB0899_BASE_TP_BUFFER58	, 0x0000c1c1 },	/* TPBUFFER58	*/
+	{ STB0899_OFF0_TP_BUFFER59	, STB0899_BASE_TP_BUFFER59	, 0x0000c1c1 },	/* TPBUFFER59	*/
+	{ STB0899_OFF0_TP_BUFFER60	, STB0899_BASE_TP_BUFFER60	, 0x0000c1c1 },	/* TPBUFFER60	*/
+	{ STB0899_OFF0_TP_BUFFER61	, STB0899_BASE_TP_BUFFER61	, 0x0000c1c1 },	/* TPBUFFER61	*/
+	{ STB0899_OFF0_TP_BUFFER62	, STB0899_BASE_TP_BUFFER62	, 0x0000c1c1 },	/* TPBUFFER62	*/
+	{ STB0899_OFF0_TP_BUFFER63	, STB0899_BASE_TP_BUFFER63	, 0x0000c1c0 },	/* TPBUFFER63	*/
+	{ STB0899_OFF0_RESET_CNTRL	, STB0899_BASE_RESET_CNTRL	, 0x00000001 },	/* RESETCNTRL	*/
+	{ STB0899_OFF0_ACM_ENABLE	, STB0899_BASE_ACM_ENABLE	, 0x00005654 },	/* ACMENABLE	*/
+	{ STB0899_OFF0_DESCR_CNTRL	, STB0899_BASE_DESCR_CNTRL	, 0x00000000 },	/* DESCRCNTRL	*/
+	{ STB0899_OFF0_CSM_CNTRL1	, STB0899_BASE_CSM_CNTRL1	, 0x00020019 },	/* CSMCNTRL1	*/
+	{ STB0899_OFF0_CSM_CNTRL2	, STB0899_BASE_CSM_CNTRL2	, 0x004b3237 },	/* CSMCNTRL2	*/
+	{ STB0899_OFF0_CSM_CNTRL3	, STB0899_BASE_CSM_CNTRL3	, 0x0003dd17 },	/* CSMCNTRL3	*/
+	{ STB0899_OFF0_CSM_CNTRL4	, STB0899_BASE_CSM_CNTRL4	, 0x00008008 },	/* CSMCNTRL4	*/
+	{ STB0899_OFF0_UWP_CNTRL1	, STB0899_BASE_UWP_CNTRL1	, 0x002a3106 },	/* UWPCNTRL1	*/
+	{ STB0899_OFF0_UWP_CNTRL2	, STB0899_BASE_UWP_CNTRL2	, 0x0006140a },	/* UWPCNTRL2	*/
+	{ STB0899_OFF0_UWP_STAT1	, STB0899_BASE_UWP_STAT1	, 0x00008000 },	/* UWPSTAT1	*/
+	{ STB0899_OFF0_UWP_STAT2	, STB0899_BASE_UWP_STAT2	, 0x00000000 },	/* UWPSTAT2	*/
+	{ STB0899_OFF0_DMD_STAT2	, STB0899_BASE_DMD_STAT2	, 0x00000000 },	/* DMDSTAT2	*/
+	{ STB0899_OFF0_FREQ_ADJ_SCALE	, STB0899_BASE_FREQ_ADJ_SCALE	, 0x00000471 },	/* FREQADJSCALE */
+	{ STB0899_OFF0_UWP_CNTRL3	, STB0899_BASE_UWP_CNTRL3	, 0x017b0465 },	/* UWPCNTRL3	*/
+	{ STB0899_OFF0_SYM_CLK_SEL	, STB0899_BASE_SYM_CLK_SEL	, 0x00000002 },	/* SYMCLKSEL	*/
+	{ STB0899_OFF0_SOF_SRCH_TO	, STB0899_BASE_SOF_SRCH_TO	, 0x00196464 },	/* SOFSRCHTO	*/
+	{ STB0899_OFF0_ACQ_CNTRL1	, STB0899_BASE_ACQ_CNTRL1	, 0x00000603 },	/* ACQCNTRL1	*/
+	{ STB0899_OFF0_ACQ_CNTRL2	, STB0899_BASE_ACQ_CNTRL2	, 0x02046666 },	/* ACQCNTRL2	*/
+	{ STB0899_OFF0_ACQ_CNTRL3	, STB0899_BASE_ACQ_CNTRL3	, 0x10046583 },	/* ACQCNTRL3	*/
+	{ STB0899_OFF0_FE_SETTLE	, STB0899_BASE_FE_SETTLE	, 0x00010404 },	/* FESETTLE	*/
+	{ STB0899_OFF0_AC_DWELL		, STB0899_BASE_AC_DWELL		, 0x0002aa8a },	/* ACDWELL	*/
+	{ STB0899_OFF0_ACQUIRE_TRIG	, STB0899_BASE_ACQUIRE_TRIG	, 0x00000000 },	/* ACQUIRETRIG	*/
+	{ STB0899_OFF0_LOCK_LOST	, STB0899_BASE_LOCK_LOST	, 0x00000001 },	/* LOCKLOST	*/
+	{ STB0899_OFF0_ACQ_STAT1	, STB0899_BASE_ACQ_STAT1	, 0x00000500 },	/* ACQSTAT1	*/
+	{ STB0899_OFF0_ACQ_TIMEOUT	, STB0899_BASE_ACQ_TIMEOUT	, 0x0028a0a0 },	/* ACQTIMEOUT	*/
+	{ STB0899_OFF0_ACQ_TIME		, STB0899_BASE_ACQ_TIME		, 0x00000000 },	/* ACQTIME	*/
+	{ STB0899_OFF0_FINAL_AGC_CNTRL	, STB0899_BASE_FINAL_AGC_CNTRL	, 0x00800c17 },	/* FINALAGCCNTRL*/
+	{ STB0899_OFF0_FINAL_AGC_GAIN	, STB0899_BASE_FINAL_AGC_GAIN	, 0x00000000 },	/* FINALAGCCGAIN*/
+	{ STB0899_OFF0_EQUALIZER_INIT	, STB0899_BASE_EQUALIZER_INIT	, 0x00000000 },	/* EQUILIZERINIT*/
+	{ STB0899_OFF0_EQ_CNTRL		, STB0899_BASE_EQ_CNTRL		, 0x00054802 },	/* EQCNTL	*/
+	{ STB0899_OFF0_EQ_I_INIT_COEFF_0, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF0 */
+	{ STB0899_OFF1_EQ_I_INIT_COEFF_1, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF1 */
+	{ STB0899_OFF2_EQ_I_INIT_COEFF_2, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF2 */
+	{ STB0899_OFF3_EQ_I_INIT_COEFF_3, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF3 */
+	{ STB0899_OFF4_EQ_I_INIT_COEFF_4, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF4 */
+	{ STB0899_OFF5_EQ_I_INIT_COEFF_5, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000400 },	/* EQIINITCOEFF5 */
+	{ STB0899_OFF6_EQ_I_INIT_COEFF_6, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF6 */
+	{ STB0899_OFF7_EQ_I_INIT_COEFF_7, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF7 */
+	{ STB0899_OFF8_EQ_I_INIT_COEFF_8, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF8 */
+	{ STB0899_OFF9_EQ_I_INIT_COEFF_9, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF9 */
+	{ STB0899_OFFa_EQ_I_INIT_COEFF_10,STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF10*/
+	{ STB0899_OFF0_EQ_Q_INIT_COEFF_0, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF0 */
+	{ STB0899_OFF1_EQ_Q_INIT_COEFF_1, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF1 */
+	{ STB0899_OFF2_EQ_Q_INIT_COEFF_2, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF2 */
+	{ STB0899_OFF3_EQ_Q_INIT_COEFF_3, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF3 */
+	{ STB0899_OFF4_EQ_Q_INIT_COEFF_4, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF4 */
+	{ STB0899_OFF5_EQ_Q_INIT_COEFF_5, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF5 */
+	{ STB0899_OFF6_EQ_Q_INIT_COEFF_6, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF6 */
+	{ STB0899_OFF7_EQ_Q_INIT_COEFF_7, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF7 */
+	{ STB0899_OFF8_EQ_Q_INIT_COEFF_8, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF8 */
+	{ STB0899_OFF9_EQ_Q_INIT_COEFF_9, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF9 */
+	{ STB0899_OFFa_EQ_Q_INIT_COEFF_10,STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF10*/
+	{ STB0899_OFF0_EQ_I_OUT_COEFF_0	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT0 */
+	{ STB0899_OFF1_EQ_I_OUT_COEFF_1	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT1 */
+	{ STB0899_OFF2_EQ_I_OUT_COEFF_2	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT2 */
+	{ STB0899_OFF3_EQ_I_OUT_COEFF_3	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT3 */
+	{ STB0899_OFF4_EQ_I_OUT_COEFF_4	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT4 */
+	{ STB0899_OFF5_EQ_I_OUT_COEFF_5	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT5 */
+	{ STB0899_OFF6_EQ_I_OUT_COEFF_6	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT6 */
+	{ STB0899_OFF7_EQ_I_OUT_COEFF_7	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT7 */
+	{ STB0899_OFF8_EQ_I_OUT_COEFF_8	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT8 */
+	{ STB0899_OFF9_EQ_I_OUT_COEFF_9	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT9 */
+	{ STB0899_OFFa_EQ_I_OUT_COEFF_10,STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT10*/
+	{ STB0899_OFF0_EQ_Q_OUT_COEFF_0	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT0 */
+	{ STB0899_OFF1_EQ_Q_OUT_COEFF_1	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT1 */
+	{ STB0899_OFF2_EQ_Q_OUT_COEFF_2	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT2 */
+	{ STB0899_OFF3_EQ_Q_OUT_COEFF_3	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT3 */
+	{ STB0899_OFF4_EQ_Q_OUT_COEFF_4	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT4 */
+	{ STB0899_OFF5_EQ_Q_OUT_COEFF_5	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT5 */
+	{ STB0899_OFF6_EQ_Q_OUT_COEFF_6 , STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT6 */
+	{ STB0899_OFF7_EQ_Q_OUT_COEFF_7	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT7 */
+	{ STB0899_OFF8_EQ_Q_OUT_COEFF_8	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT8 */
+	{ STB0899_OFF9_EQ_Q_OUT_COEFF_9	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT9 */
+	{ STB0899_OFFa_EQ_Q_OUT_COEFF_10, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT10*/
+	{ 0xffff			, 0xffffffff			, 0xffffffff },
+};
+
+static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = {
+	{ STB0899_DEMOD			, 0x00 },
+	{ STB0899_RCOMPC		, 0xc9 },
+	{ STB0899_AGC1CN		, 0x41 },
+	{ STB0899_AGC1REF		, 0x10 },
+	{ STB0899_RTC			, 0x7a },
+	{ STB0899_TMGCFG		, 0x4e },
+	{ STB0899_AGC2REF		, 0x34 },
+	{ STB0899_TLSR			, 0x84 },
+	{ STB0899_CFD			, 0xc7 },
+	{ STB0899_ACLC			, 0x87 },
+	{ STB0899_BCLC			, 0x94 },
+	{ STB0899_EQON			, 0x41 },
+	{ STB0899_LDT			, 0xdd },
+	{ STB0899_LDT2			, 0xc9 },
+	{ STB0899_EQUALREF		, 0xb4 },
+	{ STB0899_TMGRAMP		, 0x10 },
+	{ STB0899_TMGTHD		, 0x30 },
+	{ STB0899_IDCCOMP		, 0xfb },
+	{ STB0899_QDCCOMP		, 0x03 },
+	{ STB0899_POWERI		, 0x3b },
+	{ STB0899_POWERQ		, 0x3d },
+	{ STB0899_RCOMP			, 0x81 },
+	{ STB0899_AGCIQIN		, 0x80 },
+	{ STB0899_AGC2I1		, 0x04 },
+	{ STB0899_AGC2I2		, 0xf5 },
+	{ STB0899_TLIR			, 0x25 },
+	{ STB0899_RTF			, 0x80 },
+	{ STB0899_DSTATUS		, 0x00 },
+	{ STB0899_LDI			, 0xca },
+	{ STB0899_CFRM			, 0xf1 },
+	{ STB0899_CFRL			, 0xf3 },
+	{ STB0899_NIRM			, 0x2a },
+	{ STB0899_NIRL			, 0x05 },
+	{ STB0899_ISYMB			, 0x17 },
+	{ STB0899_QSYMB			, 0xfa },
+	{ STB0899_SFRH			, 0x2f },
+	{ STB0899_SFRM			, 0x68 },
+	{ STB0899_SFRL			, 0x40 },
+	{ STB0899_SFRUPH		, 0x2f },
+	{ STB0899_SFRUPM		, 0x68 },
+	{ STB0899_SFRUPL		, 0x40 },
+	{ STB0899_EQUAI1		, 0xfd },
+	{ STB0899_EQUAQ1		, 0x04 },
+	{ STB0899_EQUAI2		, 0x0f },
+	{ STB0899_EQUAQ2		, 0xff },
+	{ STB0899_EQUAI3		, 0xdf },
+	{ STB0899_EQUAQ3		, 0xfa },
+	{ STB0899_EQUAI4		, 0x37 },
+	{ STB0899_EQUAQ4		, 0x0d },
+	{ STB0899_EQUAI5		, 0xbd },
+	{ STB0899_EQUAQ5		, 0xf7 },
+	{ STB0899_DSTATUS2		, 0x00 },
+	{ STB0899_VSTATUS		, 0x00 },
+	{ STB0899_VERROR		, 0xff },
+	{ STB0899_IQSWAP		, 0x2a },
+	{ STB0899_ECNT1M		, 0x00 },
+	{ STB0899_ECNT1L		, 0x00 },
+	{ STB0899_ECNT2M		, 0x00 },
+	{ STB0899_ECNT2L		, 0x00 },
+	{ STB0899_ECNT3M		, 0x00 },
+	{ STB0899_ECNT3L		, 0x00 },
+	{ STB0899_FECAUTO1		, 0x06 },
+	{ STB0899_FECM			, 0x01 },
+	{ STB0899_VTH12			, 0xf0 },
+	{ STB0899_VTH23			, 0xa0 },
+	{ STB0899_VTH34			, 0x78 },
+	{ STB0899_VTH56			, 0x4e },
+	{ STB0899_VTH67			, 0x48 },
+	{ STB0899_VTH78			, 0x38 },
+	{ STB0899_PRVIT			, 0xff },
+	{ STB0899_VITSYNC		, 0x19 },
+	{ STB0899_RSULC			, 0xb1 }, // DVB = 0xb1, DSS = 0xa1
+	{ STB0899_TSULC			, 0x42 },
+	{ STB0899_RSLLC			, 0x40 },
+	{ STB0899_TSLPL			, 0x12 },
+	{ STB0899_TSCFGH		, 0x0c },
+	{ STB0899_TSCFGM		, 0x00 },
+	{ STB0899_TSCFGL		, 0x0c },
+	{ STB0899_TSOUT			, 0x07 },
+	{ STB0899_RSSYNCDEL		, 0x00 },
+	{ STB0899_TSINHDELH		, 0x02 },
+	{ STB0899_TSINHDELM		, 0x00 },
+	{ STB0899_TSINHDELL		, 0x00 },
+	{ STB0899_TSLLSTKM		, 0x00 },
+	{ STB0899_TSLLSTKL		, 0x00 },
+	{ STB0899_TSULSTKM		, 0x00 },
+	{ STB0899_TSULSTKL		, 0xab },
+	{ STB0899_PCKLENUL		, 0x00 },
+	{ STB0899_PCKLENLL		, 0xcc },
+	{ STB0899_RSPCKLEN		, 0xcc },
+	{ STB0899_TSSTATUS		, 0x80 },
+	{ STB0899_ERRCTRL1		, 0xb6 },
+	{ STB0899_ERRCTRL2		, 0x96 },
+	{ STB0899_ERRCTRL3		, 0x89 },
+	{ STB0899_DMONMSK1		, 0x27 },
+	{ STB0899_DMONMSK0		, 0x03 },
+	{ STB0899_DEMAPVIT		, 0x5c },
+	{ STB0899_PLPARM		, 0x1f },
+	{ 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		, 0x00 },
+	{ STB0899_MATSTRL		, 0x00 },
+	{ STB0899_UPLSTRM		, 0x00 },
+	{ STB0899_UPLSTRL		, 0x00 },
+	{ STB0899_DFLSTRM		, 0x00 },
+	{ STB0899_DFLSTRL		, 0x00 },
+	{ STB0899_SYNCSTR		, 0x00 },
+	{ STB0899_SYNCDSTRM		, 0x00 },
+	{ STB0899_SYNCDSTRL		, 0x00 },
+	{ STB0899_CFGPDELSTATUS1	, 0x10 },
+	{ STB0899_CFGPDELSTATUS2	, 0x00 },
+	{ STB0899_BBFERRORM		, 0x00 },
+	{ STB0899_BBFERRORL		, 0x00 },
+	{ STB0899_UPKTERRORM		, 0x00 },
+	{ STB0899_UPKTERRORL		, 0x00 },
+	{ 0xffff			, 0xff },
+};
+
+static const struct stb0899_s2_reg knc1_stb0899_s2_init_4[] = {
+	{ STB0899_OFF0_BLOCK_LNGTH	, STB0899_BASE_BLOCK_LNGTH	, 0x00000008 },	/* BLOCKLNGTH	*/
+	{ STB0899_OFF0_ROW_STR		, STB0899_BASE_ROW_STR		, 0x000000b4 },	/* ROWSTR	*/
+	{ STB0899_OFF0_BN_END_ADDR	, STB0899_BASE_BN_END_ADDR	, 0x000004b5 },	/* BNANDADDR	*/
+	{ STB0899_OFF0_CN_END_ADDR	, STB0899_BASE_CN_END_ADDR	, 0x00000b4b },	/* CNANDADDR	*/
+	{ STB0899_OFF0_INFO_LENGTH	, STB0899_BASE_INFO_LENGTH	, 0x00000078 },	/* INFOLENGTH	*/
+	{ STB0899_OFF0_BOT_ADDR		, STB0899_BASE_BOT_ADDR		, 0x000001e0 },	/* BOT_ADDR	*/
+	{ STB0899_OFF0_BCH_BLK_LN	, STB0899_BASE_BCH_BLK_LN	, 0x0000a8c0 },	/* BCHBLKLN	*/
+	{ STB0899_OFF0_BCH_T		, STB0899_BASE_BCH_T		, 0x0000000c },	/* BCHT		*/
+	{ STB0899_OFF0_CNFG_MODE	, STB0899_BASE_CNFG_MODE	, 0x00000001 },	/* CNFGMODE	*/
+	{ STB0899_OFF0_LDPC_STAT	, STB0899_BASE_LDPC_STAT	, 0x0000000d },	/* LDPCSTAT	*/
+	{ STB0899_OFF0_ITER_SCALE	, STB0899_BASE_ITER_SCALE	, 0x00000040 },	/* ITERSCALE	*/
+	{ STB0899_OFF0_INPUT_MODE	, STB0899_BASE_INPUT_MODE	, 0x00000000 },	/* INPUTMODE	*/
+	{ STB0899_OFF0_LDPCDECRST	, STB0899_BASE_LDPCDECRST	, 0x00000000 },	/* LDPCDECRST	*/
+	{ STB0899_OFF0_CLK_PER_BYTE_RW	, STB0899_BASE_CLK_PER_BYTE_RW	, 0x00000008 },	/* CLKPERBYTE	*/
+	{ STB0899_OFF0_BCH_ERRORS	, STB0899_BASE_BCH_ERRORS	, 0x00000000 },	/* BCHERRORS	*/
+	{ STB0899_OFF0_LDPC_ERRORS	, STB0899_BASE_LDPC_ERRORS	, 0x00000000 },	/* LDPCERRORS	*/
+	{ STB0899_OFF0_BCH_MODE		, STB0899_BASE_BCH_MODE		, 0x00000000 },	/* BCHMODE	*/
+	{ STB0899_OFF0_ERR_ACC_PER	, STB0899_BASE_ERR_ACC_PER	, 0x00000008 },	/* ERRACCPER	*/
+	{ STB0899_OFF0_BCH_ERR_ACC	, STB0899_BASE_BCH_ERR_ACC	, 0x00000000 },	/* BCHERRACC	*/
+	{ STB0899_OFF0_FEC_TP_SEL	, STB0899_BASE_FEC_TP_SEL	, 0x00000000 },	/* FECTPSEL	*/
+	{ 0xffff			, 0xffffffff			, 0xffffffff },
+};
+
+static const struct stb0899_s1_reg knc1_stb0899_s1_init_5[] = {
+	{ STB0899_TSTCK		, 0x00 },
+	{ STB0899_TSTRES	, 0x00 },
+	{ STB0899_TSTOUT	, 0x00 },
+	{ STB0899_TSTIN		, 0x00 },
+	{ STB0899_TSTSYS	, 0x00 },
+	{ STB0899_TSTCHIP	, 0x00 },
+	{ STB0899_TSTFREE	, 0x00 },
+	{ STB0899_TSTI2C	, 0x00 },
+	{ STB0899_BITSPEEDM	, 0x00 },
+	{ STB0899_BITSPEEDL	, 0x00 },
+	{ STB0899_TBUSBIT	, 0x00 },
+	{ STB0899_TSTDIS	, 0x00 },
+	{ STB0899_TSTDISRX	, 0x00 },
+	{ STB0899_TSTJETON	, 0x00 },
+	{ STB0899_TSTDCADJ	, 0x00 },
+	{ STB0899_TSTAGC1	, 0x00 },
+	{ STB0899_TSTAGC1N	, 0x00 },
+	{ STB0899_TSTPOLYPH	, 0x00 },
+	{ STB0899_TSTR		, 0x00 },
+	{ STB0899_TSTAGC2	, 0x00 },
+	{ STB0899_TSTCTL1	, 0x00 },
+	{ STB0899_TSTCTL2	, 0x00 },
+	{ STB0899_TSTCTL3	, 0x00 },
+	{ STB0899_TSTDEMAP	, 0x00 },
+	{ STB0899_TSTDEMAP2	, 0x00 },
+	{ STB0899_TSTDEMMON	, 0x00 },
+	{ STB0899_TSTRATE	, 0x00 },
+	{ STB0899_TSTSELOUT	, 0x00 },
+	{ STB0899_TSYNC		, 0x00 },
+	{ STB0899_TSTERR	, 0x00 },
+	{ STB0899_TSTRAM1	, 0x00 },
+	{ STB0899_TSTVSELOUT	, 0x00 },
+	{ STB0899_TSTFORCEIN	, 0x00 },
+	{ STB0899_TSTRS1	, 0x00 },
+	{ STB0899_TSTRS2	, 0x00 },
+	{ STB0899_TSTRS3	, 0x00 },
+	{ STB0899_GHOSTREG	, 0x81 },
+	{ 0xffff		, 0xff },
+};
+
+static int knc1_dvbs2_sd1878_pll_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct dvb_frontend_parameters pll_params;
+
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		msleep_interruptible(2);
+		pll_params.frequency = frequency;
+		fe->ops.tuner_ops.set_params(fe, &pll_params);
+		/* FIXME !
+		 * This is just a hack because dvb-pll is too rigid
+		 * will need to adjust dvb-pll to avoid unpleasant
+		 * issues like this !
+		 */
+		msleep(200);
+	}
+
+	return 0;
+}
+
+static int knc1_dvbs2_sd1878_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	/* FIXME ! need to calculate the bandwidth	*/
+	*bandwidth = 60000000;
+
+	return 0;
+}
+
+
+#define KNC1_DVBS2_ESNO_AVE			3
+#define KNC1_DVBS2_ESNO_QUANT			32
+#define KNC1_DVBS2_AVFRAMES_COARSE		10
+#define KNC1_DVBS2_AVFRAMES_FINE		20
+#define KNC1_DVBS2_MISS_THRESHOLD		6
+#define KNC1_DVBS2_UWP_THRESHOLD_ACQ		1125
+#define KNC1_DVBS2_UWP_THRESHOLD_TRACK		758
+#define KNC1_DVBS2_UWP_THRESHOLD_SOF		1350
+#define KNC1_DVBS2_SOF_SEARCH_TIMEOUT		1664100
+
+#define KNC1_DVBS2_BTR_NCO_BITS			28
+#define KNC1_DVBS2_BTR_GAIN_SHIFT_OFFSET	15
+#define KNC1_DVBS2_CRL_NCO_BITS			30
+#define KNC1_DVBS2_LDPC_MAX_ITER		70
+
+static struct stb0899_config knc1_dvbs2_config = {
+	.init_dev		= knc1_stb0899_s1_init_1,
+	.init_s2_demod		= knc1_stb0899_s2_init_2,
+	.init_s1_demod		= knc1_stb0899_s1_init_3,
+	.init_s2_fec		= knc1_stb0899_s2_init_4,
+	.init_tst		= knc1_stb0899_s1_init_5,
+
+	.demod_address		= 0x68,
+//	.ts_output_mode		= STB0899_OUT_PARALLEL,	/* types = SERIAL/PARALLEL	*/
+	.block_sync_mode	= STB0899_SYNC_FORCED,	/* DSS, SYNC_FORCED/UNSYNCED	*/
+//	.ts_pfbit_toggle	= STB0899_MPEG_NORMAL,	/* DirecTV, MPEG toggling seq	*/
+
+	.xtal_freq		= 27000000,
+	.inversion		= 1,
+
+	.esno_ave		= KNC1_DVBS2_ESNO_AVE,
+	.esno_quant		= KNC1_DVBS2_ESNO_QUANT,
+	.avframes_coarse	= KNC1_DVBS2_AVFRAMES_COARSE,
+	.avframes_fine		= KNC1_DVBS2_AVFRAMES_FINE,
+	.miss_threshold		= KNC1_DVBS2_MISS_THRESHOLD,
+	.uwp_threshold_acq	= KNC1_DVBS2_UWP_THRESHOLD_ACQ,
+	.uwp_threshold_track	= KNC1_DVBS2_UWP_THRESHOLD_TRACK,
+	.uwp_threshold_sof	= KNC1_DVBS2_UWP_THRESHOLD_SOF,
+	.sof_search_timeout	= KNC1_DVBS2_SOF_SEARCH_TIMEOUT,
+
+	.btr_nco_bits		= KNC1_DVBS2_BTR_NCO_BITS,
+	.btr_gain_shift_offset	= KNC1_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+	.crl_nco_bits		= KNC1_DVBS2_CRL_NCO_BITS,
+	.ldpc_max_iter		= KNC1_DVBS2_LDPC_MAX_ITER,
+
+	.tuner_get_frequency	= NULL,
+	.tuner_set_frequency	= knc1_dvbs2_sd1878_pll_set_frequency,
+	.tuner_set_bandwidth	= NULL,
+	.tuner_get_bandwidth	= knc1_dvbs2_sd1878_pll_get_bandwidth,
+};
+
+static int sd1878_tuner_stb0899_set_params(struct dvb_frontend *fe,
+					   struct dvb_frontend_parameters *p)
+{
+	u8 buf[4];
+	int rc;
+	struct i2c_msg tuner_msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof (buf)};
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+
+	printk("%s: tuner_set_params, frequency=%d\n", __func__, p->frequency);
+	if ((p->frequency < 950000) || (p->frequency > 2150000))
+		return -EINVAL;
+
+	rc = dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf, p->frequency, 0);
+	if (rc < 0)
+		return rc;
+
+	rc = i2c_transfer(&budget->i2c_adap, &tuner_msg, 1);
+	if (rc != 1) {
+		printk("%s: I2C Transfer returned [%d]\n", __func__, rc);
+		return -EIO;
+	}
+	msleep(1);
+	printk("%s: Send params to tuner ok!!!\n", __func__);
+
+	return 0;
+}
+
 static u8 read_pwm(struct budget_av *budget_av)
 {
 	u8 b = 0xff;
@@ -920,6 +1501,7 @@ static u8 read_pwm(struct budget_av *bud
 #define SUBID_DVBS_CYNERGY1200N 	0x1155
 #define SUBID_DVBS_TV_STAR		0x0014
 #define SUBID_DVBS_TV_STAR_CI		0x0016
+#define SUBID_DVBS2_KNC1		0x0018
 #define SUBID_DVBS_EASYWATCH_1  	0x001a
 #define SUBID_DVBS_EASYWATCH		0x001e
 
@@ -953,6 +1535,7 @@ static void frontend_init(struct budget_
 		case SUBID_DVBC_KNC1_PLUS:
 		case SUBID_DVBT_KNC1_PLUS:
 		case SUBID_DVBC_EASYWATCH:
+		case SUBID_DVBS2_KNC1:
 		case SUBID_DVBC_KNC1_PLUS_MK3:
 			saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
 			break;
@@ -1005,6 +1588,15 @@ static void frontend_init(struct budget_
 		}
 		break;
 
+	case SUBID_DVBS2_KNC1:
+		fe = stb0899_attach(&knc1_dvbs2_config,
+				    &budget_av->budget.i2c_adap);
+		if (fe) {
+			dvb_pll_attach(fe, 0x60, &budget_av->budget.i2c_adap, &dvb_pll_philips_sd1878_tda8261);
+			fe->ops.tuner_ops.set_params = sd1878_tuner_stb0899_set_params;
+		}
+		break;
+
 	case SUBID_DVBC_KNC1:
 	case SUBID_DVBC_KNC1_PLUS:
 	case SUBID_DVBC_CINERGY1200:
@@ -1259,6 +1851,7 @@ static struct saa7146_ext_vv vv_data = {
 static struct saa7146_extension budget_extension;
 
 MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
+MAKE_BUDGET_INFO(knc1s2,"KNC1 DVB-S2", BUDGET_KNC1S2);
 MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
 MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
 MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
@@ -1285,6 +1878,7 @@ static struct pci_device_id pci_tbl[] = 
 	MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
 	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
 	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
+	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018),
 	MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
 	MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
 	MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
diff -urNp linux-2.6.22.1/drivers/media/dvb/ttpci/budget-av.c.orig linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget-av.c.orig
--- linux-2.6.22.1/drivers/media/dvb/ttpci/budget-av.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget-av.c.orig	2007-07-10 20:56:30.000000000 +0200
@@ -0,0 +1,1340 @@
+/*
+ * budget-av.c: driver for the SAA7146 based Budget DVB cards
+ *              with analog video in
+ *
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ *
+ * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &
+ *                               Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>
+ *
+ * Copyright (C) 1999-2002 Ralph  Metzler
+ *                       & Marcus Metzler for convergence integrated media GmbH
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org/dvb/
+ */
+
+#include "budget.h"
+#include "stv0299.h"
+#include "tda1002x.h"
+#include "tda1004x.h"
+#include "tua6100.h"
+#include "dvb-pll.h"
+#include <media/saa7146_vv.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/spinlock.h>
+
+#include "dvb_ca_en50221.h"
+
+#define DEBICICAM		0x02420000
+
+#define SLOTSTATUS_NONE         1
+#define SLOTSTATUS_PRESENT      2
+#define SLOTSTATUS_RESET        4
+#define SLOTSTATUS_READY        8
+#define SLOTSTATUS_OCCUPIED     (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
+
+struct budget_av {
+	struct budget budget;
+	struct video_device *vd;
+	int cur_input;
+	int has_saa7113;
+	struct tasklet_struct ciintf_irq_tasklet;
+	int slot_status;
+	struct dvb_ca_en50221 ca;
+	u8 reinitialise_demod:1;
+};
+
+static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
+
+
+/* GPIO Connections:
+ * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
+ * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
+ * 2 - CI Card Enable (Active Low)
+ * 3 - CI Card Detect
+ */
+
+/****************************************************************************
+ * INITIALIZATION
+ ****************************************************************************/
+
+static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)
+{
+	u8 mm1[] = { 0x00 };
+	u8 mm2[] = { 0x00 };
+	struct i2c_msg msgs[2];
+
+	msgs[0].flags = 0;
+	msgs[1].flags = I2C_M_RD;
+	msgs[0].addr = msgs[1].addr = id / 2;
+	mm1[0] = reg;
+	msgs[0].len = 1;
+	msgs[1].len = 1;
+	msgs[0].buf = mm1;
+	msgs[1].buf = mm2;
+
+	i2c_transfer(i2c, msgs, 2);
+
+	return mm2[0];
+}
+
+static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 * buf, u8 len)
+{
+	u8 mm1[] = { reg };
+	struct i2c_msg msgs[2] = {
+		{.addr = id / 2,.flags = 0,.buf = mm1,.len = 1},
+		{.addr = id / 2,.flags = I2C_M_RD,.buf = buf,.len = len}
+	};
+
+	if (i2c_transfer(i2c, msgs, 2) != 2)
+		return -EIO;
+
+	return 0;
+}
+
+static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)
+{
+	u8 msg[2] = { reg, val };
+	struct i2c_msg msgs;
+
+	msgs.flags = 0;
+	msgs.addr = id / 2;
+	msgs.len = 2;
+	msgs.buf = msg;
+	return i2c_transfer(i2c, &msgs, 1);
+}
+
+static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
+{
+	struct budget_av *budget_av = (struct budget_av *) ca->data;
+	int result;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
+	udelay(1);
+
+	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
+	if (result == -ETIMEDOUT) {
+		ciintf_slot_shutdown(ca, slot);
+		printk(KERN_INFO "budget-av: cam ejected 1\n");
+	}
+	return result;
+}
+
+static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
+{
+	struct budget_av *budget_av = (struct budget_av *) ca->data;
+	int result;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);
+	udelay(1);
+
+	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
+	if (result == -ETIMEDOUT) {
+		ciintf_slot_shutdown(ca, slot);
+		printk(KERN_INFO "budget-av: cam ejected 2\n");
+	}
+	return result;
+}
+
+static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
+{
+	struct budget_av *budget_av = (struct budget_av *) ca->data;
+	int result;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+	udelay(1);
+
+	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
+	if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
+		ciintf_slot_shutdown(ca, slot);
+		printk(KERN_INFO "budget-av: cam ejected 3\n");
+		return -ETIMEDOUT;
+	}
+	return result;
+}
+
+static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
+{
+	struct budget_av *budget_av = (struct budget_av *) ca->data;
+	int result;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+	udelay(1);
+
+	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
+	if (result == -ETIMEDOUT) {
+		ciintf_slot_shutdown(ca, slot);
+		printk(KERN_INFO "budget-av: cam ejected 5\n");
+	}
+	return result;
+}
+
+static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct budget_av *budget_av = (struct budget_av *) ca->data;
+	struct saa7146_dev *saa = budget_av->budget.dev;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	dprintk(1, "ciintf_slot_reset\n");
+	budget_av->slot_status = SLOTSTATUS_RESET;
+
+	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
+
+	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
+	msleep(2);
+	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
+	msleep(20); /* 20 ms Vcc settling time */
+
+	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
+	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+	msleep(20);
+
+	/* reinitialise the frontend if necessary */
+	if (budget_av->reinitialise_demod)
+		dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
+
+	return 0;
+}
+
+static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct budget_av *budget_av = (struct budget_av *) ca->data;
+	struct saa7146_dev *saa = budget_av->budget.dev;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	dprintk(1, "ciintf_slot_shutdown\n");
+
+	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+	budget_av->slot_status = SLOTSTATUS_NONE;
+
+	return 0;
+}
+
+static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct budget_av *budget_av = (struct budget_av *) ca->data;
+	struct saa7146_dev *saa = budget_av->budget.dev;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
+
+	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
+
+	return 0;
+}
+
+static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+	struct budget_av *budget_av = (struct budget_av *) ca->data;
+	struct saa7146_dev *saa = budget_av->budget.dev;
+	int result;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	/* test the card detect line - needs to be done carefully
+	 * since it never goes high for some CAMs on this interface (e.g. topuptv) */
+	if (budget_av->slot_status == SLOTSTATUS_NONE) {
+		saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
+		udelay(1);
+		if (saa7146_read(saa, PSR) & MASK_06) {
+			if (budget_av->slot_status == SLOTSTATUS_NONE) {
+				budget_av->slot_status = SLOTSTATUS_PRESENT;
+				printk(KERN_INFO "budget-av: cam inserted A\n");
+			}
+		}
+		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+	}
+
+	/* We also try and read from IO memory to work round the above detection bug. If
+	 * there is no CAM, we will get a timeout. Only done if there is no cam
+	 * present, since this test actually breaks some cams :(
+	 *
+	 * if the CI interface is not open, we also do the above test since we
+	 * don't care if the cam has problems - we'll be resetting it on open() anyway */
+	if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
+		saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
+		result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
+		if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
+			budget_av->slot_status = SLOTSTATUS_PRESENT;
+			printk(KERN_INFO "budget-av: cam inserted B\n");
+		} else if (result < 0) {
+			if (budget_av->slot_status != SLOTSTATUS_NONE) {
+				ciintf_slot_shutdown(ca, slot);
+				printk(KERN_INFO "budget-av: cam ejected 5\n");
+				return 0;
+			}
+		}
+	}
+
+	/* read from attribute memory in reset/ready state to know when the CAM is ready */
+	if (budget_av->slot_status == SLOTSTATUS_RESET) {
+		result = ciintf_read_attribute_mem(ca, slot, 0);
+		if (result == 0x1d) {
+			budget_av->slot_status = SLOTSTATUS_READY;
+		}
+	}
+
+	/* work out correct return code */
+	if (budget_av->slot_status != SLOTSTATUS_NONE) {
+		if (budget_av->slot_status & SLOTSTATUS_READY) {
+			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+		}
+		return DVB_CA_EN50221_POLL_CAM_PRESENT;
+	}
+	return 0;
+}
+
+static int ciintf_init(struct budget_av *budget_av)
+{
+	struct saa7146_dev *saa = budget_av->budget.dev;
+	int result;
+
+	memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
+
+	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
+	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
+	saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+
+	/* Enable DEBI pins */
+	saa7146_write(saa, MC1, MASK_27 | MASK_11);
+
+	/* register CI interface */
+	budget_av->ca.owner = THIS_MODULE;
+	budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;
+	budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;
+	budget_av->ca.read_cam_control = ciintf_read_cam_control;
+	budget_av->ca.write_cam_control = ciintf_write_cam_control;
+	budget_av->ca.slot_reset = ciintf_slot_reset;
+	budget_av->ca.slot_shutdown = ciintf_slot_shutdown;
+	budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
+	budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
+	budget_av->ca.data = budget_av;
+	budget_av->budget.ci_present = 1;
+	budget_av->slot_status = SLOTSTATUS_NONE;
+
+	if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
+					  &budget_av->ca, 0, 1)) != 0) {
+		printk(KERN_ERR "budget-av: ci initialisation failed.\n");
+		goto error;
+	}
+
+	printk(KERN_INFO "budget-av: ci interface initialised.\n");
+	return 0;
+
+error:
+	saa7146_write(saa, MC1, MASK_27);
+	return result;
+}
+
+static void ciintf_deinit(struct budget_av *budget_av)
+{
+	struct saa7146_dev *saa = budget_av->budget.dev;
+
+	saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
+	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
+	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
+
+	/* release the CA device */
+	dvb_ca_en50221_release(&budget_av->ca);
+
+	/* disable DEBI pins */
+	saa7146_write(saa, MC1, MASK_27);
+}
+
+
+static const u8 saa7113_tab[] = {
+	0x01, 0x08,
+	0x02, 0xc0,
+	0x03, 0x33,
+	0x04, 0x00,
+	0x05, 0x00,
+	0x06, 0xeb,
+	0x07, 0xe0,
+	0x08, 0x28,
+	0x09, 0x00,
+	0x0a, 0x80,
+	0x0b, 0x47,
+	0x0c, 0x40,
+	0x0d, 0x00,
+	0x0e, 0x01,
+	0x0f, 0x44,
+
+	0x10, 0x08,
+	0x11, 0x0c,
+	0x12, 0x7b,
+	0x13, 0x00,
+	0x15, 0x00, 0x16, 0x00, 0x17, 0x00,
+
+	0x57, 0xff,
+	0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,
+	0x5b, 0x83, 0x5e, 0x00,
+	0xff
+};
+
+static int saa7113_init(struct budget_av *budget_av)
+{
+	struct budget *budget = &budget_av->budget;
+	struct saa7146_dev *saa = budget->dev;
+	const u8 *data = saa7113_tab;
+
+	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
+	msleep(200);
+
+	if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
+		dprintk(1, "saa7113 not found on KNC card\n");
+		return -ENODEV;
+	}
+
+	dprintk(1, "saa7113 detected and initializing\n");
+
+	while (*data != 0xff) {
+		i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));
+		data += 2;
+	}
+
+	dprintk(1, "saa7113  status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));
+
+	return 0;
+}
+
+static int saa7113_setinput(struct budget_av *budget_av, int input)
+{
+	struct budget *budget = &budget_av->budget;
+
+	if (1 != budget_av->has_saa7113)
+		return -ENODEV;
+
+	if (input == 1) {
+		i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);
+		i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);
+	} else if (input == 0) {
+		i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);
+		i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);
+	} else
+		return -EINVAL;
+
+	budget_av->cur_input = input;
+	return 0;
+}
+
+
+static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+	u8 m1;
+
+	aclk = 0xb5;
+	if (srate < 2000000)
+		bclk = 0x86;
+	else if (srate < 5000000)
+		bclk = 0x89;
+	else if (srate < 15000000)
+		bclk = 0x8f;
+	else if (srate < 45000000)
+		bclk = 0x95;
+
+	m1 = 0x14;
+	if (srate < 4000000)
+		m1 = 0x10;
+
+	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);
+	stv0299_writereg(fe, 0x0f, 0x80 | m1);
+
+	return 0;
+}
+
+static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
+						 struct dvb_frontend_parameters *params)
+{
+	u32 div;
+	u8 buf[4];
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+	struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
+
+	if ((params->frequency < 950000) || (params->frequency > 2150000))
+		return -EINVAL;
+
+	div = (params->frequency + (125 - 1)) / 125;	// round correctly
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
+	buf[3] = 0x20;
+
+	if (params->u.qpsk.symbol_rate < 4000000)
+		buf[3] |= 1;
+
+	if (params->frequency < 1250000)
+		buf[3] |= 0;
+	else if (params->frequency < 1550000)
+		buf[3] |= 0x40;
+	else if (params->frequency < 2050000)
+		buf[3] |= 0x80;
+	else if (params->frequency < 2150000)
+		buf[3] |= 0xC0;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
+		return -EIO;
+	return 0;
+}
+
+static u8 typhoon_cinergy1200s_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x30,
+	0x03, 0x00,
+	0x04, 0x7d,		/* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+	0x05, 0x35,		/* I2CT = 0, SCLT = 1, SDAT = 1 */
+	0x06, 0x40,		/* DAC not used, set to high impendance mode */
+	0x07, 0x00,		/* DAC LSB */
+	0x08, 0x40,		/* DiSEqC off */
+	0x09, 0x00,		/* FIFO */
+	0x0c, 0x51,		/* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+	0x0d, 0x82,		/* DC offset compensation = ON, beta_agc1 = 2 */
+	0x0e, 0x23,		/* alpha_tmg = 2, beta_tmg = 3 */
+	0x10, 0x3f,		// AGC2  0x3d
+	0x11, 0x84,
+	0x12, 0xb9,
+	0x15, 0xc9,		// lock detector threshold
+	0x16, 0x00,
+	0x17, 0x00,
+	0x18, 0x00,
+	0x19, 0x00,
+	0x1a, 0x00,
+	0x1f, 0x50,
+	0x20, 0x00,
+	0x21, 0x00,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x28, 0x00,		// out imp: normal  out type: parallel FEC mode:0
+	0x29, 0x1e,		// 1/2 threshold
+	0x2a, 0x14,		// 2/3 threshold
+	0x2b, 0x0f,		// 3/4 threshold
+	0x2c, 0x09,		// 5/6 threshold
+	0x2d, 0x05,		// 7/8 threshold
+	0x2e, 0x01,
+	0x31, 0x1f,		// test all FECs
+	0x32, 0x19,		// viterbi and synchro search
+	0x33, 0xfc,		// rs control
+	0x34, 0x93,		// error control
+	0x0f, 0x92,
+	0xff, 0xff
+};
+
+static struct stv0299_config typhoon_config = {
+	.demod_address = 0x68,
+	.inittab = typhoon_cinergy1200s_inittab,
+	.mclk = 88000000UL,
+	.invert = 0,
+	.skip_reinit = 0,
+	.lock_output = STV0229_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+	.min_delay_ms = 100,
+	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+};
+
+
+static struct stv0299_config cinergy_1200s_config = {
+	.demod_address = 0x68,
+	.inittab = typhoon_cinergy1200s_inittab,
+	.mclk = 88000000UL,
+	.invert = 0,
+	.skip_reinit = 0,
+	.lock_output = STV0229_LOCKOUTPUT_0,
+	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+	.min_delay_ms = 100,
+	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+};
+
+static struct stv0299_config cinergy_1200s_1894_0010_config = {
+	.demod_address = 0x68,
+	.inittab = typhoon_cinergy1200s_inittab,
+	.mclk = 88000000UL,
+	.invert = 1,
+	.skip_reinit = 0,
+	.lock_output = STV0229_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+	.min_delay_ms = 100,
+	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
+};
+
+static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+	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(&budget->i2c_adap, &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(&budget->i2c_adap, &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(&budget->i2c_adap, &msg, 1) != 1)
+		return -EIO;
+
+	return 0;
+}
+
+static struct tda1002x_config philips_cu1216_config = {
+	.demod_address = 0x0c,
+	.invert = 1,
+};
+
+static struct tda1002x_config philips_cu1216_config_altaddress = {
+	.demod_address = 0x0d,
+	.invert = 0,
+};
+
+static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
+{
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+	static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
+	struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
+
+	// setup PLL configuration
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
+		return -EIO;
+	msleep(1);
+
+	return 0;
+}
+
+static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+	u8 tuner_buf[4];
+	struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf,.len =
+			sizeof(tuner_buf) };
+	int tuner_frequency = 0;
+	u8 band, cp, filter;
+
+	// determine charge pump
+	tuner_frequency = params->frequency + 36166000;
+	if (tuner_frequency < 87000000)
+		return -EINVAL;
+	else if (tuner_frequency < 130000000)
+		cp = 3;
+	else if (tuner_frequency < 160000000)
+		cp = 5;
+	else if (tuner_frequency < 200000000)
+		cp = 6;
+	else if (tuner_frequency < 290000000)
+		cp = 3;
+	else if (tuner_frequency < 420000000)
+		cp = 5;
+	else if (tuner_frequency < 480000000)
+		cp = 6;
+	else if (tuner_frequency < 620000000)
+		cp = 3;
+	else if (tuner_frequency < 830000000)
+		cp = 5;
+	else if (tuner_frequency < 895000000)
+		cp = 7;
+	else
+		return -EINVAL;
+
+	// determine band
+	if (params->frequency < 49000000)
+		return -EINVAL;
+	else if (params->frequency < 161000000)
+		band = 1;
+	else if (params->frequency < 444000000)
+		band = 2;
+	else if (params->frequency < 861000000)
+		band = 4;
+	else
+		return -EINVAL;
+
+	// setup PLL filter
+	switch (params->u.ofdm.bandwidth) {
+	case BANDWIDTH_6_MHZ:
+		filter = 0;
+		break;
+
+	case BANDWIDTH_7_MHZ:
+		filter = 0;
+		break;
+
+	case BANDWIDTH_8_MHZ:
+		filter = 1;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// calculate divisor
+	// ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
+	tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000;
+
+	// setup tuner buffer
+	tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;
+	tuner_buf[1] = tuner_frequency & 0xff;
+	tuner_buf[2] = 0xca;
+	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
+		return -EIO;
+
+	msleep(1);
+	return 0;
+}
+
+static int philips_tu1216_request_firmware(struct dvb_frontend *fe,
+					   const struct firmware **fw, char *name)
+{
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+
+	return request_firmware(fw, name, &budget->dev->pci->dev);
+}
+
+static struct tda1004x_config philips_tu1216_config = {
+
+	.demod_address = 0x8,
+	.invert = 1,
+	.invert_oclk = 1,
+	.xtal_freq = TDA10046_XTAL_4M,
+	.agc_config = TDA10046_AGC_DEFAULT,
+	.if_freq = TDA10046_FREQ_3617,
+	.request_firmware = philips_tu1216_request_firmware,
+};
+
+static u8 philips_sd1878_inittab[] = {
+	0x01, 0x15,
+	0x02, 0x30,
+	0x03, 0x00,
+	0x04, 0x7d,
+	0x05, 0x35,
+	0x06, 0x40,
+	0x07, 0x00,
+	0x08, 0x43,
+	0x09, 0x02,
+	0x0C, 0x51,
+	0x0D, 0x82,
+	0x0E, 0x23,
+	0x10, 0x3f,
+	0x11, 0x84,
+	0x12, 0xb9,
+	0x15, 0xc9,
+	0x16, 0x19,
+	0x17, 0x8c,
+	0x18, 0x59,
+	0x19, 0xf8,
+	0x1a, 0xfe,
+	0x1c, 0x7f,
+	0x1d, 0x00,
+	0x1e, 0x00,
+	0x1f, 0x50,
+	0x20, 0x00,
+	0x21, 0x00,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x28, 0x00,
+	0x29, 0x28,
+	0x2a, 0x14,
+	0x2b, 0x0f,
+	0x2c, 0x09,
+	0x2d, 0x09,
+	0x31, 0x1f,
+	0x32, 0x19,
+	0x33, 0xfc,
+	0x34, 0x93,
+	0xff, 0xff
+};
+
+static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
+						   struct dvb_frontend_parameters *params)
+{
+	u8              buf[4];
+	int             rc;
+	struct i2c_msg  tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)};
+	struct budget *budget = (struct budget *) fe->dvb->priv;
+
+	if((params->frequency < 950000) || (params->frequency > 2150000))
+		return -EINVAL;
+
+	rc=dvb_pll_configure(&dvb_pll_philips_sd1878_tda8261, buf,
+			     params->frequency, 0);
+	if(rc < 0) return rc;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if(i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
+		return -EIO;
+
+    return 0;
+}
+
+static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,
+		u32 srate, u32 ratio)
+{
+	u8 aclk = 0;
+	u8 bclk = 0;
+	u8 m1;
+
+	aclk = 0xb5;
+	if (srate < 2000000)
+		bclk = 0x86;
+	else if (srate < 5000000)
+		bclk = 0x89;
+	else if (srate < 15000000)
+		bclk = 0x8f;
+	else if (srate < 45000000)
+		bclk = 0x95;
+
+	m1 = 0x14;
+	if (srate < 4000000)
+		m1 = 0x10;
+
+	stv0299_writereg(fe, 0x0e, 0x23);
+	stv0299_writereg(fe, 0x0f, 0x94);
+	stv0299_writereg(fe, 0x10, 0x39);
+	stv0299_writereg(fe, 0x13, aclk);
+	stv0299_writereg(fe, 0x14, bclk);
+	stv0299_writereg(fe, 0x15, 0xc9);
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+	stv0299_writereg(fe, 0x0f, 0x80 | m1);
+
+	return 0;
+}
+
+static struct stv0299_config philips_sd1878_config = {
+	.demod_address = 0x68,
+     .inittab = philips_sd1878_inittab,
+	.mclk = 88000000UL,
+	.invert = 0,
+	.skip_reinit = 0,
+	.lock_output = STV0229_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP0,
+	.min_delay_ms = 100,
+	.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
+};
+
+static u8 read_pwm(struct budget_av *budget_av)
+{
+	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(&budget_av->budget.i2c_adap, msg, 2) != 2)
+	    || (pwm == 0xff))
+		pwm = 0x48;
+
+	return pwm;
+}
+
+#define SUBID_DVBS_KNC1			0x0010
+#define SUBID_DVBS_KNC1_PLUS		0x0011
+#define SUBID_DVBS_TYPHOON		0x4f56
+#define SUBID_DVBS_CINERGY1200		0x1154
+#define SUBID_DVBS_CYNERGY1200N 	0x1155
+#define SUBID_DVBS_TV_STAR		0x0014
+#define SUBID_DVBS_TV_STAR_CI		0x0016
+#define SUBID_DVBS_EASYWATCH_1  	0x001a
+#define SUBID_DVBS_EASYWATCH		0x001e
+
+#define SUBID_DVBC_EASYWATCH		0x002a
+#define SUBID_DVBC_EASYWATCH_MK3	0x002c
+#define SUBID_DVBC_KNC1			0x0020
+#define SUBID_DVBC_KNC1_PLUS		0x0021
+#define SUBID_DVBC_KNC1_MK3		0x0022
+#define SUBID_DVBC_KNC1_PLUS_MK3	0x0023
+#define SUBID_DVBC_CINERGY1200		0x1156
+#define SUBID_DVBC_CINERGY1200_MK3	0x1176
+
+#define SUBID_DVBT_KNC1_PLUS		0x0031
+#define SUBID_DVBT_KNC1			0x0030
+#define SUBID_DVBT_CINERGY1200		0x1157
+
+static void frontend_init(struct budget_av *budget_av)
+{
+	struct saa7146_dev * saa = budget_av->budget.dev;
+	struct dvb_frontend * fe = NULL;
+
+	/* Enable / PowerON Frontend */
+	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+
+	/* Wait for PowerON */
+	msleep(100);
+
+	/* additional setup necessary for the PLUS cards */
+	switch (saa->pci->subsystem_device) {
+		case SUBID_DVBS_KNC1_PLUS:
+		case SUBID_DVBC_KNC1_PLUS:
+		case SUBID_DVBT_KNC1_PLUS:
+		case SUBID_DVBC_EASYWATCH:
+		case SUBID_DVBC_KNC1_PLUS_MK3:
+			saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
+			break;
+	}
+
+	switch (saa->pci->subsystem_device) {
+
+	case SUBID_DVBS_KNC1:
+	case SUBID_DVBS_KNC1_PLUS:
+	case SUBID_DVBS_EASYWATCH_1:
+		if (saa->pci->subsystem_vendor == 0x1894) {
+			fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config,
+					     &budget_av->budget.i2c_adap);
+			if (fe) {
+				dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap);
+			}
+		} else {
+			fe = dvb_attach(stv0299_attach, &typhoon_config,
+					     &budget_av->budget.i2c_adap);
+			if (fe) {
+				fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+			}
+		}
+		break;
+
+	case SUBID_DVBS_TV_STAR:
+	case SUBID_DVBS_TV_STAR_CI:
+	case SUBID_DVBS_CYNERGY1200N:
+	case SUBID_DVBS_EASYWATCH:
+		fe = dvb_attach(stv0299_attach, &philips_sd1878_config,
+				&budget_av->budget.i2c_adap);
+		if (fe) {
+			fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params;
+		}
+		break;
+
+	case SUBID_DVBS_TYPHOON:
+		fe = dvb_attach(stv0299_attach, &typhoon_config,
+				    &budget_av->budget.i2c_adap);
+		if (fe) {
+			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+		}
+		break;
+
+	case SUBID_DVBS_CINERGY1200:
+		fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,
+				    &budget_av->budget.i2c_adap);
+		if (fe) {
+			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+		}
+		break;
+
+	case SUBID_DVBC_KNC1:
+	case SUBID_DVBC_KNC1_PLUS:
+	case SUBID_DVBC_CINERGY1200:
+	case SUBID_DVBC_EASYWATCH:
+		budget_av->reinitialise_demod = 1;
+		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
+		fe = dvb_attach(tda10021_attach, &philips_cu1216_config,
+				     &budget_av->budget.i2c_adap,
+				     read_pwm(budget_av));
+		if (fe == NULL)
+			fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,
+					     &budget_av->budget.i2c_adap,
+					     read_pwm(budget_av));
+		if (fe) {
+			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
+		}
+		break;
+
+	case SUBID_DVBC_EASYWATCH_MK3:
+	case SUBID_DVBC_CINERGY1200_MK3:
+	case SUBID_DVBC_KNC1_MK3:
+	case SUBID_DVBC_KNC1_PLUS_MK3:
+		budget_av->reinitialise_demod = 1;
+		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
+		fe = dvb_attach(tda10023_attach, &philips_cu1216_config,
+				     &budget_av->budget.i2c_adap,
+				     read_pwm(budget_av));
+		if (fe) {
+			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
+		}
+		break;
+
+	case SUBID_DVBT_KNC1:
+	case SUBID_DVBT_KNC1_PLUS:
+	case SUBID_DVBT_CINERGY1200:
+		budget_av->reinitialise_demod = 1;
+		fe = dvb_attach(tda10046_attach, &philips_tu1216_config,
+				     &budget_av->budget.i2c_adap);
+		if (fe) {
+			fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
+			fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
+		}
+		break;
+	}
+
+	if (fe == NULL) {
+		printk(KERN_ERR "budget-av: A frontend driver was not found "
+				"for device %04x/%04x subsystem %04x/%04x\n",
+		       saa->pci->vendor,
+		       saa->pci->device,
+		       saa->pci->subsystem_vendor,
+		       saa->pci->subsystem_device);
+		return;
+	}
+
+	budget_av->budget.dvb_frontend = fe;
+
+	if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
+				  budget_av->budget.dvb_frontend)) {
+		printk(KERN_ERR "budget-av: Frontend registration failed!\n");
+		dvb_frontend_detach(budget_av->budget.dvb_frontend);
+		budget_av->budget.dvb_frontend = NULL;
+	}
+}
+
+
+static void budget_av_irq(struct saa7146_dev *dev, u32 * isr)
+{
+	struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
+
+	dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);
+
+	if (*isr & MASK_10)
+		ttpci_budget_irq10_handler(dev, isr);
+}
+
+static int budget_av_detach(struct saa7146_dev *dev)
+{
+	struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
+	int err;
+
+	dprintk(2, "dev: %p\n", dev);
+
+	if (1 == budget_av->has_saa7113) {
+		saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
+
+		msleep(200);
+
+		saa7146_unregister_device(&budget_av->vd, dev);
+
+		saa7146_vv_release(dev);
+	}
+
+	if (budget_av->budget.ci_present)
+		ciintf_deinit(budget_av);
+
+	if (budget_av->budget.dvb_frontend != NULL) {
+		dvb_unregister_frontend(budget_av->budget.dvb_frontend);
+		dvb_frontend_detach(budget_av->budget.dvb_frontend);
+	}
+	err = ttpci_budget_deinit(&budget_av->budget);
+
+	kfree(budget_av);
+
+	return err;
+}
+
+static struct saa7146_ext_vv vv_data;
+
+static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
+{
+	struct budget_av *budget_av;
+	u8 *mac;
+	int err;
+
+	dprintk(2, "dev: %p\n", dev);
+
+	if (!(budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL)))
+		return -ENOMEM;
+
+	budget_av->has_saa7113 = 0;
+	budget_av->budget.ci_present = 0;
+
+	dev->ext_priv = budget_av;
+
+	if ((err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE))) {
+		kfree(budget_av);
+		return err;
+	}
+
+	/* knc1 initialization */
+	saa7146_write(dev, DD1_STREAM_B, 0x04000000);
+	saa7146_write(dev, DD1_INIT, 0x07000600);
+	saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
+
+	if (saa7113_init(budget_av) == 0) {
+		budget_av->has_saa7113 = 1;
+
+		if (0 != saa7146_vv_init(dev, &vv_data)) {
+			/* fixme: proper cleanup here */
+			ERR(("cannot init vv subsystem.\n"));
+			return err;
+		}
+
+		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
+			/* fixme: proper cleanup here */
+			ERR(("cannot register capture v4l2 device.\n"));
+			saa7146_vv_release(dev);
+			return err;
+		}
+
+		/* beware: this modifies dev->vv ... */
+		saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,
+						SAA7146_HPS_SYNC_PORT_A);
+
+		saa7113_setinput(budget_av, 0);
+	}
+
+	/* fixme: find some sane values here... */
+	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
+
+	mac = budget_av->budget.dvb_adapter.proposed_mac;
+	if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
+		printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
+		       budget_av->budget.dvb_adapter.num);
+		memset(mac, 0, 6);
+	} else {
+		printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+		       budget_av->budget.dvb_adapter.num,
+		       mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+	}
+
+	budget_av->budget.dvb_adapter.priv = budget_av;
+	frontend_init(budget_av);
+	ciintf_init(budget_av);
+
+	ttpci_budget_init_hooks(&budget_av->budget);
+
+	return 0;
+}
+
+#define KNC1_INPUTS 2
+static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {
+	{0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
+	{1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0, V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0},
+};
+
+static struct saa7146_extension_ioctls ioctls[] = {
+	{VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE},
+	{VIDIOC_G_INPUT, SAA7146_EXCLUSIVE},
+	{VIDIOC_S_INPUT, SAA7146_EXCLUSIVE},
+	{0, 0}
+};
+
+static int av_ioctl(struct saa7146_fh *fh, unsigned int cmd, void *arg)
+{
+	struct saa7146_dev *dev = fh->dev;
+	struct budget_av *budget_av = (struct budget_av *) dev->ext_priv;
+
+	switch (cmd) {
+	case VIDIOC_ENUMINPUT:{
+		struct v4l2_input *i = arg;
+
+		dprintk(1, "VIDIOC_ENUMINPUT %d.\n", i->index);
+		if (i->index < 0 || i->index >= KNC1_INPUTS) {
+			return -EINVAL;
+		}
+		memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));
+		return 0;
+	}
+	case VIDIOC_G_INPUT:{
+		int *input = (int *) arg;
+
+		*input = budget_av->cur_input;
+
+		dprintk(1, "VIDIOC_G_INPUT %d.\n", *input);
+		return 0;
+	}
+	case VIDIOC_S_INPUT:{
+		int input = *(int *) arg;
+		dprintk(1, "VIDIOC_S_INPUT %d.\n", input);
+		return saa7113_setinput(budget_av, input);
+	}
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static struct saa7146_standard standard[] = {
+	{.name = "PAL",.id = V4L2_STD_PAL,
+	 .v_offset = 0x17,.v_field = 288,
+	 .h_offset = 0x14,.h_pixels = 680,
+	 .v_max_out = 576,.h_max_out = 768 },
+
+	{.name = "NTSC",.id = V4L2_STD_NTSC,
+	 .v_offset = 0x16,.v_field = 240,
+	 .h_offset = 0x06,.h_pixels = 708,
+	 .v_max_out = 480,.h_max_out = 640, },
+};
+
+static struct saa7146_ext_vv vv_data = {
+	.inputs = 2,
+	.capabilities = 0,	// perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113
+	.flags = 0,
+	.stds = &standard[0],
+	.num_stds = sizeof(standard) / sizeof(struct saa7146_standard),
+	.ioctls = &ioctls[0],
+	.ioctl = av_ioctl,
+};
+
+static struct saa7146_extension budget_extension;
+
+MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
+MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
+MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
+MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
+MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
+MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
+MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);
+MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3);
+MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
+MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
+MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);
+MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);
+MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
+MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
+MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
+MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
+MAKE_BUDGET_INFO(cin1200cmk3, "Terratec Cinergy 1200 DVB-C MK3", BUDGET_CIN1200C_MK3);
+MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
+
+static struct pci_device_id pci_tbl[] = {
+	MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
+	MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
+	MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),
+	MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
+	MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),
+	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
+	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
+	MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
+	MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
+	MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),
+	MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c),
+	MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
+	MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
+	MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),
+	MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),
+	MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
+	MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
+	MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
+	MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),
+	MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
+	MAKE_EXTENSION_PCI(cin1200cmk3, 0x153b, 0x1176),
+	MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
+	{
+	 .vendor = 0,
+	}
+};
+
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+static struct saa7146_extension budget_extension = {
+	.name = "budget_av",
+	.flags = SAA7146_USE_I2C_IRQ,
+
+	.pci_tbl = pci_tbl,
+
+	.module = THIS_MODULE,
+	.attach = budget_av_attach,
+	.detach = budget_av_detach,
+
+	.irq_mask = MASK_10,
+	.irq_func = budget_av_irq,
+};
+
+static int __init budget_av_init(void)
+{
+	return saa7146_register_extension(&budget_extension);
+}
+
+static void __exit budget_av_exit(void)
+{
+	saa7146_unregister_extension(&budget_extension);
+}
+
+module_init(budget_av_init);
+module_exit(budget_av_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
+MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
+		   "budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
diff -urNp linux-2.6.22.1/drivers/media/dvb/ttpci/budget-ci.c linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget-ci.c
--- linux-2.6.22.1/drivers/media/dvb/ttpci/budget-ci.c	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget-ci.c	2007-07-28 01:17:12.000000000 +0200
@@ -47,6 +47,10 @@
 #include "bsbe1.h"
 #include "bsru6.h"
 
+#include "stb0899_drv.h"
+#include "stb0899_reg.h"
+#include "stb6100.h"
+
 /*
  * Regarding DEBIADDR_IR:
  * Some CI modules hang if random addresses are read.
@@ -1056,7 +1060,851 @@ static struct stv0297_config dvbc_philip
 	.stop_during_read = 1,
 };
 
+/*	TT S2-3200 DVB-S (STB0899) Inittab	*/
+static const struct stb0899_s1_reg tt3200_stb0899_s1_init_1[] = {
+#if 1
+//	 0x0000000b ,	/* SYSREG */
+	{ STB0899_DEV_ID		, 0x81 },
+	{ 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		, 0x8c },
+	{ STB0899_DISF22RX		, 0x9a },
+	//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		, 0x30 },
+	{ STB0899_IRQSTATUS_2		, 0x00 },
+	{ STB0899_IRQSTATUS_1		, 0x00 },
+	{ STB0899_IRQSTATUS_0		, 0x00 },
+	{ STB0899_IRQMSK_3		, 0xf3 },
+	{ STB0899_IRQMSK_2		, 0xfc },
+	{ STB0899_IRQMSK_1		, 0xff },
+	{ STB0899_IRQMSK_0		, 0xff },
+	{ STB0899_IRQCFG		, 0x00 },
+	{ STB0899_I2CCFG		, 0x88 },
+	{ STB0899_I2CRPT		, 0x5c },
+	{ STB0899_IOPVALUE5		, 0x00 },
+	{ STB0899_IOPVALUE4		, 0x20 },
+	{ STB0899_IOPVALUE3		, 0xc9 },
+	{ STB0899_IOPVALUE2		, 0x90 },
+	{ STB0899_IOPVALUE1		, 0x40 },
+	{ 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		, 0x15 }, // 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		, 0x00 },
+	{ STB0899_STOPCLK1		, 0x20 },
+	{ STB0899_STOPCLK2		, 0x00 },
+	{ STB0899_INTBUFSTATUS		, 0x00 },
+	{ STB0899_INTBUFCTRL		, 0x0a },
+	{ 0xffff			, 0xff },
+#else
+//	 0x0000000b ,	/* SYSREG */
+	{ STB0899_DEV_ID		, 0x30 /*0x81*/ },	//
+	{ 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        	, 0x8c },
+	{ STB0899_DISF22RX      	, 0x9a },
+	{ STB0899_SYSREG		, 0x0B },		//
+	//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 /*0x30*/ },
+	{ STB0899_IRQSTATUS_2		, 0x80 /*0x00*/ },
+	{ STB0899_IRQSTATUS_1		, 0xBC /*0x00*/ },
+	{ STB0899_IRQSTATUS_0		, 0xF4 /*0x00*/ },
+	{ STB0899_IRQMSK_3      	, 0xf3 },
+	{ STB0899_IRQMSK_2      	, 0xfc },
+	{ STB0899_IRQMSK_1      	, 0xff },
+	{ STB0899_IRQMSK_0		, 0xff },
+	{ STB0899_IRQCFG		, 0x00 },
+	{ STB0899_I2CCFG        	, 0x88 },
+	{ STB0899_I2CRPT        	, 0x5c },
+	{ STB0899_IOPVALUE5		, 0x00 },
+	{ STB0899_IOPVALUE4		, 0x33 /*0x20*/ },
+	{ STB0899_IOPVALUE3		, 0x51 /*0xc9*/ },
+	{ STB0899_IOPVALUE2		, 0x90 },
+	{ STB0899_IOPVALUE1		, 0x40 },
+	{ 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*/ }, // 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       	, 0x00 },
+	{ STB0899_STOPCLK1      	, 0x20 },
+	{ STB0899_STOPCLK2      	, 0x00 },
+	{ STB0899_INTBUFSTATUS		, 0x00 },
+	{ STB0899_INTBUFCTRL    	, 0x0a },
+	{ 0xffff			, 0xff },
+#endif
+};
+
+static const struct stb0899_s2_reg  tt3200_stb0899_s2_init_2[] = {
+
+	{ STB0899_OFF0_DMD_STATUS	, STB0899_BASE_DMD_STATUS	, 0x00000103 },	/* DMDSTATUS	*/
+	{ STB0899_OFF0_CRL_FREQ		, STB0899_BASE_CRL_FREQ		, 0x3ed1da56 },	/* CRLFREQ	*/
+	{ STB0899_OFF0_BTR_FREQ		, STB0899_BASE_BTR_FREQ		, 0x00004000 },	/* BTRFREQ	*/
+	{ STB0899_OFF0_IF_AGC_GAIN	, STB0899_BASE_IF_AGC_GAIN	, 0x00002ade },	/* IFAGCGAIN	*/
+	{ STB0899_OFF0_BB_AGC_GAIN	, STB0899_BASE_BB_AGC_GAIN	, 0x000001bc },	/* BBAGCGAIN	*/
+	{ STB0899_OFF0_DC_OFFSET	, STB0899_BASE_DC_OFFSET	, 0x00000200 },	/* DCOFFSET	*/
+	{ STB0899_OFF0_DMD_CNTRL	, STB0899_BASE_DMD_CNTRL	, 0x0000000f },	/* DMDCNTRL	*/
+
+	{ STB0899_OFF0_IF_AGC_CNTRL	, STB0899_BASE_IF_AGC_CNTRL	, 0x03fb4a20 },	/* IFAGCCNTRL	*/
+	{ STB0899_OFF0_BB_AGC_CNTRL	, STB0899_BASE_BB_AGC_CNTRL	, 0x00200c97 },	/* BBAGCCNTRL	*/
+
+	{ STB0899_OFF0_CRL_CNTRL	, STB0899_BASE_CRL_CNTRL	, 0x00000016 },	/* CRLCNTRL	*/
+	{ STB0899_OFF0_CRL_PHS_INIT	, STB0899_BASE_CRL_PHS_INIT	, 0x00000000 },	/* CRLPHSINIT	*/
+	{ STB0899_OFF0_CRL_FREQ_INIT	, STB0899_BASE_CRL_FREQ_INIT	, 0x00000000 },	/* CRLFREQINIT	*/
+	{ STB0899_OFF0_CRL_LOOP_GAIN	, STB0899_BASE_CRL_LOOP_GAIN	, 0x00000000 },	/* CRLLOOPGAIN	*/
+	{ STB0899_OFF0_CRL_NOM_FREQ	, STB0899_BASE_CRL_NOM_FREQ	, 0x3ed097b6 },	/* CRLNOMFREQ	*/
+	{ STB0899_OFF0_CRL_SWP_RATE	, STB0899_BASE_CRL_SWP_RATE	, 0x00000000 },	/* CRLSWPRATE	*/
+	{ STB0899_OFF0_CRL_MAX_SWP	, STB0899_BASE_CRL_MAX_SWP	, 0x00000000 },	/* CRLMAXSWP	*/
+	{ STB0899_OFF0_CRL_LK_CNTRL	, STB0899_BASE_CRL_LK_CNTRL	, 0x0f6cdc01 },	/* CRLLKCNTRL	*/
+	{ STB0899_OFF0_DECIM_CNTRL	, STB0899_BASE_DECIM_CNTRL	, 0x00000000 },	/* DECIMCNTRL	*/
+	{ STB0899_OFF0_BTR_CNTRL	, STB0899_BASE_BTR_CNTRL	, 0x00003993 },	/* BTRCNTRL	*/
+	{ STB0899_OFF0_BTR_LOOP_GAIN	, STB0899_BASE_BTR_LOOP_GAIN	, 0x000d3c6f },	/* BTRLOOPGAIN	*/
+	{ STB0899_OFF0_BTR_PHS_INIT	, STB0899_BASE_BTR_PHS_INIT	, 0x00000000 },	/* BTRPHSINIT	*/
+	{ STB0899_OFF0_BTR_FREQ_INIT	, STB0899_BASE_BTR_FREQ_INIT	, 0x00000000 },	/* BTRFREQINIT	*/
+	{ STB0899_OFF0_BTR_NOM_FREQ	, STB0899_BASE_BTR_NOM_FREQ	, 0x0238e38e },	/* BTRNOMFREQ	*/
+	{ STB0899_OFF0_BTR_LK_CNTRL	, STB0899_BASE_BTR_LK_CNTRL	, 0x00000000 },	/* BTRLKCNTRL	*/
+	{ STB0899_OFF0_DECN_CNTRL	, STB0899_BASE_DECN_CNTRL	, 0x00000000 },	/* DECNCNTRL	*/
+	{ STB0899_OFF0_TP_CNTRL		, STB0899_BASE_TP_CNTRL		, 0x00000000 },	/* TPCNTRL	*/
+	{ STB0899_OFF0_TP_BUF_STATUS	, STB0899_BASE_TP_BUF_STATUS	, 0x00000000 },	/* TPBUFSTATUS	*/
+	{ STB0899_OFF0_DC_ESTIM		, STB0899_BASE_DC_ESTIM		, 0x00000000 },	/* DCESTIM	*/
+	{ STB0899_OFF0_FLL_CNTRL	, STB0899_BASE_FLL_CNTRL	, 0x00000000 },	/* FLLCNTRL	*/
+	{ STB0899_OFF0_FLL_FREQ_WD	, STB0899_BASE_FLL_FREQ_WD	, 0x40070000 },	/* FLLFREQWD	*/
+	{ STB0899_OFF0_ANTI_ALIAS_SEL	, STB0899_BASE_ANTI_ALIAS_SEL	, 0x00000001 },	/* ANTIALIASSEL */
+	{ STB0899_OFF0_RRC_ALPHA	, STB0899_BASE_RRC_ALPHA	, 0x00000002 },	/* RRCALPHA	*/
+	{ STB0899_OFF0_DC_ADAPT_LSHFT	, STB0899_BASE_DC_ADAPT_LSHFT	, 0x00000000 },	/* DCADAPTISHFT */
+	{ STB0899_OFF0_IMB_OFFSET	, STB0899_BASE_IMB_OFFSET	, 0x0000fe01 },	/* IMBOFFSET	*/
+	{ STB0899_OFF0_IMB_ESTIMATE	, STB0899_BASE_IMB_ESTIMATE	, 0x00000000 },	/* IMBESTIMATE	*/
+	{ STB0899_OFF0_IMB_CNTRL	, STB0899_BASE_IMB_CNTRL	, 0x00000001 },	/* IMBCNTRL	*/
+	{ STB0899_OFF0_IF_AGC_CNTRL2	, STB0899_BASE_IF_AGC_CNTRL2	, 0x00005007 },	/* IFAGCCNTRL2	*/
+	{ STB0899_OFF0_DMD_CNTRL2	, STB0899_BASE_DMD_CNTRL2	, 0x00000002 },	/* DMDCNTRL2	*/
+	{ STB0899_OFF0_TP_BUFFER	, STB0899_BASE_TP_BUFFER	, 0x00000000 },	/* TPBUFFER	*/
+	{ STB0899_OFF0_TP_BUFFER1	, STB0899_BASE_TP_BUFFER1	, 0x00000000 },	/* TPBUFFER1	*/
+	{ STB0899_OFF0_TP_BUFFER2	, STB0899_BASE_TP_BUFFER2	, 0x00000000 },	/* TPBUFFER2	*/
+	{ STB0899_OFF0_TP_BUFFER3	, STB0899_BASE_TP_BUFFER3	, 0x00000000 },	/* TPBUFFER3	*/
+	{ STB0899_OFF0_TP_BUFFER4	, STB0899_BASE_TP_BUFFER4	, 0x00000000 },	/* TPBUFFER4	*/
+	{ STB0899_OFF0_TP_BUFFER5	, STB0899_BASE_TP_BUFFER5	, 0x00000000 },	/* TPBUFFER5	*/
+	{ STB0899_OFF0_TP_BUFFER6	, STB0899_BASE_TP_BUFFER6	, 0x00000000 },	/* TPBUFFER6	*/
+	{ STB0899_OFF0_TP_BUFFER7	, STB0899_BASE_TP_BUFFER7	, 0x00000000 },	/* TPBUFFER7	*/
+	{ STB0899_OFF0_TP_BUFFER8	, STB0899_BASE_TP_BUFFER8	, 0x00000000 },	/* TPBUFFER8	*/
+	{ STB0899_OFF0_TP_BUFFER9	, STB0899_BASE_TP_BUFFER9	, 0x00000000 },	/* TPBUFFER9	*/
+	{ STB0899_OFF0_TP_BUFFER10	, STB0899_BASE_TP_BUFFER10	, 0x00000000 },	/* TPBUFFER10	*/
+	{ STB0899_OFF0_TP_BUFFER11	, STB0899_BASE_TP_BUFFER11	, 0x00000000 },	/* TPBUFFER11	*/
+	{ STB0899_OFF0_TP_BUFFER12	, STB0899_BASE_TP_BUFFER12	, 0x00000000 },	/* TPBUFFER12	*/
+	{ STB0899_OFF0_TP_BUFFER13	, STB0899_BASE_TP_BUFFER13	, 0x00000000 },	/* TPBUFFER13	*/
+	{ STB0899_OFF0_TP_BUFFER14	, STB0899_BASE_TP_BUFFER14	, 0x00000000 },	/* TPBUFFER14	*/
+	{ STB0899_OFF0_TP_BUFFER15	, STB0899_BASE_TP_BUFFER15	, 0x00000000 },	/* TPBUFFER15	*/
+	{ STB0899_OFF0_TP_BUFFER16	, STB0899_BASE_TP_BUFFER16	, 0x0000ff00 },	/* TPBUFFER16	*/
+	{ STB0899_OFF0_TP_BUFFER17	, STB0899_BASE_TP_BUFFER17	, 0x00000100 },	/* TPBUFFER17	*/
+	{ STB0899_OFF0_TP_BUFFER18	, STB0899_BASE_TP_BUFFER18	, 0x0000fe01 },	/* TPBUFFER18	*/
+	{ STB0899_OFF0_TP_BUFFER19	, STB0899_BASE_TP_BUFFER19	, 0x000004fe },	/* TPBUFFER19	*/
+	{ STB0899_OFF0_TP_BUFFER20	, STB0899_BASE_TP_BUFFER20	, 0x0000cfe7 },	/* TPBUFFER20	*/
+	{ STB0899_OFF0_TP_BUFFER21	, STB0899_BASE_TP_BUFFER21	, 0x0000bec6 },	/* TPBUFFER21	*/
+	{ STB0899_OFF0_TP_BUFFER22	, STB0899_BASE_TP_BUFFER22	, 0x0000c2bf },	/* TPBUFFER22	*/
+	{ STB0899_OFF0_TP_BUFFER23	, STB0899_BASE_TP_BUFFER23	, 0x0000c1c1 },	/* TPBUFFER23	*/
+	{ STB0899_OFF0_TP_BUFFER24	, STB0899_BASE_TP_BUFFER24	, 0x0000c1c1 },	/* TPBUFFER24	*/
+	{ STB0899_OFF0_TP_BUFFER25	, STB0899_BASE_TP_BUFFER25	, 0x0000c1c1 },	/* TPBUFFER25	*/
+	{ STB0899_OFF0_TP_BUFFER26	, STB0899_BASE_TP_BUFFER26	, 0x0000c1c1 },	/* TPBUFFER26	*/
+	{ STB0899_OFF0_TP_BUFFER27	, STB0899_BASE_TP_BUFFER27	, 0x0000c1c0 },	/* TPBUFFER27	*/
+	{ STB0899_OFF0_TP_BUFFER28	, STB0899_BASE_TP_BUFFER28	, 0x0000c0c0 },	/* TPBUFFER28	*/
+	{ STB0899_OFF0_TP_BUFFER29	, STB0899_BASE_TP_BUFFER29	, 0x0000c1c1 },	/* TPBUFFER29	*/
+	{ STB0899_OFF0_TP_BUFFER30	, STB0899_BASE_TP_BUFFER30	, 0x0000c1c1 },	/* TPBUFFER30	*/
+	{ STB0899_OFF0_TP_BUFFER31	, STB0899_BASE_TP_BUFFER31	, 0x0000c0c1 },	/* TPBUFFER31	*/
+	{ STB0899_OFF0_TP_BUFFER32	, STB0899_BASE_TP_BUFFER32	, 0x0000c0c1 },	/* TPBUFFER32	*/
+	{ STB0899_OFF0_TP_BUFFER33	, STB0899_BASE_TP_BUFFER33	, 0x0000c1c1 },	/* TPBUFFER33	*/
+	{ STB0899_OFF0_TP_BUFFER34	, STB0899_BASE_TP_BUFFER34	, 0x0000c1c1 },	/* TPBUFFER34	*/
+	{ STB0899_OFF0_TP_BUFFER35	, STB0899_BASE_TP_BUFFER35	, 0x0000c0c1 },	/* TPBUFFER35	*/
+	{ STB0899_OFF0_TP_BUFFER36	, STB0899_BASE_TP_BUFFER36	, 0x0000c1c1 },	/* TPBUFFER36	*/
+	{ STB0899_OFF0_TP_BUFFER37	, STB0899_BASE_TP_BUFFER37	, 0x0000c0c1 },	/* TPBUFFER37	*/
+	{ STB0899_OFF0_TP_BUFFER38	, STB0899_BASE_TP_BUFFER38	, 0x0000c1c1 },	/* TPBUFFER38	*/
+	{ STB0899_OFF0_TP_BUFFER39	, STB0899_BASE_TP_BUFFER39	, 0x0000c0c0 },	/* TPBUFFER39	*/
+	{ STB0899_OFF0_TP_BUFFER40	, STB0899_BASE_TP_BUFFER40	, 0x0000c1c0 },	/* TPBUFFER40	*/
+	{ STB0899_OFF0_TP_BUFFER41	, STB0899_BASE_TP_BUFFER41	, 0x0000c1c1 },	/* TPBUFFER41	*/
+	{ STB0899_OFF0_TP_BUFFER42	, STB0899_BASE_TP_BUFFER42	, 0x0000c0c0 },	/* TPBUFFER42	*/
+	{ STB0899_OFF0_TP_BUFFER43	, STB0899_BASE_TP_BUFFER43	, 0x0000c1c0 },	/* TPBUFFER43	*/
+	{ STB0899_OFF0_TP_BUFFER44	, STB0899_BASE_TP_BUFFER44	, 0x0000c0c1 },	/* TPBUFFER44	*/
+	{ STB0899_OFF0_TP_BUFFER45	, STB0899_BASE_TP_BUFFER45	, 0x0000c1be },	/* TPBUFFER45	*/
+	{ STB0899_OFF0_TP_BUFFER46	, STB0899_BASE_TP_BUFFER46	, 0x0000c1c9 },	/* TPBUFFER46	*/
+	{ STB0899_OFF0_TP_BUFFER47	, STB0899_BASE_TP_BUFFER47	, 0x0000c0da },	/* TPBUFFER47	*/
+	{ STB0899_OFF0_TP_BUFFER48	, STB0899_BASE_TP_BUFFER48	, 0x0000c0ba },	/* TPBUFFER48	*/
+	{ STB0899_OFF0_TP_BUFFER49	, STB0899_BASE_TP_BUFFER49	, 0x0000c1c4 },	/* TPBUFFER49	*/
+	{ STB0899_OFF0_TP_BUFFER50	, STB0899_BASE_TP_BUFFER50	, 0x0000c1bf },	/* TPBUFFER50	*/
+	{ STB0899_OFF0_TP_BUFFER51	, STB0899_BASE_TP_BUFFER51	, 0x0000c0c1 },	/* TPBUFFER51	*/
+	{ STB0899_OFF0_TP_BUFFER52	, STB0899_BASE_TP_BUFFER52	, 0x0000c1c0 },	/* TPBUFFER52	*/
+	{ STB0899_OFF0_TP_BUFFER53	, STB0899_BASE_TP_BUFFER53	, 0x0000c0c1 },	/* TPBUFFER53	*/
+	{ STB0899_OFF0_TP_BUFFER54	, STB0899_BASE_TP_BUFFER54	, 0x0000c1c1 },	/* TPBUFFER54	*/
+	{ STB0899_OFF0_TP_BUFFER55	, STB0899_BASE_TP_BUFFER55	, 0x0000c1c1 },	/* TPBUFFER55	*/
+	{ STB0899_OFF0_TP_BUFFER56	, STB0899_BASE_TP_BUFFER56	, 0x0000c1c1 },	/* TPBUFFER56	*/
+	{ STB0899_OFF0_TP_BUFFER57	, STB0899_BASE_TP_BUFFER57	, 0x0000c1c1 },	/* TPBUFFER57	*/
+	{ STB0899_OFF0_TP_BUFFER58	, STB0899_BASE_TP_BUFFER58	, 0x0000c1c1 },	/* TPBUFFER58	*/
+	{ STB0899_OFF0_TP_BUFFER59	, STB0899_BASE_TP_BUFFER59	, 0x0000c1c1 },	/* TPBUFFER59	*/
+	{ STB0899_OFF0_TP_BUFFER60	, STB0899_BASE_TP_BUFFER60	, 0x0000c1c1 },	/* TPBUFFER60	*/
+	{ STB0899_OFF0_TP_BUFFER61	, STB0899_BASE_TP_BUFFER61	, 0x0000c1c1 },	/* TPBUFFER61	*/
+	{ STB0899_OFF0_TP_BUFFER62	, STB0899_BASE_TP_BUFFER62	, 0x0000c1c1 },	/* TPBUFFER62	*/
+	{ STB0899_OFF0_TP_BUFFER63	, STB0899_BASE_TP_BUFFER63	, 0x0000c1c0 },	/* TPBUFFER63	*/
+	{ STB0899_OFF0_RESET_CNTRL	, STB0899_BASE_RESET_CNTRL	, 0x00000001 },	/* RESETCNTRL	*/
+	{ STB0899_OFF0_ACM_ENABLE	, STB0899_BASE_ACM_ENABLE	, 0x00005654 },	/* ACMENABLE	*/
+	{ STB0899_OFF0_DESCR_CNTRL	, STB0899_BASE_DESCR_CNTRL	, 0x00000000 },	/* DESCRCNTRL	*/
+	{ STB0899_OFF0_CSM_CNTRL1	, STB0899_BASE_CSM_CNTRL1	, 0x00020019 },	/* CSMCNTRL1	*/
+	{ STB0899_OFF0_CSM_CNTRL2	, STB0899_BASE_CSM_CNTRL2	, 0x004b3237 },	/* CSMCNTRL2	*/
+	{ STB0899_OFF0_CSM_CNTRL3	, STB0899_BASE_CSM_CNTRL3	, 0x0003dd17 },	/* CSMCNTRL3	*/
+	{ STB0899_OFF0_CSM_CNTRL4	, STB0899_BASE_CSM_CNTRL4	, 0x00008008 },	/* CSMCNTRL4	*/
+	{ STB0899_OFF0_UWP_CNTRL1	, STB0899_BASE_UWP_CNTRL1	, 0x002a3106 },	/* UWPCNTRL1	*/
+	{ STB0899_OFF0_UWP_CNTRL2	, STB0899_BASE_UWP_CNTRL2	, 0x0006140a },	/* UWPCNTRL2	*/
+	{ STB0899_OFF0_UWP_STAT1	, STB0899_BASE_UWP_STAT1	, 0x00008000 },	/* UWPSTAT1	*/
+	{ STB0899_OFF0_UWP_STAT2	, STB0899_BASE_UWP_STAT2	, 0x00000000 },	/* UWPSTAT2	*/
+	{ STB0899_OFF0_DMD_STAT2	, STB0899_BASE_DMD_STAT2	, 0x00000000 },	/* DMDSTAT2	*/
+	{ STB0899_OFF0_FREQ_ADJ_SCALE	, STB0899_BASE_FREQ_ADJ_SCALE	, 0x00000471 },	/* FREQADJSCALE */
+	{ STB0899_OFF0_UWP_CNTRL3	, STB0899_BASE_UWP_CNTRL3	, 0x017b0465 },	/* UWPCNTRL3	*/
+	{ STB0899_OFF0_SYM_CLK_SEL	, STB0899_BASE_SYM_CLK_SEL	, 0x00000002 },	/* SYMCLKSEL	*/
+	{ STB0899_OFF0_SOF_SRCH_TO	, STB0899_BASE_SOF_SRCH_TO	, 0x00196464 },	/* SOFSRCHTO	*/
+	{ STB0899_OFF0_ACQ_CNTRL1	, STB0899_BASE_ACQ_CNTRL1	, 0x00000603 },	/* ACQCNTRL1	*/
+	{ STB0899_OFF0_ACQ_CNTRL2	, STB0899_BASE_ACQ_CNTRL2	, 0x02046666 },	/* ACQCNTRL2	*/
+	{ STB0899_OFF0_ACQ_CNTRL3	, STB0899_BASE_ACQ_CNTRL3	, 0x10046583 },	/* ACQCNTRL3	*/
+	{ STB0899_OFF0_FE_SETTLE	, STB0899_BASE_FE_SETTLE	, 0x00010404 },	/* FESETTLE	*/
+	{ STB0899_OFF0_AC_DWELL		, STB0899_BASE_AC_DWELL		, 0x0002aa8a },	/* ACDWELL	*/
+	{ STB0899_OFF0_ACQUIRE_TRIG	, STB0899_BASE_ACQUIRE_TRIG	, 0x00000000 },	/* ACQUIRETRIG	*/
+	{ STB0899_OFF0_LOCK_LOST	, STB0899_BASE_LOCK_LOST	, 0x00000001 },	/* LOCKLOST	*/
+	{ STB0899_OFF0_ACQ_STAT1	, STB0899_BASE_ACQ_STAT1	, 0x00000500 },	/* ACQSTAT1	*/
+	{ STB0899_OFF0_ACQ_TIMEOUT	, STB0899_BASE_ACQ_TIMEOUT	, 0x0028a0a0 },	/* ACQTIMEOUT	*/
+	{ STB0899_OFF0_ACQ_TIME		, STB0899_BASE_ACQ_TIME		, 0x00000000 },	/* ACQTIME	*/
+	{ STB0899_OFF0_FINAL_AGC_CNTRL	, STB0899_BASE_FINAL_AGC_CNTRL	, 0x00800c17 },	/* FINALAGCCNTRL*/
+	{ STB0899_OFF0_FINAL_AGC_GAIN	, STB0899_BASE_FINAL_AGC_GAIN	, 0x00000000 },	/* FINALAGCCGAIN*/
+	{ STB0899_OFF0_EQUALIZER_INIT	, STB0899_BASE_EQUALIZER_INIT	, 0x00000000 },	/* EQUILIZERINIT*/
+	{ STB0899_OFF0_EQ_CNTRL		, STB0899_BASE_EQ_CNTRL		, 0x00054802 },	/* EQCNTL	*/
+	{ STB0899_OFF0_EQ_I_INIT_COEFF_0, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF0 */
+	{ STB0899_OFF1_EQ_I_INIT_COEFF_1, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF1 */
+	{ STB0899_OFF2_EQ_I_INIT_COEFF_2, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF2 */
+	{ STB0899_OFF3_EQ_I_INIT_COEFF_3, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF3 */
+	{ STB0899_OFF4_EQ_I_INIT_COEFF_4, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF4 */
+	{ STB0899_OFF5_EQ_I_INIT_COEFF_5, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000400 },	/* EQIINITCOEFF5 */
+	{ STB0899_OFF6_EQ_I_INIT_COEFF_6, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF6 */
+	{ STB0899_OFF7_EQ_I_INIT_COEFF_7, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF7 */
+	{ STB0899_OFF8_EQ_I_INIT_COEFF_8, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF8 */
+	{ STB0899_OFF9_EQ_I_INIT_COEFF_9, STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF9 */
+	{ STB0899_OFFa_EQ_I_INIT_COEFF_10,STB0899_BASE_EQ_I_INIT_COEFF_N, 0x00000000 },	/* EQIINITCOEFF10*/
+	{ STB0899_OFF0_EQ_Q_INIT_COEFF_0, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF0 */
+	{ STB0899_OFF1_EQ_Q_INIT_COEFF_1, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF1 */
+	{ STB0899_OFF2_EQ_Q_INIT_COEFF_2, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF2 */
+	{ STB0899_OFF3_EQ_Q_INIT_COEFF_3, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF3 */
+	{ STB0899_OFF4_EQ_Q_INIT_COEFF_4, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF4 */
+	{ STB0899_OFF5_EQ_Q_INIT_COEFF_5, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF5 */
+	{ STB0899_OFF6_EQ_Q_INIT_COEFF_6, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF6 */
+	{ STB0899_OFF7_EQ_Q_INIT_COEFF_7, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF7 */
+	{ STB0899_OFF8_EQ_Q_INIT_COEFF_8, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF8 */
+	{ STB0899_OFF9_EQ_Q_INIT_COEFF_9, STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF9 */
+	{ STB0899_OFFa_EQ_Q_INIT_COEFF_10,STB0899_BASE_EQ_Q_INIT_COEFF_N, 0x00000000 },	/* EQQINITCOEFF10*/
+	{ STB0899_OFF0_EQ_I_OUT_COEFF_0	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT0 */
+	{ STB0899_OFF1_EQ_I_OUT_COEFF_1	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT1 */
+	{ STB0899_OFF2_EQ_I_OUT_COEFF_2	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT2 */
+	{ STB0899_OFF3_EQ_I_OUT_COEFF_3	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT3 */
+	{ STB0899_OFF4_EQ_I_OUT_COEFF_4	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT4 */
+	{ STB0899_OFF5_EQ_I_OUT_COEFF_5	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT5 */
+	{ STB0899_OFF6_EQ_I_OUT_COEFF_6	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT6 */
+	{ STB0899_OFF7_EQ_I_OUT_COEFF_7	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT7 */
+	{ STB0899_OFF8_EQ_I_OUT_COEFF_8	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT8 */
+	{ STB0899_OFF9_EQ_I_OUT_COEFF_9	, STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT9 */
+	{ STB0899_OFFa_EQ_I_OUT_COEFF_10,STB0899_BASE_EQ_I_OUT_COEFF_N	, 0x00000000 }, /* EQICOEFFSOUT10*/
+	{ STB0899_OFF0_EQ_Q_OUT_COEFF_0	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT0 */
+	{ STB0899_OFF1_EQ_Q_OUT_COEFF_1	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT1 */
+	{ STB0899_OFF2_EQ_Q_OUT_COEFF_2	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT2 */
+	{ STB0899_OFF3_EQ_Q_OUT_COEFF_3	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT3 */
+	{ STB0899_OFF4_EQ_Q_OUT_COEFF_4	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT4 */
+	{ STB0899_OFF5_EQ_Q_OUT_COEFF_5	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT5 */
+	{ STB0899_OFF6_EQ_Q_OUT_COEFF_6 , STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT6 */
+	{ STB0899_OFF7_EQ_Q_OUT_COEFF_7	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT7 */
+	{ STB0899_OFF8_EQ_Q_OUT_COEFF_8	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT8 */
+	{ STB0899_OFF9_EQ_Q_OUT_COEFF_9	, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT9 */
+	{ STB0899_OFFa_EQ_Q_OUT_COEFF_10, STB0899_BASE_EQ_Q_OUT_COEFF_N	, 0x00000000 },	/* EQQCOEFFSOUT10*/
+	{ 0xffff			, 0xffffffff			, 0xffffffff },
+};
+
+static const struct stb0899_s1_reg tt3200_stb0899_s1_init_3[] = {
+#if 1
+	{ STB0899_DEMOD			, 0x00 },
+	{ STB0899_RCOMPC		, 0xc9 },
+	{ STB0899_AGC1CN		, 0x41 },
+	{ STB0899_AGC1REF		, 0x10 },
+	{ STB0899_RTC			, 0x7a },
+	{ STB0899_TMGCFG		, 0x4e },
+	{ STB0899_AGC2REF		, 0x34 },
+	{ STB0899_TLSR			, 0x84 },
+	{ STB0899_CFD			, 0xc7 },
+	{ STB0899_ACLC			, 0x87 },
+	{ STB0899_BCLC			, 0x94 },
+	{ STB0899_EQON			, 0x41 },
+	{ STB0899_LDT			, 0xdd },
+	{ STB0899_LDT2			, 0xc9 },
+	{ STB0899_EQUALREF		, 0xb4 },
+	{ STB0899_TMGRAMP		, 0x10 },
+	{ STB0899_TMGTHD		, 0x30 },
+	{ STB0899_IDCCOMP		, 0xfb },
+	{ STB0899_QDCCOMP		, 0x03 },
+	{ STB0899_POWERI		, 0x3b },
+	{ STB0899_POWERQ		, 0x3d },
+	{ STB0899_RCOMP			, 0x81 },
+	{ STB0899_AGCIQIN		, 0x80 },
+	{ STB0899_AGC2I1		, 0x04 },
+	{ STB0899_AGC2I2		, 0xf5 },
+	{ STB0899_TLIR			, 0x25 },
+	{ STB0899_RTF			, 0x80 },
+	{ STB0899_DSTATUS		, 0x00 },
+	{ STB0899_LDI			, 0xca },
+	{ STB0899_CFRM			, 0xf1 },
+	{ STB0899_CFRL			, 0xf3 },
+	{ STB0899_NIRM			, 0x2a },
+	{ STB0899_NIRL			, 0x05 },
+	{ STB0899_ISYMB			, 0x17 },
+	{ STB0899_QSYMB			, 0xfa },
+	{ STB0899_SFRH			, 0x2f },
+	{ STB0899_SFRM			, 0x68 },
+	{ STB0899_SFRL			, 0x40 },
+	{ STB0899_SFRUPH		, 0x2f },
+	{ STB0899_SFRUPM		, 0x68 },
+	{ STB0899_SFRUPL		, 0x40 },
+	{ STB0899_EQUAI1		, 0xfd },
+	{ STB0899_EQUAQ1		, 0x04 },
+	{ STB0899_EQUAI2		, 0x0f },
+	{ STB0899_EQUAQ2		, 0xff },
+	{ STB0899_EQUAI3		, 0xdf },
+	{ STB0899_EQUAQ3		, 0xfa },
+	{ STB0899_EQUAI4		, 0x37 },
+	{ STB0899_EQUAQ4		, 0x0d },
+	{ STB0899_EQUAI5		, 0xbd },
+	{ STB0899_EQUAQ5		, 0xf7 },
+	{ STB0899_DSTATUS2		, 0x00 },
+	{ STB0899_VSTATUS		, 0x00 },
+	{ STB0899_VERROR		, 0xff },
+	{ STB0899_IQSWAP		, 0x2a },
+	{ STB0899_ECNT1M		, 0x00 },
+	{ STB0899_ECNT1L		, 0x00 },
+	{ STB0899_ECNT2M		, 0x00 },
+	{ STB0899_ECNT2L		, 0x00 },
+	{ STB0899_ECNT3M		, 0x00 },
+	{ STB0899_ECNT3L		, 0x00 },
+	{ STB0899_FECAUTO1		, 0x06 },
+	{ STB0899_FECM			, 0x01 },
+	{ STB0899_VTH12			, 0xf0 },
+	{ STB0899_VTH23			, 0xa0 },
+	{ STB0899_VTH34			, 0x78 },
+	{ STB0899_VTH56			, 0x4e },
+	{ STB0899_VTH67			, 0x48 },
+	{ STB0899_VTH78			, 0x38 },
+	{ STB0899_PRVIT			, 0xff },
+	{ STB0899_VITSYNC		, 0x19 },
+	{ STB0899_RSULC			, 0xb1 }, // DVB = 0xb1, DSS = 0xa1
+	{ STB0899_TSULC			, 0x42 },
+	{ STB0899_RSLLC			, 0x40 },
+	{ STB0899_TSLPL			, 0x12 },
+	{ STB0899_TSCFGH		, 0x0c },
+	{ STB0899_TSCFGM		, 0x00 },
+	{ STB0899_TSCFGL		, 0x0c },
+	{ STB0899_TSOUT			, 0x07 },
+	{ STB0899_RSSYNCDEL		, 0x00 },
+	{ STB0899_TSINHDELH		, 0x02 },
+	{ STB0899_TSINHDELM		, 0x00 },
+	{ STB0899_TSINHDELL		, 0x00 },
+	{ STB0899_TSLLSTKM		, 0x00 },
+	{ STB0899_TSLLSTKL		, 0x00 },
+	{ STB0899_TSULSTKM		, 0x00 },
+	{ STB0899_TSULSTKL		, 0xab },
+	{ STB0899_PCKLENUL		, 0x00 },
+	{ STB0899_PCKLENLL		, 0xcc },
+	{ STB0899_RSPCKLEN		, 0xcc },
+	{ STB0899_TSSTATUS		, 0x80 },
+	{ STB0899_ERRCTRL1		, 0xb6 },
+	{ STB0899_ERRCTRL2		, 0x96 },
+	{ STB0899_ERRCTRL3		, 0x89 },
+	{ STB0899_DMONMSK1		, 0x27 },
+	{ STB0899_DMONMSK0		, 0x03 },
+	{ STB0899_DEMAPVIT		, 0x5c },
+	{ STB0899_PLPARM		, 0x1f },
+	{ 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		, 0x00 },
+	{ STB0899_MATSTRL		, 0x00 },
+	{ STB0899_UPLSTRM		, 0x00 },
+	{ STB0899_UPLSTRL		, 0x00 },
+	{ STB0899_DFLSTRM		, 0x00 },
+	{ STB0899_DFLSTRL		, 0x00 },
+	{ STB0899_SYNCSTR		, 0x00 },
+	{ STB0899_SYNCDSTRM		, 0x00 },
+	{ STB0899_SYNCDSTRL		, 0x00 },
+	{ STB0899_CFGPDELSTATUS1	, 0x10 },
+	{ STB0899_CFGPDELSTATUS2	, 0x00 },
+	{ STB0899_BBFERRORM		, 0x00 },
+	{ STB0899_BBFERRORL		, 0x00 },
+	{ STB0899_UPKTERRORM		, 0x00 },
+	{ STB0899_UPKTERRORL		, 0x00 },
+	{ 0xffff			, 0xff },
+#else
+	{ STB0899_DEMOD         	, 0x20 /*0x00*/ },
+	{ STB0899_RCOMPC        	, 0xc9 },
+	{ STB0899_AGC1CN        	, 0x01 /*0x41*/ },
+	{ STB0899_AGC1REF       	, 0x10 },
+	{ STB0899_RTC	        	, 0x7a },
+	{ STB0899_TMGCFG        	, 0x4e },
+	{ STB0899_AGC2REF       	, 0x34 },
+	{ STB0899_TLSR          	, 0x84 },
+	{ STB0899_CFD           	, 0x47 /*0xc7*/ },
+	{ STB0899_ACLC	        	, 0xC8 /*0x87*/ },
+	{ STB0899_BCLC          	, 0xA0 /*0x94*/ },
+	{ STB0899_EQON          	, 0x41 },
+	{ STB0899_LDT           	, 0xdd },
+	{ STB0899_LDT2          	, 0xc9 },
+	{ STB0899_EQUALREF      	, 0xb4 },
+	{ STB0899_TMGRAMP       	, 0x10 },
+	{ STB0899_TMGTHD        	, 0x30 },
+	{ STB0899_IDCCOMP		, 0xFF /*0xfb*/ },
+	{ STB0899_QDCCOMP		, 0x01 /*0x03*/ },
+	{ STB0899_POWERI		, 0x16 /*0x3b*/ },
+	{ STB0899_POWERQ		, 0x16 /*0x3d*/ },
+	{ STB0899_RCOMP			, 0x7B /*0x81*/ },
+	{ STB0899_AGCIQIN		, 0x80 },
+	{ STB0899_AGC2I1		, 0x03 /*0x04*/ },
+	{ STB0899_AGC2I2		, 0x1F /*0xf5*/ },
+	{ STB0899_TLIR			, 0x31 /*0x25*/ },
+	{ STB0899_RTF			, 0xF2 /*0x80*/ },
+	{ STB0899_DSTATUS		, 0x08 /*0x00*/ },
+	{ STB0899_LDI			, 0xB2 /*0xca*/ },
+	{ STB0899_CFRM			, 0x00 /*0xf1*/ },
+	{ STB0899_CFRL			, 0x00 /*0xf3*/ },
+	{ STB0899_NIRM			, 0x2C /*0x2a*/ },
+	{ STB0899_NIRL			, 0x18 /*0x05*/ },
+	{ STB0899_ISYMB			, 0x21 /*0x17*/ },
+	{ STB0899_QSYMB			, 0x00 /*0xfa*/ },
+	{ STB0899_SFRH          	, 0x41 /*0x2f*/ },
+	{ STB0899_SFRM          	, 0x2f /*0x68*/ },
+	{ STB0899_SFRL          	, 0x60 /*0x40*/ },
+	{ STB0899_SFRUPH        	, 0x43 /*0x2f*/ },
+	{ STB0899_SFRUPM        	, 0x24 /*0x68*/ },
+	{ STB0899_SFRUPL        	, 0x00 /*0x40*/ },
+	{ STB0899_EQUAI1		, 0x00 /*0xfd*/ },
+	{ STB0899_EQUAQ1		, 0x00 /*0x04*/ },
+	{ STB0899_EQUAI2		, 0x00 /*0x0f*/ },
+	{ STB0899_EQUAQ2		, 0x00 /*0xff*/ },
+	{ STB0899_EQUAI3		, 0x00 /*0xdf*/ },
+	{ STB0899_EQUAQ3		, 0x00 /*0xfa*/ },
+	{ STB0899_EQUAI4		, 0x00 /*0x37*/ },
+	{ STB0899_EQUAQ4		, 0x00 /*0x0d*/ },
+	{ STB0899_EQUAI5		, 0x00 /*0xbd*/ },
+	{ STB0899_EQUAQ5		, 0x00 /*0xf7*/ },
+	{ STB0899_DSTATUS2		, 0x40 /*0x00*/ },
+	{ STB0899_VSTATUS       	, 0x00 },
+	{ STB0899_VERROR		, 0xff },
+	{ STB0899_IQSWAP		, 0x20 /*0x2a*/ },
+	{ STB0899_ECNT1M		, 0x00 },
+	{ STB0899_ECNT1L		, 0x02 /*0x00*/ },
+	{ STB0899_ECNT2M		, 0x00 },
+	{ STB0899_ECNT2L		, 0x00 },
+	{ STB0899_ECNT3M		, 0x3c /*0x00*/ },
+	{ STB0899_ECNT3L		, 0xF6 /*0x00*/ },
+	{ STB0899_FECAUTO1      	, 0x06 },
+	{ STB0899_FECM	        	, 0x00 /*0x01*/ },
+	{ STB0899_VTH12         	, 0xb0 /*0xf0*/ },
+	{ STB0899_VTH23         	, 0x7a /*0xa0*/ },
+	{ STB0899_VTH34	        	, 0x58 /*0x78*/ },
+	{ STB0899_VTH56         	, 0x38 /*0x4e*/ },
+	{ STB0899_VTH67         	, 0x34 /*0x48*/ },
+	{ STB0899_VTH78         	, 0x24 /*0x38*/ },
+	{ STB0899_PRVIT         	, 0xff },
+	{ STB0899_VITSYNC       	, 0x19 },
+	{ STB0899_RSULC         	, 0xb1 }, // DVB = 0xb1, DSS = 0xa1
+	{ STB0899_TSULC         	, 0x42 },
+	{ STB0899_RSLLC         	, 0x40 },
+	{ STB0899_TSLPL	        	, 0x12 },
+	{ STB0899_TSCFGH        	, 0x00 /*0x0c*/ }, //0x0c
+	{ STB0899_TSCFGM        	, 0x5f /*0x00*/ },
+	{ STB0899_TSCFGL        	, 0x0c }, //0x0c
+	{ STB0899_TSOUT         	, 0x07 },
+	{ STB0899_RSSYNCDEL     	, 0x00 },
+	{ STB0899_TSINHDELH     	, 0x02 },
+	{ STB0899_TSINHDELM		, 0x00 },
+	{ STB0899_TSINHDELL		, 0x00 },
+	{ STB0899_TSLLSTKM		, 0x0e /*0x00*/ },
+	{ STB0899_TSLLSTKL		, 0xe4 /*0x00*/ },
+	{ STB0899_TSULSTKM		, 0x00 },
+	{ STB0899_TSULSTKL		, 0x00 /*0xab*/ },
+	{ STB0899_PCKLENUL		, 0xbc /*0x00*/ },
+	{ STB0899_PCKLENLL		, 0xcc },
+	{ STB0899_RSPCKLEN		, 0x83 /*0xcc*/ },
+	{ STB0899_TSSTATUS		, 0xd8 /*0x80*/ },
+	{ STB0899_ERRCTRL1      	, 0xb6 },
+	{ STB0899_ERRCTRL2      	, 0x96 },
+	{ STB0899_ERRCTRL3      	, 0x89 },
+	{ STB0899_DMONMSK1		, 0x27 },
+	{ STB0899_DMONMSK0		, 0x03 },
+	{ STB0899_DEMAPVIT      	, 0x3c /*0x5c*/ },
+	{ STB0899_PLPARM		, 0x35 /*0x1f*/ },
+	{ 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 /*0x00*/ },
+	{ STB0899_MATSTRL		, 0x01 /*0x00*/ },
+	{ STB0899_UPLSTRM		, 0x05 /*0x00*/ },
+	{ STB0899_UPLSTRL		, 0xe0 /*0x00*/ },
+	{ STB0899_DFLSTRM		, 0x7d /*0x00*/ },
+	{ STB0899_DFLSTRL		, 0x80 /*0x00*/ },
+	{ STB0899_SYNCSTR		, 0x47 /*0x00*/ },
+	{ STB0899_SYNCDSTRM		, 0x00 },
+	{ STB0899_SYNCDSTRL		, 0x78 /*0x00*/ },
+	{ STB0899_CFGPDELSTATUS1	, 0x1D /*0x10*/ },
+	{ STB0899_CFGPDELSTATUS2	, 0x0e /*0x00*/ },
+	{ STB0899_BBFERRORM		, 0x00 },
+	{ STB0899_BBFERRORL		, 0x03 /*0x00*/ },
+	{ STB0899_UPKTERRORM		, 0x00 },
+	{ STB0899_UPKTERRORL		, 0x2c /*0x00*/ },
+	{ 0xffff			, 0xff },
+#endif
+};
 
+static const struct stb0899_s2_reg tt3200_stb0899_s2_init_4[] = {
+	{ STB0899_OFF0_BLOCK_LNGTH	, STB0899_BASE_BLOCK_LNGTH	, 0x00000008 },	/* BLOCKLNGTH	*/
+	{ STB0899_OFF0_ROW_STR		, STB0899_BASE_ROW_STR		, 0x000000b4 },	/* ROWSTR	*/
+	{ STB0899_OFF0_BN_END_ADDR	, STB0899_BASE_BN_END_ADDR	, 0x000004b5 },	/* BNANDADDR	*/
+	{ STB0899_OFF0_CN_END_ADDR	, STB0899_BASE_CN_END_ADDR	, 0x00000b4b },	/* CNANDADDR	*/
+	{ STB0899_OFF0_INFO_LENGTH	, STB0899_BASE_INFO_LENGTH	, 0x00000078 },	/* INFOLENGTH	*/
+	{ STB0899_OFF0_BOT_ADDR		, STB0899_BASE_BOT_ADDR		, 0x000001e0 },	/* BOT_ADDR	*/
+	{ STB0899_OFF0_BCH_BLK_LN	, STB0899_BASE_BCH_BLK_LN	, 0x0000a8c0 },	/* BCHBLKLN	*/
+	{ STB0899_OFF0_BCH_T		, STB0899_BASE_BCH_T		, 0x0000000c },	/* BCHT		*/
+	{ STB0899_OFF0_CNFG_MODE	, STB0899_BASE_CNFG_MODE	, 0x00000001 },	/* CNFGMODE	*/
+	{ STB0899_OFF0_LDPC_STAT	, STB0899_BASE_LDPC_STAT	, 0x0000000d },	/* LDPCSTAT	*/
+	{ STB0899_OFF0_ITER_SCALE	, STB0899_BASE_ITER_SCALE	, 0x00000040 },	/* ITERSCALE	*/
+	{ STB0899_OFF0_INPUT_MODE	, STB0899_BASE_INPUT_MODE	, 0x00000000 },	/* INPUTMODE	*/
+	{ STB0899_OFF0_LDPCDECRST	, STB0899_BASE_LDPCDECRST	, 0x00000000 },	/* LDPCDECRST	*/
+	{ STB0899_OFF0_CLK_PER_BYTE_RW	, STB0899_BASE_CLK_PER_BYTE_RW	, 0x00000008 },	/* CLKPERBYTE	*/
+	{ STB0899_OFF0_BCH_ERRORS	, STB0899_BASE_BCH_ERRORS	, 0x00000000 },	/* BCHERRORS	*/
+	{ STB0899_OFF0_LDPC_ERRORS	, STB0899_BASE_LDPC_ERRORS	, 0x00000000 },	/* LDPCERRORS	*/
+	{ STB0899_OFF0_BCH_MODE		, STB0899_BASE_BCH_MODE		, 0x00000000 },	/* BCHMODE	*/
+	{ STB0899_OFF0_ERR_ACC_PER	, STB0899_BASE_ERR_ACC_PER	, 0x00000008 },	/* ERRACCPER	*/
+	{ STB0899_OFF0_BCH_ERR_ACC	, STB0899_BASE_BCH_ERR_ACC	, 0x00000000 },	/* BCHERRACC	*/
+	{ STB0899_OFF0_FEC_TP_SEL	, STB0899_BASE_FEC_TP_SEL	, 0x00000000 },	/* FECTPSEL	*/
+	{ 0xffff			, 0xffffffff			, 0xffffffff },
+};
+
+static const struct stb0899_s1_reg tt3200_stb0899_s1_init_5[] = {
+	{ STB0899_TSTCK		, 0x00 },
+	{ STB0899_TSTRES	, 0x00 },
+	{ STB0899_TSTOUT	, 0x00 },
+	{ STB0899_TSTIN		, 0x00 },
+	{ STB0899_TSTSYS	, 0x00 },
+	{ STB0899_TSTCHIP	, 0x00 },
+	{ STB0899_TSTFREE	, 0x00 },
+	{ STB0899_TSTI2C	, 0x00 },
+	{ STB0899_BITSPEEDM	, 0x00 },
+	{ STB0899_BITSPEEDL	, 0x00 },
+	{ STB0899_TBUSBIT	, 0x00 },
+	{ STB0899_TSTDIS	, 0x00 },
+	{ STB0899_TSTDISRX	, 0x00 },
+	{ STB0899_TSTJETON	, 0x00 },
+	{ STB0899_TSTDCADJ	, 0x00 },
+	{ STB0899_TSTAGC1	, 0x00 },
+	{ STB0899_TSTAGC1N	, 0x00 },
+	{ STB0899_TSTPOLYPH	, 0x00 },
+	{ STB0899_TSTR		, 0x00 },
+	{ STB0899_TSTAGC2	, 0x00 },
+	{ STB0899_TSTCTL1	, 0x00 },
+	{ STB0899_TSTCTL2	, 0x00 },
+	{ STB0899_TSTCTL3	, 0x00 },
+	{ STB0899_TSTDEMAP	, 0x00 },
+	{ STB0899_TSTDEMAP2	, 0x00 },
+	{ STB0899_TSTDEMMON	, 0x00 },
+	{ STB0899_TSTRATE	, 0x00 },
+	{ STB0899_TSTSELOUT	, 0x00 },
+	{ STB0899_TSYNC		, 0x00 },
+	{ STB0899_TSTERR	, 0x00 },
+	{ STB0899_TSTRAM1	, 0x00 },
+	{ STB0899_TSTVSELOUT	, 0x00 },
+	{ STB0899_TSTFORCEIN	, 0x00 },
+	{ STB0899_TSTRS1	, 0x00 },
+	{ STB0899_TSTRS2	, 0x00 },
+	{ STB0899_TSTRS3	, 0x00 },
+	{ STB0899_GHOSTREG	, 0x81 },
+	{ 0xffff		, 0xff },
+};
+
+static int tt3200_set_frequency(struct dvb_frontend *fe, u32 frequency)
+{
+	struct budget* budget = (struct budget*) fe->dvb->priv;
+	struct tuner_state stb6100_tuner_state;
+	if ( budget->dvb_frontend->ops.tuner_ops.set_state ) {
+
+	    stb6100_tuner_state.frequency = frequency;
+
+//	    printk("%s frequency=%d\n",__func__,frequency);
+
+	    budget->dvb_frontend->ops.tuner_ops.set_state(
+			fe,DVBFE_TUNER_FREQUENCY,
+			&stb6100_tuner_state);
+
+		/* FIXME !
+		 * This is just a hack because dvb-pll is too rigid
+		 * will need to adjust dvb-pll to avoid unpleasant
+		 * issues like this !
+		 */
+	    msleep(200);
+	}
+
+	return 0;
+}
+
+static int tt3200_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct budget* budget = (struct budget*) fe->dvb->priv;
+	struct tuner_state stb6100_tuner_state;
+	*frequency = 0;
+	if ( budget->dvb_frontend->ops.tuner_ops.get_state ) {
+
+	    budget->dvb_frontend->ops.tuner_ops.get_state(
+			fe,DVBFE_TUNER_FREQUENCY,
+			&stb6100_tuner_state);
+
+	    *frequency = stb6100_tuner_state.frequency;
+	}
+
+	return 0;
+}
+
+static int tt3200_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth)
+{
+	struct budget* budget = (struct budget*) fe->dvb->priv;
+	struct tuner_state stb6100_tuner_state;
+	if ( budget->dvb_frontend->ops.tuner_ops.set_state ) {
+
+	    stb6100_tuner_state.bandwidth = bandwidth;
+
+//	    printk("%s bandwidth=%d\n",__func__,bandwidth);
+
+	    budget->dvb_frontend->ops.tuner_ops.set_state(
+			fe,DVBFE_TUNER_BANDWIDTH,
+			&stb6100_tuner_state);
+
+		/* FIXME !
+		 * This is just a hack because dvb-pll is too rigid
+		 * will need to adjust dvb-pll to avoid unpleasant
+		 * issues like this !
+		 */
+//	    msleep(200);
+	}
+	return 0;
+}
+
+static int tt3200_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct budget* budget = (struct budget*) fe->dvb->priv;
+	struct tuner_state stb6100_tuner_state;
+
+	*bandwidth = 0;
+	if ( budget->dvb_frontend->ops.tuner_ops.get_state ) {
+
+	    budget->dvb_frontend->ops.tuner_ops.get_state(
+			fe,DVBFE_TUNER_BANDWIDTH,
+			&stb6100_tuner_state);
+
+	    *bandwidth = stb6100_tuner_state.bandwidth;
+
+//	    printk("%s bandwidth=%d\n",__func__,*bandwidth);
+	
+	}
+
+	return 0;
+}
+
+/*
+static int tt3200_set_params(struct dvb_frontend *fe,
+					   struct dvb_frontend_parameters *p)
+{
+        printk("%s frequency=%d\n",__func__,p->frequency);
+	return tt3200_set_frequency(fe,p->frequency);
+}
+*/
+
+#define KNC1_DVBS2_ESNO_AVE			3
+#define KNC1_DVBS2_ESNO_QUANT			32
+#define KNC1_DVBS2_AVFRAMES_COARSE		10
+#define KNC1_DVBS2_AVFRAMES_FINE		20
+#define KNC1_DVBS2_MISS_THRESHOLD		6
+#define KNC1_DVBS2_UWP_THRESHOLD_ACQ		1125
+#define KNC1_DVBS2_UWP_THRESHOLD_TRACK		758
+#define KNC1_DVBS2_UWP_THRESHOLD_SOF		1350
+#define KNC1_DVBS2_SOF_SEARCH_TIMEOUT		1664100
+
+#define KNC1_DVBS2_BTR_NCO_BITS			28
+#define KNC1_DVBS2_BTR_GAIN_SHIFT_OFFSET	15
+#define KNC1_DVBS2_CRL_NCO_BITS			30
+#define KNC1_DVBS2_LDPC_MAX_ITER		70
+
+static struct stb0899_config tt3200_config = {
+	.init_dev	= tt3200_stb0899_s1_init_1,
+	.init_s2_demod	= tt3200_stb0899_s2_init_2,
+	.init_s1_demod	= tt3200_stb0899_s1_init_3,
+	.init_s2_fec	= tt3200_stb0899_s2_init_4,
+	.init_tst	= tt3200_stb0899_s1_init_5,
+
+	.demod_address = 0x68,
+//	.ts_output_mode		= STB0899_OUT_PARALLEL,	/* types = SERIAL/PARALLEL	*/
+	.block_sync_mode	= STB0899_SYNC_FORCED,	/* DSS, SYNC_FORCED/UNSYNCED	*/
+//	.ts_pfbit_toggle	= STB0899_MPEG_NORMAL,	/* DirecTV, MPEG toggling seq	*/
+
+	.xtal_freq		= 27000000,
+//	.inversion		= 1,
+	.inversion		= 2,
+
+	.esno_ave		= KNC1_DVBS2_ESNO_AVE,
+	.esno_quant		= KNC1_DVBS2_ESNO_QUANT,
+	.avframes_coarse	= KNC1_DVBS2_AVFRAMES_COARSE,
+	.avframes_fine		= KNC1_DVBS2_AVFRAMES_FINE,
+	.miss_threshold		= KNC1_DVBS2_MISS_THRESHOLD,
+	.uwp_threshold_acq	= KNC1_DVBS2_UWP_THRESHOLD_ACQ,
+	.uwp_threshold_track	= KNC1_DVBS2_UWP_THRESHOLD_TRACK,
+	.uwp_threshold_sof	= KNC1_DVBS2_UWP_THRESHOLD_SOF,
+	.sof_search_timeout	= KNC1_DVBS2_SOF_SEARCH_TIMEOUT,
+
+	.btr_nco_bits		= KNC1_DVBS2_BTR_NCO_BITS,
+	.btr_gain_shift_offset	= KNC1_DVBS2_BTR_GAIN_SHIFT_OFFSET,
+	.crl_nco_bits		= KNC1_DVBS2_CRL_NCO_BITS,
+	.ldpc_max_iter		= KNC1_DVBS2_LDPC_MAX_ITER,
+
+	.tuner_get_frequency	= tt3200_get_frequency,
+	.tuner_set_frequency	= tt3200_set_frequency,
+	.tuner_set_bandwidth	= tt3200_set_bandwidth,
+	.tuner_get_bandwidth	= tt3200_get_bandwidth,
+};
+
+struct stb6100_config tt3200_stb6100_config = {
+	.tuner_address = 0x60,	/* I2C-Adresse	*/
+	.refclock = 27000,	/* kHz 		*/
+//	.refclock = 27000000,
+};
 
 
 static void frontend_init(struct budget_ci *budget_ci)
@@ -1128,6 +1976,32 @@ static void frontend_init(struct budget_
 		}
 
 		break;
+
+	case 0x1019:		// TT S2-3200 PCI
+		// gpio2 is connected to CLB - reset it + leave it high
+		saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTLO);
+		msleep(1);
+		saa7146_setgpio(budget_ci->budget.dev, 2, SAA7146_GPIO_OUTHI);
+		msleep(1);
+
+		budget_ci->budget.dvb_frontend = dvb_attach(stb0899_attach, &tt3200_config, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			if (dvb_attach(stb6100_attach, budget_ci->budget.dvb_frontend, &tt3200_stb6100_config, &budget_ci->budget.i2c_adap)) {
+				if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
+					printk("%s: No LNBP21 found!\n", __FUNCTION__);
+					if (budget_ci->budget.dvb_frontend->ops.tuner_ops.release)
+						budget_ci->budget.dvb_frontend->ops.tuner_ops.release(budget_ci->budget.dvb_frontend);
+					dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+					budget_ci->budget.dvb_frontend = NULL;
+				}
+			} else {
+				printk("%s: No STB6100 found!\n", __FUNCTION__);
+				dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+				budget_ci->budget.dvb_frontend = NULL;
+			}
+		}
+		break;
+
 	}
 
 	if (budget_ci->budget.dvb_frontend == NULL) {
@@ -1216,6 +2090,7 @@ MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV
 MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T	 PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
 MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(tt3200, "TT-Budget S2-3200 PCI", BUDGET_TT3200);
 
 static struct pci_device_id pci_tbl[] = {
 	MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
@@ -1224,6 +2099,7 @@ static struct pci_device_id pci_tbl[] = 
 	MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
 	MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
 	MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
+	MAKE_EXTENSION_PCI(tt3200, 0x13c2, 0x1019),
 	{
 	 .vendor = 0,
 	 }
diff -urNp linux-2.6.22.1/drivers/media/dvb/ttpci/budget-ci.c.orig linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget-ci.c.orig
--- linux-2.6.22.1/drivers/media/dvb/ttpci/budget-ci.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget-ci.c.orig	2007-07-10 20:56:30.000000000 +0200
@@ -0,0 +1,1264 @@
+/*
+ * budget-ci.c: driver for the SAA7146 based Budget DVB cards
+ *
+ * Compiled from various sources by Michael Hunold <michael@mihu.de>
+ *
+ *     msp430 IR support contributed by Jack Thomasson <jkt@Helius.COM>
+ *     partially based on the Siemens DVB driver by Ralph+Marcus Metzler
+ *
+ * CI interface support (c) 2004 Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org/dvb/
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/spinlock.h>
+#include <media/ir-common.h>
+
+#include "budget.h"
+
+#include "dvb_ca_en50221.h"
+#include "stv0299.h"
+#include "stv0297.h"
+#include "tda1004x.h"
+#include "lnbp21.h"
+#include "bsbe1.h"
+#include "bsru6.h"
+
+/*
+ * Regarding DEBIADDR_IR:
+ * Some CI modules hang if random addresses are read.
+ * Using address 0x4000 for the IR read means that we
+ * use the same address as for CI version, which should
+ * be a safe default.
+ */
+#define DEBIADDR_IR		0x4000
+#define DEBIADDR_CICONTROL	0x0000
+#define DEBIADDR_CIVERSION	0x4000
+#define DEBIADDR_IO		0x1000
+#define DEBIADDR_ATTR		0x3000
+
+#define CICONTROL_RESET		0x01
+#define CICONTROL_ENABLETS	0x02
+#define CICONTROL_CAMDETECT	0x08
+
+#define DEBICICTL		0x00420000
+#define DEBICICAM		0x02420000
+
+#define SLOTSTATUS_NONE		1
+#define SLOTSTATUS_PRESENT	2
+#define SLOTSTATUS_RESET	4
+#define SLOTSTATUS_READY	8
+#define SLOTSTATUS_OCCUPIED	(SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
+
+/*
+ * Milliseconds during which a key is regarded as pressed.
+ * If an identical command arrives within this time, the timer will start over.
+ */
+#define IR_KEYPRESS_TIMEOUT	250
+
+/* RC5 device wildcard */
+#define IR_DEVICE_ANY		255
+
+static int rc5_device = -1;
+module_param(rc5_device, int, 0644);
+MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)");
+
+static int ir_debug = 0;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding");
+
+struct budget_ci_ir {
+	struct input_dev *dev;
+	struct tasklet_struct msp430_irq_tasklet;
+	struct timer_list timer_keyup;
+	char name[72]; /* 40 + 32 for (struct saa7146_dev).name */
+	char phys[32];
+	struct ir_input_state state;
+	int rc5_device;
+	u32 last_raw;
+	u32 ir_key;
+	bool have_command;
+};
+
+struct budget_ci {
+	struct budget budget;
+	struct tasklet_struct ciintf_irq_tasklet;
+	int slot_status;
+	int ci_irq;
+	struct dvb_ca_en50221 ca;
+	struct budget_ci_ir ir;
+	u8 tuner_pll_address; /* used for philips_tdm1316l configs */
+};
+
+static void msp430_ir_keyup(unsigned long data)
+{
+	struct budget_ci_ir *ir = (struct budget_ci_ir *) data;
+	ir_input_nokey(ir->dev, &ir->state);
+}
+
+static void msp430_ir_interrupt(unsigned long data)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) data;
+	struct input_dev *dev = budget_ci->ir.dev;
+	u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8;
+	u32 raw;
+
+	/*
+	 * The msp430 chip can generate two different bytes, command and device
+	 *
+	 * type1: X1CCCCCC, C = command bits (0 - 63)
+	 * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit
+	 *
+	 * Each signal from the remote control can generate one or more command
+	 * bytes and one or more device bytes. For the repeated bytes, the
+	 * highest bit (X) is set. The first command byte is always generated
+	 * before the first device byte. Other than that, no specific order
+	 * seems to apply. To make life interesting, bytes can also be lost.
+	 *
+	 * Only when we have a command and device byte, a keypress is
+	 * generated.
+	 */
+
+	if (ir_debug)
+		printk("budget_ci: received byte 0x%02x\n", command);
+
+	/* Remove repeat bit, we use every command */
+	command = command & 0x7f;
+
+	/* Is this a RC5 command byte? */
+	if (command & 0x40) {
+		budget_ci->ir.have_command = true;
+		budget_ci->ir.ir_key = command & 0x3f;
+		return;
+	}
+
+	/* It's a RC5 device byte */
+	if (!budget_ci->ir.have_command)
+		return;
+	budget_ci->ir.have_command = false;
+
+	if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
+	    budget_ci->ir.rc5_device != (command & 0x1f))
+		return;
+
+	/* Is this a repeated key sequence? (same device, command, toggle) */
+	raw = budget_ci->ir.ir_key | (command << 8);
+	if (budget_ci->ir.last_raw != raw || !timer_pending(&budget_ci->ir.timer_keyup)) {
+		ir_input_nokey(dev, &budget_ci->ir.state);
+		ir_input_keydown(dev, &budget_ci->ir.state,
+				 budget_ci->ir.ir_key, raw);
+		budget_ci->ir.last_raw = raw;
+	}
+
+	mod_timer(&budget_ci->ir.timer_keyup, jiffies + msecs_to_jiffies(IR_KEYPRESS_TIMEOUT));
+}
+
+static int msp430_ir_init(struct budget_ci *budget_ci)
+{
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+	struct input_dev *input_dev = budget_ci->ir.dev;
+	int error;
+
+	budget_ci->ir.dev = input_dev = input_allocate_device();
+	if (!input_dev) {
+		printk(KERN_ERR "budget_ci: IR interface initialisation failed\n");
+		error = -ENOMEM;
+		goto out1;
+	}
+
+	snprintf(budget_ci->ir.name, sizeof(budget_ci->ir.name),
+		 "Budget-CI dvb ir receiver %s", saa->name);
+	snprintf(budget_ci->ir.phys, sizeof(budget_ci->ir.phys),
+		 "pci-%s/ir0", pci_name(saa->pci));
+
+	input_dev->name = budget_ci->ir.name;
+
+	input_dev->phys = budget_ci->ir.phys;
+	input_dev->id.bustype = BUS_PCI;
+	input_dev->id.version = 1;
+	if (saa->pci->subsystem_vendor) {
+		input_dev->id.vendor = saa->pci->subsystem_vendor;
+		input_dev->id.product = saa->pci->subsystem_device;
+	} else {
+		input_dev->id.vendor = saa->pci->vendor;
+		input_dev->id.product = saa->pci->device;
+	}
+	input_dev->cdev.dev = &saa->pci->dev;
+
+	/* Select keymap and address */
+	switch (budget_ci->budget.dev->pci->subsystem_device) {
+	case 0x100c:
+	case 0x100f:
+	case 0x1011:
+	case 0x1012:
+	case 0x1017:
+		/* The hauppauge keymap is a superset of these remotes */
+		ir_input_init(input_dev, &budget_ci->ir.state,
+			      IR_TYPE_RC5, ir_codes_hauppauge_new);
+
+		if (rc5_device < 0)
+			budget_ci->ir.rc5_device = 0x1f;
+		else
+			budget_ci->ir.rc5_device = rc5_device;
+		break;
+	case 0x1010:
+		/* for the Technotrend 1500 bundled remote */
+		ir_input_init(input_dev, &budget_ci->ir.state,
+			      IR_TYPE_RC5, ir_codes_tt_1500);
+
+		if (rc5_device < 0)
+			budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+		else
+			budget_ci->ir.rc5_device = rc5_device;
+		break;
+	default:
+		/* unknown remote */
+		ir_input_init(input_dev, &budget_ci->ir.state,
+			      IR_TYPE_RC5, ir_codes_budget_ci_old);
+
+		if (rc5_device < 0)
+			budget_ci->ir.rc5_device = IR_DEVICE_ANY;
+		else
+			budget_ci->ir.rc5_device = rc5_device;
+		break;
+	}
+
+	/* initialise the key-up timeout handler */
+	init_timer(&budget_ci->ir.timer_keyup);
+	budget_ci->ir.timer_keyup.function = msp430_ir_keyup;
+	budget_ci->ir.timer_keyup.data = (unsigned long) &budget_ci->ir;
+	budget_ci->ir.last_raw = 0xffff; /* An impossible value */
+	error = input_register_device(input_dev);
+	if (error) {
+		printk(KERN_ERR "budget_ci: could not init driver for IR device (code %d)\n", error);
+		goto out2;
+	}
+
+	/* note: these must be after input_register_device */
+	input_dev->rep[REP_DELAY] = 400;
+	input_dev->rep[REP_PERIOD] = 250;
+
+	tasklet_init(&budget_ci->ir.msp430_irq_tasklet, msp430_ir_interrupt,
+		     (unsigned long) budget_ci);
+
+	SAA7146_IER_ENABLE(saa, MASK_06);
+	saa7146_setgpio(saa, 3, SAA7146_GPIO_IRQHI);
+
+	return 0;
+
+out2:
+	input_free_device(input_dev);
+out1:
+	return error;
+}
+
+static void msp430_ir_deinit(struct budget_ci *budget_ci)
+{
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+	struct input_dev *dev = budget_ci->ir.dev;
+
+	SAA7146_IER_DISABLE(saa, MASK_06);
+	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
+	tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
+
+	del_timer_sync(&dev->timer);
+	ir_input_nokey(dev, &budget_ci->ir.state);
+
+	input_unregister_device(dev);
+}
+
+static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
+				     DEBIADDR_ATTR | (address & 0xfff), 1, 1, 0);
+}
+
+static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
+				      DEBIADDR_ATTR | (address & 0xfff), 1, value, 1, 0);
+}
+
+static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return ttpci_budget_debiread(&budget_ci->budget, DEBICICAM,
+				     DEBIADDR_IO | (address & 3), 1, 1, 0);
+}
+
+static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	return ttpci_budget_debiwrite(&budget_ci->budget, DEBICICAM,
+				      DEBIADDR_IO | (address & 3), 1, value, 1, 0);
+}
+
+static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	if (budget_ci->ci_irq) {
+		// trigger on RISING edge during reset so we know when READY is re-asserted
+		saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
+	}
+	budget_ci->slot_status = SLOTSTATUS_RESET;
+	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
+	msleep(1);
+	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
+			       CICONTROL_RESET, 1, 0);
+
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
+	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+	return 0;
+}
+
+static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
+	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+	return 0;
+}
+
+static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+	int tmp;
+
+	if (slot != 0)
+		return -EINVAL;
+
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
+
+	tmp = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
+	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
+			       tmp | CICONTROL_ENABLETS, 1, 0);
+
+	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
+	return 0;
+}
+
+static void ciintf_interrupt(unsigned long data)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) data;
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+	unsigned int flags;
+
+	// ensure we don't get spurious IRQs during initialisation
+	if (!budget_ci->budget.ci_present)
+		return;
+
+	// read the CAM status
+	flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
+	if (flags & CICONTROL_CAMDETECT) {
+
+		// GPIO should be set to trigger on falling edge if a CAM is present
+		saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
+
+		if (budget_ci->slot_status & SLOTSTATUS_NONE) {
+			// CAM insertion IRQ
+			budget_ci->slot_status = SLOTSTATUS_PRESENT;
+			dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
+						     DVB_CA_EN50221_CAMCHANGE_INSERTED);
+
+		} else if (budget_ci->slot_status & SLOTSTATUS_RESET) {
+			// CAM ready (reset completed)
+			budget_ci->slot_status = SLOTSTATUS_READY;
+			dvb_ca_en50221_camready_irq(&budget_ci->ca, 0);
+
+		} else if (budget_ci->slot_status & SLOTSTATUS_READY) {
+			// FR/DA IRQ
+			dvb_ca_en50221_frda_irq(&budget_ci->ca, 0);
+		}
+	} else {
+
+		// trigger on rising edge if a CAM is not present - when a CAM is inserted, we
+		// only want to get the IRQ when it sets READY. If we trigger on the falling edge,
+		// the CAM might not actually be ready yet.
+		saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
+
+		// generate a CAM removal IRQ if we haven't already
+		if (budget_ci->slot_status & SLOTSTATUS_OCCUPIED) {
+			// CAM removal IRQ
+			budget_ci->slot_status = SLOTSTATUS_NONE;
+			dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0,
+						     DVB_CA_EN50221_CAMCHANGE_REMOVED);
+		}
+	}
+}
+
+static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) ca->data;
+	unsigned int flags;
+
+	// ensure we don't get spurious IRQs during initialisation
+	if (!budget_ci->budget.ci_present)
+		return -EINVAL;
+
+	// read the CAM status
+	flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
+	if (flags & CICONTROL_CAMDETECT) {
+		// mark it as present if it wasn't before
+		if (budget_ci->slot_status & SLOTSTATUS_NONE) {
+			budget_ci->slot_status = SLOTSTATUS_PRESENT;
+		}
+
+		// during a RESET, we check if we can read from IO memory to see when CAM is ready
+		if (budget_ci->slot_status & SLOTSTATUS_RESET) {
+			if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) {
+				budget_ci->slot_status = SLOTSTATUS_READY;
+			}
+		}
+	} else {
+		budget_ci->slot_status = SLOTSTATUS_NONE;
+	}
+
+	if (budget_ci->slot_status != SLOTSTATUS_NONE) {
+		if (budget_ci->slot_status & SLOTSTATUS_READY) {
+			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+		}
+		return DVB_CA_EN50221_POLL_CAM_PRESENT;
+	}
+
+	return 0;
+}
+
+static int ciintf_init(struct budget_ci *budget_ci)
+{
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+	int flags;
+	int result;
+	int ci_version;
+	int ca_flags;
+
+	memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221));
+
+	// enable DEBI pins
+	saa7146_write(saa, MC1, MASK_27 | MASK_11);
+
+	// test if it is there
+	ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0);
+	if ((ci_version & 0xa0) != 0xa0) {
+		result = -ENODEV;
+		goto error;
+	}
+
+	// determine whether a CAM is present or not
+	flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0);
+	budget_ci->slot_status = SLOTSTATUS_NONE;
+	if (flags & CICONTROL_CAMDETECT)
+		budget_ci->slot_status = SLOTSTATUS_PRESENT;
+
+	// version 0xa2 of the CI firmware doesn't generate interrupts
+	if (ci_version == 0xa2) {
+		ca_flags = 0;
+		budget_ci->ci_irq = 0;
+	} else {
+		ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
+				DVB_CA_EN50221_FLAG_IRQ_FR |
+				DVB_CA_EN50221_FLAG_IRQ_DA;
+		budget_ci->ci_irq = 1;
+	}
+
+	// register CI interface
+	budget_ci->ca.owner = THIS_MODULE;
+	budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem;
+	budget_ci->ca.write_attribute_mem = ciintf_write_attribute_mem;
+	budget_ci->ca.read_cam_control = ciintf_read_cam_control;
+	budget_ci->ca.write_cam_control = ciintf_write_cam_control;
+	budget_ci->ca.slot_reset = ciintf_slot_reset;
+	budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
+	budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
+	budget_ci->ca.poll_slot_status = ciintf_poll_slot_status;
+	budget_ci->ca.data = budget_ci;
+	if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
+					  &budget_ci->ca,
+					  ca_flags, 1)) != 0) {
+		printk("budget_ci: CI interface detected, but initialisation failed.\n");
+		goto error;
+	}
+
+	// Setup CI slot IRQ
+	if (budget_ci->ci_irq) {
+		tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci);
+		if (budget_ci->slot_status != SLOTSTATUS_NONE) {
+			saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO);
+		} else {
+			saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI);
+		}
+		SAA7146_IER_ENABLE(saa, MASK_03);
+	}
+
+	// enable interface
+	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
+			       CICONTROL_RESET, 1, 0);
+
+	// success!
+	printk("budget_ci: CI interface initialised\n");
+	budget_ci->budget.ci_present = 1;
+
+	// forge a fake CI IRQ so the CAM state is setup correctly
+	if (budget_ci->ci_irq) {
+		flags = DVB_CA_EN50221_CAMCHANGE_REMOVED;
+		if (budget_ci->slot_status != SLOTSTATUS_NONE)
+			flags = DVB_CA_EN50221_CAMCHANGE_INSERTED;
+		dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags);
+	}
+
+	return 0;
+
+error:
+	saa7146_write(saa, MC1, MASK_27);
+	return result;
+}
+
+static void ciintf_deinit(struct budget_ci *budget_ci)
+{
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+
+	// disable CI interrupts
+	if (budget_ci->ci_irq) {
+		SAA7146_IER_DISABLE(saa, MASK_03);
+		saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);
+		tasklet_kill(&budget_ci->ciintf_irq_tasklet);
+	}
+
+	// reset interface
+	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0);
+	msleep(1);
+	ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1,
+			       CICONTROL_RESET, 1, 0);
+
+	// disable TS data stream to CI interface
+	saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);
+
+	// release the CA device
+	dvb_ca_en50221_release(&budget_ci->ca);
+
+	// disable DEBI pins
+	saa7146_write(saa, MC1, MASK_27);
+}
+
+static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
+
+	dprintk(8, "dev: %p, budget_ci: %p\n", dev, budget_ci);
+
+	if (*isr & MASK_06)
+		tasklet_schedule(&budget_ci->ir.msp430_irq_tasklet);
+
+	if (*isr & MASK_10)
+		ttpci_budget_irq10_handler(dev, isr);
+
+	if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq))
+		tasklet_schedule(&budget_ci->ciintf_irq_tasklet);
+}
+
+static u8 philips_su1278_tt_inittab[] = {
+	0x01, 0x0f,
+	0x02, 0x30,
+	0x03, 0x00,
+	0x04, 0x5b,
+	0x05, 0x85,
+	0x06, 0x02,
+	0x07, 0x00,
+	0x08, 0x02,
+	0x09, 0x00,
+	0x0C, 0x01,
+	0x0D, 0x81,
+	0x0E, 0x44,
+	0x0f, 0x14,
+	0x10, 0x3c,
+	0x11, 0x84,
+	0x12, 0xda,
+	0x13, 0x97,
+	0x14, 0x95,
+	0x15, 0xc9,
+	0x16, 0x19,
+	0x17, 0x8c,
+	0x18, 0x59,
+	0x19, 0xf8,
+	0x1a, 0xfe,
+	0x1c, 0x7f,
+	0x1d, 0x00,
+	0x1e, 0x00,
+	0x1f, 0x50,
+	0x20, 0x00,
+	0x21, 0x00,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x28, 0x00,
+	0x29, 0x28,
+	0x2a, 0x14,
+	0x2b, 0x0f,
+	0x2c, 0x09,
+	0x2d, 0x09,
+	0x31, 0x1f,
+	0x32, 0x19,
+	0x33, 0xfc,
+	0x34, 0x93,
+	0xff, 0xff
+};
+
+static int philips_su1278_tt_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)
+{
+	stv0299_writereg(fe, 0x0e, 0x44);
+	if (srate >= 10000000) {
+		stv0299_writereg(fe, 0x13, 0x97);
+		stv0299_writereg(fe, 0x14, 0x95);
+		stv0299_writereg(fe, 0x15, 0xc9);
+		stv0299_writereg(fe, 0x17, 0x8c);
+		stv0299_writereg(fe, 0x1a, 0xfe);
+		stv0299_writereg(fe, 0x1c, 0x7f);
+		stv0299_writereg(fe, 0x2d, 0x09);
+	} else {
+		stv0299_writereg(fe, 0x13, 0x99);
+		stv0299_writereg(fe, 0x14, 0x8d);
+		stv0299_writereg(fe, 0x15, 0xce);
+		stv0299_writereg(fe, 0x17, 0x43);
+		stv0299_writereg(fe, 0x1a, 0x1d);
+		stv0299_writereg(fe, 0x1c, 0x12);
+		stv0299_writereg(fe, 0x2d, 0x05);
+	}
+	stv0299_writereg(fe, 0x0e, 0x23);
+	stv0299_writereg(fe, 0x0f, 0x94);
+	stv0299_writereg(fe, 0x10, 0x39);
+	stv0299_writereg(fe, 0x15, 0xc9);
+
+	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);
+	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);
+	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);
+
+	return 0;
+}
+
+static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
+					   struct dvb_frontend_parameters *params)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
+	u32 div;
+	u8 buf[4];
+	struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
+
+	if ((params->frequency < 950000) || (params->frequency > 2150000))
+		return -EINVAL;
+
+	div = (params->frequency + (500 - 1)) / 500;	// round correctly
+	buf[0] = (div >> 8) & 0x7f;
+	buf[1] = div & 0xff;
+	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 2;
+	buf[3] = 0x20;
+
+	if (params->u.qpsk.symbol_rate < 4000000)
+		buf[3] |= 1;
+
+	if (params->frequency < 1250000)
+		buf[3] |= 0;
+	else if (params->frequency < 1550000)
+		buf[3] |= 0x40;
+	else if (params->frequency < 2050000)
+		buf[3] |= 0x80;
+	else if (params->frequency < 2150000)
+		buf[3] |= 0xC0;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
+		return -EIO;
+	return 0;
+}
+
+static struct stv0299_config philips_su1278_tt_config = {
+
+	.demod_address = 0x68,
+	.inittab = philips_su1278_tt_inittab,
+	.mclk = 64000000UL,
+	.invert = 0,
+	.skip_reinit = 1,
+	.lock_output = STV0229_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 50,
+	.set_symbol_rate = philips_su1278_tt_set_symbol_rate,
+};
+
+
+
+static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
+	static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
+	static u8 disable_mc44BC374c[] = { 0x1d, 0x74, 0xa0, 0x68 };
+	struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = td1316_init,.len =
+			sizeof(td1316_init) };
+
+	// setup PLL configuration
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+		return -EIO;
+	msleep(1);
+
+	// disable the mc44BC374c (do not check for errors)
+	tuner_msg.addr = 0x65;
+	tuner_msg.buf = disable_mc44BC374c;
+	tuner_msg.len = sizeof(disable_mc44BC374c);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
+	}
+
+	return 0;
+}
+
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
+	u8 tuner_buf[4];
+	struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,.flags = 0,.buf = tuner_buf,.len = sizeof(tuner_buf) };
+	int tuner_frequency = 0;
+	u8 band, cp, filter;
+
+	// determine charge pump
+	tuner_frequency = params->frequency + 36130000;
+	if (tuner_frequency < 87000000)
+		return -EINVAL;
+	else if (tuner_frequency < 130000000)
+		cp = 3;
+	else if (tuner_frequency < 160000000)
+		cp = 5;
+	else if (tuner_frequency < 200000000)
+		cp = 6;
+	else if (tuner_frequency < 290000000)
+		cp = 3;
+	else if (tuner_frequency < 420000000)
+		cp = 5;
+	else if (tuner_frequency < 480000000)
+		cp = 6;
+	else if (tuner_frequency < 620000000)
+		cp = 3;
+	else if (tuner_frequency < 830000000)
+		cp = 5;
+	else if (tuner_frequency < 895000000)
+		cp = 7;
+	else
+		return -EINVAL;
+
+	// determine band
+	if (params->frequency < 49000000)
+		return -EINVAL;
+	else if (params->frequency < 159000000)
+		band = 1;
+	else if (params->frequency < 444000000)
+		band = 2;
+	else if (params->frequency < 861000000)
+		band = 4;
+	else
+		return -EINVAL;
+
+	// setup PLL filter and TDA9889
+	switch (params->u.ofdm.bandwidth) {
+	case BANDWIDTH_6_MHZ:
+		tda1004x_writereg(fe, 0x0C, 0x14);
+		filter = 0;
+		break;
+
+	case BANDWIDTH_7_MHZ:
+		tda1004x_writereg(fe, 0x0C, 0x80);
+		filter = 0;
+		break;
+
+	case BANDWIDTH_8_MHZ:
+		tda1004x_writereg(fe, 0x0C, 0x14);
+		filter = 1;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	// calculate divisor
+	// ((36130000+((1000000/6)/2)) + Finput)/(1000000/6)
+	tuner_frequency = (((params->frequency / 1000) * 6) + 217280) / 1000;
+
+	// setup tuner buffer
+	tuner_buf[0] = tuner_frequency >> 8;
+	tuner_buf[1] = tuner_frequency & 0xff;
+	tuner_buf[2] = 0xca;
+	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+		return -EIO;
+
+	msleep(1);
+	return 0;
+}
+
+static int philips_tdm1316l_request_firmware(struct dvb_frontend *fe,
+					     const struct firmware **fw, char *name)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
+
+	return request_firmware(fw, name, &budget_ci->budget.dev->pci->dev);
+}
+
+static struct tda1004x_config philips_tdm1316l_config = {
+
+	.demod_address = 0x8,
+	.invert = 0,
+	.invert_oclk = 0,
+	.xtal_freq = TDA10046_XTAL_4M,
+	.agc_config = TDA10046_AGC_DEFAULT,
+	.if_freq = TDA10046_FREQ_3617,
+	.request_firmware = philips_tdm1316l_request_firmware,
+};
+
+static struct tda1004x_config philips_tdm1316l_config_invert = {
+
+	.demod_address = 0x8,
+	.invert = 1,
+	.invert_oclk = 0,
+	.xtal_freq = TDA10046_XTAL_4M,
+	.agc_config = TDA10046_AGC_DEFAULT,
+	.if_freq = TDA10046_FREQ_3617,
+	.request_firmware = philips_tdm1316l_request_firmware,
+};
+
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
+	u8 tuner_buf[5];
+	struct i2c_msg tuner_msg = {.addr = budget_ci->tuner_pll_address,
+				    .flags = 0,
+				    .buf = tuner_buf,
+				    .len = sizeof(tuner_buf) };
+	int tuner_frequency = 0;
+	u8 band, cp, filter;
+
+	// determine charge pump
+	tuner_frequency = params->frequency + 36125000;
+	if (tuner_frequency < 87000000)
+		return -EINVAL;
+	else if (tuner_frequency < 130000000) {
+		cp = 3;
+		band = 1;
+	} else if (tuner_frequency < 160000000) {
+		cp = 5;
+		band = 1;
+	} else if (tuner_frequency < 200000000) {
+		cp = 6;
+		band = 1;
+	} else if (tuner_frequency < 290000000) {
+		cp = 3;
+		band = 2;
+	} else if (tuner_frequency < 420000000) {
+		cp = 5;
+		band = 2;
+	} else if (tuner_frequency < 480000000) {
+		cp = 6;
+		band = 2;
+	} else if (tuner_frequency < 620000000) {
+		cp = 3;
+		band = 4;
+	} else if (tuner_frequency < 830000000) {
+		cp = 5;
+		band = 4;
+	} else if (tuner_frequency < 895000000) {
+		cp = 7;
+		band = 4;
+	} else
+		return -EINVAL;
+
+	// assume PLL filter should always be 8MHz for the moment.
+	filter = 1;
+
+	// calculate divisor
+	tuner_frequency = (params->frequency + 36125000 + (62500/2)) / 62500;
+
+	// setup tuner buffer
+	tuner_buf[0] = tuner_frequency >> 8;
+	tuner_buf[1] = tuner_frequency & 0xff;
+	tuner_buf[2] = 0xc8;
+	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+	tuner_buf[4] = 0x80;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+		return -EIO;
+
+	msleep(50);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
+		return -EIO;
+
+	msleep(1);
+
+	return 0;
+}
+
+static u8 dvbc_philips_tdm1316l_inittab[] = {
+	0x80, 0x01,
+	0x80, 0x00,
+	0x81, 0x01,
+	0x81, 0x00,
+	0x00, 0x09,
+	0x01, 0x69,
+	0x03, 0x00,
+	0x04, 0x00,
+	0x07, 0x00,
+	0x08, 0x00,
+	0x20, 0x00,
+	0x21, 0x40,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x24, 0x40,
+	0x25, 0x88,
+	0x30, 0xff,
+	0x31, 0x00,
+	0x32, 0xff,
+	0x33, 0x00,
+	0x34, 0x50,
+	0x35, 0x7f,
+	0x36, 0x00,
+	0x37, 0x20,
+	0x38, 0x00,
+	0x40, 0x1c,
+	0x41, 0xff,
+	0x42, 0x29,
+	0x43, 0x20,
+	0x44, 0xff,
+	0x45, 0x00,
+	0x46, 0x00,
+	0x49, 0x04,
+	0x4a, 0x00,
+	0x4b, 0x7b,
+	0x52, 0x30,
+	0x55, 0xae,
+	0x56, 0x47,
+	0x57, 0xe1,
+	0x58, 0x3a,
+	0x5a, 0x1e,
+	0x5b, 0x34,
+	0x60, 0x00,
+	0x63, 0x00,
+	0x64, 0x00,
+	0x65, 0x00,
+	0x66, 0x00,
+	0x67, 0x00,
+	0x68, 0x00,
+	0x69, 0x00,
+	0x6a, 0x02,
+	0x6b, 0x00,
+	0x70, 0xff,
+	0x71, 0x00,
+	0x72, 0x00,
+	0x73, 0x00,
+	0x74, 0x0c,
+	0x80, 0x00,
+	0x81, 0x00,
+	0x82, 0x00,
+	0x83, 0x00,
+	0x84, 0x04,
+	0x85, 0x80,
+	0x86, 0x24,
+	0x87, 0x78,
+	0x88, 0x10,
+	0x89, 0x00,
+	0x90, 0x01,
+	0x91, 0x01,
+	0xa0, 0x04,
+	0xa1, 0x00,
+	0xa2, 0x00,
+	0xb0, 0x91,
+	0xb1, 0x0b,
+	0xc0, 0x53,
+	0xc1, 0x70,
+	0xc2, 0x12,
+	0xd0, 0x00,
+	0xd1, 0x00,
+	0xd2, 0x00,
+	0xd3, 0x00,
+	0xd4, 0x00,
+	0xd5, 0x00,
+	0xde, 0x00,
+	0xdf, 0x00,
+	0x61, 0x38,
+	0x62, 0x0a,
+	0x53, 0x13,
+	0x59, 0x08,
+	0xff, 0xff,
+};
+
+static struct stv0297_config dvbc_philips_tdm1316l_config = {
+	.demod_address = 0x1c,
+	.inittab = dvbc_philips_tdm1316l_inittab,
+	.invert = 0,
+	.stop_during_read = 1,
+};
+
+
+
+
+static void frontend_init(struct budget_ci *budget_ci)
+{
+	switch (budget_ci->budget.dev->pci->subsystem_device) {
+	case 0x100c:		// Hauppauge/TT Nova-CI budget (stv0299/ALPS BSRU6(tsa5059))
+		budget_ci->budget.dvb_frontend =
+			dvb_attach(stv0299_attach, &alps_bsru6_config, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+			budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
+			break;
+		}
+		break;
+
+	case 0x100f:		// Hauppauge/TT Nova-CI budget (stv0299b/Philips su1278(tsa5059))
+		budget_ci->budget.dvb_frontend =
+			dvb_attach(stv0299_attach, &philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
+			break;
+		}
+		break;
+
+	case 0x1010:		// TT DVB-C CI budget (stv0297/Philips tdm1316l(tda6651tt))
+		budget_ci->tuner_pll_address = 0x61;
+		budget_ci->budget.dvb_frontend =
+			dvb_attach(stv0297_attach, &dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
+			break;
+		}
+		break;
+
+	case 0x1011:		// Hauppauge/TT Nova-T budget (tda10045/Philips tdm1316l(tda6651tt) + TDA9889)
+		budget_ci->tuner_pll_address = 0x63;
+		budget_ci->budget.dvb_frontend =
+			dvb_attach(tda10045_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
+			break;
+		}
+		break;
+
+	case 0x1012:		// TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt))
+		budget_ci->tuner_pll_address = 0x60;
+		budget_ci->budget.dvb_frontend =
+			dvb_attach(tda10046_attach, &philips_tdm1316l_config_invert, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
+			break;
+		}
+		break;
+
+	case 0x1017:		// TT S-1500 PCI
+		budget_ci->budget.dvb_frontend = dvb_attach(stv0299_attach, &alps_bsbe1_config, &budget_ci->budget.i2c_adap);
+		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+			budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
+
+			budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+			if (dvb_attach(lnbp21_attach, budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0) == NULL) {
+				printk("%s: No LNBP21 found!\n", __FUNCTION__);
+				dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+				budget_ci->budget.dvb_frontend = NULL;
+			}
+		}
+
+		break;
+	}
+
+	if (budget_ci->budget.dvb_frontend == NULL) {
+		printk("budget-ci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
+		       budget_ci->budget.dev->pci->vendor,
+		       budget_ci->budget.dev->pci->device,
+		       budget_ci->budget.dev->pci->subsystem_vendor,
+		       budget_ci->budget.dev->pci->subsystem_device);
+	} else {
+		if (dvb_register_frontend
+		    (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
+			printk("budget-ci: Frontend registration failed!\n");
+			dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+			budget_ci->budget.dvb_frontend = NULL;
+		}
+	}
+}
+
+static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
+{
+	struct budget_ci *budget_ci;
+	int err;
+
+	budget_ci = kzalloc(sizeof(struct budget_ci), GFP_KERNEL);
+	if (!budget_ci) {
+		err = -ENOMEM;
+		goto out1;
+	}
+
+	dprintk(2, "budget_ci: %p\n", budget_ci);
+
+	dev->ext_priv = budget_ci;
+
+	err = ttpci_budget_init(&budget_ci->budget, dev, info, THIS_MODULE);
+	if (err)
+		goto out2;
+
+	err = msp430_ir_init(budget_ci);
+	if (err)
+		goto out3;
+
+	ciintf_init(budget_ci);
+
+	budget_ci->budget.dvb_adapter.priv = budget_ci;
+	frontend_init(budget_ci);
+
+	ttpci_budget_init_hooks(&budget_ci->budget);
+
+	return 0;
+
+out3:
+	ttpci_budget_deinit(&budget_ci->budget);
+out2:
+	kfree(budget_ci);
+out1:
+	return err;
+}
+
+static int budget_ci_detach(struct saa7146_dev *dev)
+{
+	struct budget_ci *budget_ci = (struct budget_ci *) dev->ext_priv;
+	struct saa7146_dev *saa = budget_ci->budget.dev;
+	int err;
+
+	if (budget_ci->budget.ci_present)
+		ciintf_deinit(budget_ci);
+	msp430_ir_deinit(budget_ci);
+	if (budget_ci->budget.dvb_frontend) {
+		dvb_unregister_frontend(budget_ci->budget.dvb_frontend);
+		dvb_frontend_detach(budget_ci->budget.dvb_frontend);
+	}
+	err = ttpci_budget_deinit(&budget_ci->budget);
+
+	// disable frontend and CI interface
+	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);
+
+	kfree(budget_ci);
+
+	return err;
+}
+
+static struct saa7146_extension budget_extension;
+
+MAKE_BUDGET_INFO(ttbs2, "TT-Budget/S-1500 PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC);
+MAKE_BUDGET_INFO(ttbt2, "TT-Budget/WinTV-NOVA-T	 PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbtci, "TT-Budget-T-CI PCI", BUDGET_TT);
+MAKE_BUDGET_INFO(ttbcci, "TT-Budget-C-CI PCI", BUDGET_TT);
+
+static struct pci_device_id pci_tbl[] = {
+	MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c),
+	MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f),
+	MAKE_EXTENSION_PCI(ttbcci, 0x13c2, 0x1010),
+	MAKE_EXTENSION_PCI(ttbt2, 0x13c2, 0x1011),
+	MAKE_EXTENSION_PCI(ttbtci, 0x13c2, 0x1012),
+	MAKE_EXTENSION_PCI(ttbs2, 0x13c2, 0x1017),
+	{
+	 .vendor = 0,
+	 }
+};
+
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+static struct saa7146_extension budget_extension = {
+	.name = "budget_ci dvb",
+	.flags = SAA7146_USE_I2C_IRQ,
+
+	.module = THIS_MODULE,
+	.pci_tbl = &pci_tbl[0],
+	.attach = budget_ci_attach,
+	.detach = budget_ci_detach,
+
+	.irq_mask = MASK_03 | MASK_06 | MASK_10,
+	.irq_func = budget_ci_irq,
+};
+
+static int __init budget_ci_init(void)
+{
+	return saa7146_register_extension(&budget_extension);
+}
+
+static void __exit budget_ci_exit(void)
+{
+	saa7146_unregister_extension(&budget_extension);
+}
+
+module_init(budget_ci_init);
+module_exit(budget_ci_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Hunold, Jack Thomasson, Andrew de Quincey, others");
+MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
+		   "budget PCI DVB cards w/ CI-module produced by "
+		   "Siemens, Technotrend, Hauppauge");
diff -urNp linux-2.6.22.1/drivers/media/dvb/ttpci/budget.h linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget.h
--- linux-2.6.22.1/drivers/media/dvb/ttpci/budget.h	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget.h	2007-07-28 01:17:12.000000000 +0200
@@ -102,6 +102,8 @@ static struct saa7146_pci_extension_data
 #define BUDGET_CIN1200C_MK3	   15
 #define BUDGET_KNC1C_MK3	   16
 #define BUDGET_KNC1CP_MK3	   17
+#define BUDGET_KNC1S2		   18
+#define BUDGET_TT3200		   19
 
 #define BUDGET_VIDEO_PORTA         0
 #define BUDGET_VIDEO_PORTB         1
diff -urNp linux-2.6.22.1/drivers/media/dvb/ttpci/budget.h.orig linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget.h.orig
--- linux-2.6.22.1/drivers/media/dvb/ttpci/budget.h.orig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/ttpci/budget.h.orig	2007-07-10 20:56:30.000000000 +0200
@@ -0,0 +1,121 @@
+#ifndef __BUDGET_DVB__
+#define __BUDGET_DVB__
+
+#include "dvb_frontend.h"
+#include "dvbdev.h"
+#include "demux.h"
+#include "dvb_demux.h"
+#include "dmxdev.h"
+#include "dvb_filter.h"
+#include "dvb_net.h"
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+#include <media/saa7146.h>
+
+extern int budget_debug;
+
+#ifdef dprintk
+#undef dprintk
+#endif
+
+#define dprintk(level,args...) \
+	    do { if ((budget_debug & level)) { printk("%s: %s(): ", KBUILD_MODNAME, __FUNCTION__); printk(args); } } while (0)
+
+struct budget_info {
+	char *name;
+	int type;
+};
+
+/* place to store all the necessary device information */
+struct budget {
+
+	/* devices */
+	struct dvb_device dvb_dev;
+	struct dvb_net dvb_net;
+
+	struct saa7146_dev *dev;
+
+	struct i2c_adapter i2c_adap;
+	struct budget_info *card;
+
+	unsigned char *grabbing;
+	struct saa7146_pgtable pt;
+
+	struct tasklet_struct fidb_tasklet;
+	struct tasklet_struct vpe_tasklet;
+
+	struct dmxdev dmxdev;
+	struct dvb_demux demux;
+
+	struct dmx_frontend hw_frontend;
+	struct dmx_frontend mem_frontend;
+
+	int ci_present;
+	int video_port;
+
+	u32 buffer_width;
+	u32 buffer_height;
+	u32 buffer_size;
+	u32 buffer_warning_threshold;
+	u32 buffer_warnings;
+	unsigned long buffer_warning_time;
+
+	u32 ttbp;
+	int feeding;
+
+	spinlock_t feedlock;
+
+	spinlock_t debilock;
+
+	struct dvb_adapter dvb_adapter;
+	struct dvb_frontend *dvb_frontend;
+	int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status);
+	int fe_synced;
+
+	void *priv;
+};
+
+#define MAKE_BUDGET_INFO(x_var,x_name,x_type) \
+static struct budget_info x_var ## _info = { \
+	.name=x_name,	\
+	.type=x_type };	\
+static struct saa7146_pci_extension_data x_var = { \
+	.ext_priv = &x_var ## _info, \
+	.ext = &budget_extension };
+
+#define BUDGET_TT		   0
+#define BUDGET_TT_HW_DISEQC	   1
+#define BUDGET_PATCH		   3
+#define BUDGET_FS_ACTIVY	   4
+#define BUDGET_CIN1200S		   5
+#define BUDGET_CIN1200C		   6
+#define BUDGET_CIN1200T		   7
+#define BUDGET_KNC1S		   8
+#define BUDGET_KNC1C		   9
+#define BUDGET_KNC1T		   10
+#define BUDGET_KNC1SP		   11
+#define BUDGET_KNC1CP		   12
+#define BUDGET_KNC1TP		   13
+#define BUDGET_TVSTAR		   14
+#define BUDGET_CIN1200C_MK3	   15
+#define BUDGET_KNC1C_MK3	   16
+#define BUDGET_KNC1CP_MK3	   17
+
+#define BUDGET_VIDEO_PORTA         0
+#define BUDGET_VIDEO_PORTB         1
+
+extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
+			     struct saa7146_pci_extension_data *info,
+			     struct module *owner);
+extern void ttpci_budget_init_hooks(struct budget *budget);
+extern int ttpci_budget_deinit(struct budget *budget);
+extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr);
+extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port);
+extern int ttpci_budget_debiread(struct budget *budget, u32 config, int addr, int count,
+				 int uselocks, int nobusyloop);
+extern int ttpci_budget_debiwrite(struct budget *budget, u32 config, int addr, int count, u32 value,
+				  int uselocks, int nobusyloop);
+
+#endif
diff -urNp linux-2.6.22.1/drivers/media/dvb/ttpci/Kconfig linux-2.6.22.1-new/drivers/media/dvb/ttpci/Kconfig
--- linux-2.6.22.1/drivers/media/dvb/ttpci/Kconfig	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/drivers/media/dvb/ttpci/Kconfig	2007-07-28 01:17:12.000000000 +0200
@@ -110,6 +110,7 @@ config DVB_BUDGET_AV
 	select VIDEO_SAA7146_VV
 	select DVB_PLL
 	select DVB_STV0299 if !DVB_FE_CUSTOMISE
+	select DVB_STB0899 if !DVB_FE_CUSTOMISE
 	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
 	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
 	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
diff -urNp linux-2.6.22.1/drivers/media/dvb/ttpci/Kconfig.orig linux-2.6.22.1-new/drivers/media/dvb/ttpci/Kconfig.orig
--- linux-2.6.22.1/drivers/media/dvb/ttpci/Kconfig.orig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.22.1-new/drivers/media/dvb/ttpci/Kconfig.orig	2007-07-10 20:56:30.000000000 +0200
@@ -0,0 +1,148 @@
+config DVB_AV7110
+	tristate "AV7110 cards"
+	depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
+	select FW_LOADER if !DVB_AV7110_FIRMWARE
+	select VIDEO_SAA7146_VV
+	select DVB_VES1820 if !DVB_FE_CUSTOMISE
+	select DVB_VES1X93 if !DVB_FE_CUSTOMISE
+	select DVB_STV0299 if !DVB_FE_CUSTOMISE
+	select DVB_TDA8083 if !DVB_FE_CUSTOMISE
+	select DVB_SP8870 if !DVB_FE_CUSTOMISE
+	select DVB_STV0297 if !DVB_FE_CUSTOMISE
+	select DVB_L64781 if !DVB_FE_CUSTOMISE
+	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+	help
+	  Support for SAA7146 and AV7110 based DVB cards as produced
+	  by Fujitsu-Siemens, Technotrend, Hauppauge and others.
+
+	  This driver only supports the fullfeatured cards with
+	  onboard MPEG2 decoder.
+
+	  This driver needs an external firmware. Please use the script
+	  "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
+	  download/extract it, and then copy it to /usr/lib/hotplug/firmware
+	  or /lib/firmware (depending on configuration of firmware hotplug).
+
+	  Say Y if you own such a card and want to use it.
+
+config DVB_AV7110_FIRMWARE
+	bool "Compile AV7110 firmware into the driver"
+	depends on DVB_AV7110 && !STANDALONE
+	default y if DVB_AV7110=y
+	help
+	  The AV7110 firmware is normally loaded by the firmware hotplug manager.
+	  If you want to compile the firmware into the driver you need to say
+	  Y here and provide the correct path of the firmware. You need this
+	  option if you want to compile the whole driver statically into the
+	  kernel.
+
+	  All other people say N.
+
+config DVB_AV7110_FIRMWARE_FILE
+	string "Full pathname of av7110 firmware file"
+	depends on DVB_AV7110_FIRMWARE
+	default "/usr/lib/hotplug/firmware/dvb-ttpci-01.fw"
+
+config DVB_AV7110_OSD
+	bool "AV7110 OSD support"
+	depends on DVB_AV7110
+	default y if DVB_AV7110=y || DVB_AV7110=m
+	help
+	  The AV7110 firmware provides some code to generate an OnScreenDisplay
+	  on the video output. This is kind of nonstandard and not guaranteed to
+	  be maintained.
+
+	  Anyway, some popular DVB software like VDR uses this OSD to render
+	  its menus, so say Y if you want to use this software.
+
+	  All other people say N.
+
+config DVB_BUDGET
+	tristate "Budget cards"
+	depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
+	select VIDEO_SAA7146
+	select DVB_STV0299 if !DVB_FE_CUSTOMISE
+	select DVB_VES1X93 if !DVB_FE_CUSTOMISE
+	select DVB_VES1820 if !DVB_FE_CUSTOMISE
+	select DVB_L64781 if !DVB_FE_CUSTOMISE
+	select DVB_TDA8083 if !DVB_FE_CUSTOMISE
+	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
+	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+	select DVB_S5H1420 if !DVB_FE_CUSTOMISE
+	select DVB_TDA10086 if !DVB_FE_CUSTOMISE
+	select DVB_TDA826X if !DVB_FE_CUSTOMISE
+	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+	help
+	  Support for simple SAA7146 based DVB cards
+	  (so called Budget- or Nova-PCI cards) without onboard
+	  MPEG2 decoder.
+
+	  Say Y if you own such a card and want to use it.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called budget.
+
+config DVB_BUDGET_CI
+	tristate "Budget cards with onboard CI connector"
+	depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
+	select VIDEO_SAA7146
+	select DVB_STV0297 if !DVB_FE_CUSTOMISE
+	select DVB_STV0299 if !DVB_FE_CUSTOMISE
+	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+	select VIDEO_IR
+	help
+	  Support for simple SAA7146 based DVB cards
+	  (so called Budget- or Nova-PCI cards) without onboard
+	  MPEG2 decoder, but with onboard Common Interface connector.
+
+	  Note: The Common Interface is not yet supported by this driver
+	  due to lack of information from the vendor.
+
+	  Say Y if you own such a card and want to use it.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called budget-ci.
+
+config DVB_BUDGET_AV
+	tristate "Budget cards with analog video inputs"
+	depends on DVB_CORE && PCI && I2C && VIDEO_V4L1
+	select VIDEO_SAA7146_VV
+	select DVB_PLL
+	select DVB_STV0299 if !DVB_FE_CUSTOMISE
+	select DVB_TDA1004X if !DVB_FE_CUSTOMISE
+	select DVB_TDA10021 if !DVB_FE_CUSTOMISE
+	select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+	select DVB_TUA6100 if !DVB_FE_CUSTOMISE
+	select FW_LOADER
+	help
+	  Support for simple SAA7146 based DVB cards
+	  (so called Budget- or Nova-PCI cards) without onboard
+	  MPEG2 decoder, but with one or more analog video inputs.
+
+	  Say Y if you own such a card and want to use it.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called budget-av.
+
+config DVB_BUDGET_PATCH
+	tristate "AV7110 cards with Budget Patch"
+	depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1
+	select DVB_AV7110
+	select DVB_STV0299 if !DVB_FE_CUSTOMISE
+	select DVB_VES1X93 if !DVB_FE_CUSTOMISE
+	select DVB_TDA8083 if !DVB_FE_CUSTOMISE
+	help
+	  Support for Budget Patch (full TS) modification on
+	  SAA7146+AV7110 based cards (DVB-S cards). This
+	  driver doesn't use onboard MPEG2 decoder. The
+	  card is driven in Budget-only mode. Card is
+	  required to have loaded firmware to tune properly.
+	  Firmware can be loaded by insertion and removal of
+	  standard AV7110 driver prior to loading this
+	  driver.
+
+	  Say Y if you own such a card and want to use it.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called budget-patch.
diff -urNp linux-2.6.22.1/include/linux/dvb/frontend.h linux-2.6.22.1-new/include/linux/dvb/frontend.h
--- linux-2.6.22.1/include/linux/dvb/frontend.h	2007-07-10 20:56:30.000000000 +0200
+++ linux-2.6.22.1-new/include/linux/dvb/frontend.h	2007-07-28 01:17:12.000000000 +0200
@@ -7,6 +7,8 @@
  *		    Andre Draszik <ad@convergence.de>
  *		    for convergence integrated media GmbH
  *
+ * Copyright (C) 2006, 2007 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 Lesser General Public License
  * as published by the Free Software Foundation; either version 2.1
@@ -234,12 +236,6 @@ struct dvb_frontend_parameters {
 };
 
 
-struct dvb_frontend_event {
-	fe_status_t status;
-	struct dvb_frontend_parameters parameters;
-};
-
-
 /**
  * When set, this flag will disable any zigzagging or other "normal" tuning
  * behaviour. Additionally, there will be no automatic monitoring of the lock
@@ -270,8 +266,384 @@ struct dvb_frontend_event {
 #define FE_SET_FRONTEND		   _IOW('o', 76, struct dvb_frontend_parameters)
 #define FE_GET_FRONTEND		   _IOR('o', 77, struct dvb_frontend_parameters)
 #define FE_SET_FRONTEND_TUNE_MODE  _IO('o', 81) /* unsigned int */
-#define FE_GET_EVENT		   _IOR('o', 78, struct dvb_frontend_event)
 
 #define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
 
+/*
+ * References:
+ * DVB-S : EN 300 421
+ * DVB-S2: EN 302 307, TR 102 376, EN 301 210
+ * DVB-C : EN 300 429
+ * DVB-T : EN 300 744
+ * DVB-H : EN 300 304
+ * ATSC  : A/53A
+ */
+
+/*
+ * Delivery Systems
+ * needs to set/queried for multistandard frontends
+ */
+enum dvbfe_delsys {
+	DVBFE_DELSYS_DVBS		= (1 <<  0),
+	DVBFE_DELSYS_DSS		= (1 <<  1),
+	DVBFE_DELSYS_DVBS2		= (1 <<  2),
+	DVBFE_DELSYS_DVBC		= (1 <<  3),
+	DVBFE_DELSYS_DVBT		= (1 <<  4),
+	DVBFE_DELSYS_DVBH		= (1 <<  5),
+	DVBFE_DELSYS_ATSC		= (1 <<  6),
+	DVBFE_DELSYS_DUMMY		= (1 << 31)
+};
+#define DVBFE_GET_DELSYS		_IOR('o', 82, enum dvbfe_delsys)
+
+/* Modulation types			*/
+enum dvbfe_modulation {
+	DVBFE_MOD_NONE			= (0 <<  0),
+	DVBFE_MOD_BPSK			= (1 <<  0),
+	DVBFE_MOD_QPSK			= (1 <<  1),
+	DVBFE_MOD_OQPSK			= (1 <<  2),
+	DVBFE_MOD_8PSK			= (1 <<  3),
+	DVBFE_MOD_16APSK		= (1 <<  4),
+	DVBFE_MOD_32APSK		= (1 <<  5),
+	DVBFE_MOD_QAM4			= (1 <<  6),
+	DVBFE_MOD_QAM16			= (1 <<  7),
+	DVBFE_MOD_QAM32			= (1 <<  8),
+	DVBFE_MOD_QAM64			= (1 <<  9),
+	DVBFE_MOD_QAM128		= (1 << 10),
+	DVBFE_MOD_QAM256		= (1 << 11),
+	DVBFE_MOD_QAM512		= (1 << 12),
+	DVBFE_MOD_QAM1024		= (1 << 13),
+	DVBFE_MOD_QAMAUTO		= (1 << 14),
+	DVBFE_MOD_OFDM			= (1 << 15),
+	DVBFE_MOD_COFDM			= (1 << 16),
+	DVBFE_MOD_VSB8			= (1 << 17),
+	DVBFE_MOD_VSB16			= (1 << 18),
+	DVBFE_MOD_AUTO			= (1 << 31)
+};
+
+/*
+ * Convolution Code Rate (Viterbi Inner Code Rate)
+ * DVB-S2 uses LDPC. Information on LDPC can be found at
+ * http://www.ldpc-codes.com
+ */
+enum dvbfe_fec {
+	DVBFE_FEC_NONE			= (0 <<  0),
+	DVBFE_FEC_1_4			= (1 <<  0),
+	DVBFE_FEC_1_3			= (1 <<  1),
+	DVBFE_FEC_2_5			= (1 <<  2),
+	DVBFE_FEC_1_2			= (1 <<  3),
+	DVBFE_FEC_3_5			= (1 <<  4),
+	DVBFE_FEC_2_3			= (1 <<  5),
+	DVBFE_FEC_3_4			= (1 <<  6),
+	DVBFE_FEC_4_5			= (1 <<  7),
+	DVBFE_FEC_5_6			= (1 <<  8),
+	DVBFE_FEC_6_7			= (1 <<  9),
+	DVBFE_FEC_7_8			= (1 << 10),
+	DVBFE_FEC_8_9			= (1 << 11),
+	DVBFE_FEC_9_10			= (1 << 12),
+	DVBFE_FEC_AUTO			= (1 << 31)
+};
+
+/* Frontend Inversion (I/Q Swap)	*/
+enum dvbfe_inversion {
+	DVBFE_INVERSION_OFF		= 0,
+	DVBFE_INVERSION_ON		= 1,
+	DVBFE_INVERSION_AUTO		= 2
+};
+
+/* DVB-S parameters			*/
+struct dvbs_params {
+	__u32				symbol_rate;
+
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_fec			fec;
+};
+
+/* DSS parameters			*/
+struct dss_params {
+	__u32				symbol_rate;
+
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_fec			fec;
+};
+
+/*
+ * Rolloff Rate (Nyquist Filter Rolloff)
+ * NOTE: DVB-S2 has rates of 0.20, 0.25, 0.35
+ * Values are x100
+ * Applies to DVB-S2
+ */
+enum dvbfe_rolloff {
+	DVBFE_ROLLOFF_35		= 0,
+	DVBFE_ROLLOFF_25		= 1,
+	DVBFE_ROLLOFF_20		= 2,
+	DVBFE_ROLLOFF_UNKNOWN		= 3
+};
+
+/* DVB-S2 parameters			*/
+struct dvbs2_params {
+	__u32				symbol_rate;
+
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_fec			fec;
+
+	/* Informational fields only	*/
+	enum dvbfe_rolloff		rolloff;
+
+	__u8				matype_1;
+	__u8				matype_2;
+	__u8				upl_1;
+	__u8				upl_2;
+	__u8				dfl_1;
+	__u8				dfl_2;
+	__u8				sync;
+	__u8				syncd_1;
+	__u8				syncd_2;
+
+	__u8				pad[32];
+};
+
+/* DVB-C parameters			*/
+struct dvbc_params {
+	__u32				symbol_rate;
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_fec			fec;
+};
+
+/* DVB-T Channel bandwidth		*/
+enum dvbfe_bandwidth {
+	DVBFE_BANDWIDTH_8_MHZ		= (1 <<  0),
+	DVBFE_BANDWIDTH_7_MHZ		= (1 <<  1),
+	DVBFE_BANDWIDTH_6_MHZ		= (1 <<  2),
+	DVBFE_BANDWIDTH_5_MHZ		= (1 <<  3),
+	DVBFE_BANDWIDTH_AUTO		= (1 << 31)
+};
+
+/* DVB-T/DVB-H transmission mode	*/
+enum dvbfe_transmission_mode {
+	DVBFE_TRANSMISSION_MODE_2K	= (1 <<  0),
+	DVBFE_TRANSMISSION_MODE_4K	= (1 <<  1),
+	DVBFE_TRANSMISSION_MODE_8K	= (1 <<  2),
+	DVBFE_TRANSMISSION_MODE_AUTO	= (1 << 31)
+};
+
+/* DVB-T/DVB-H Guard interval		*/
+enum dvbfe_guard_interval {
+	DVBFE_GUARD_INTERVAL_1_32	= (1 <<  1),
+	DVBFE_GUARD_INTERVAL_1_16	= (1 <<  2),
+	DVBFE_GUARD_INTERVAL_1_8	= (1 <<  3),
+	DVBFE_GUARD_INTERVAL_1_4	= (1 <<  4),
+	DVBFE_GUARD_INTERVAL_AUTO	= (1 << 31)
+};
+
+/* DVB-T/DVB-H Hierarchial modulation	*/
+enum dvbfe_hierarchy {
+	DVBFE_HIERARCHY_OFF		= (1 <<  0),
+	DVBFE_HIERARCHY_ON		= (1 <<  1),
+	DVBFE_HIERARCHY_AUTO		= (1 <<  2)
+};
+
+/* DVB-T/DVB-H Rolloff's		*/
+enum dvbfe_alpha {
+	DVBFE_ALPHA_1			= (1 <<  0),
+	DVBFE_ALPHA_2			= (1 <<  1),
+	DVBFE_ALPHA_4			= (1 <<  2)
+};
+
+/* Stream priority (Hierachial coding)	*/
+enum dvbfe_stream_priority {
+	DVBFE_STREAM_PRIORITY_HP	= (0 << 0),
+	DVBFE_STREAM_PRIORITY_LP	= (1 << 0)
+};
+
+/* DVB-T parameters			*/
+struct dvbt_params {
+	enum dvbfe_modulation		constellation;
+	enum dvbfe_bandwidth		bandwidth;
+	enum dvbfe_fec			code_rate_HP;
+	enum dvbfe_fec			code_rate_LP;
+	enum dvbfe_transmission_mode	transmission_mode;
+	enum dvbfe_guard_interval	guard_interval;
+	enum dvbfe_hierarchy		hierarchy;
+	enum dvbfe_alpha		alpha;
+	enum dvbfe_stream_priority	priority;
+
+	__u8				pad[32];
+};
+
+/* DVB-H Interleaver type		*/
+enum dvbfe_interleaver {
+	DVBFE_INTERLEAVER_NATIVE	= (1 <<  0),
+	DVBFE_INTERLEAVER_INDEPTH	= (1 <<  1),
+	DVBFE_INTERLEAVER_AUTO		= (1 << 31)
+};
+
+/* DVB-H MPE-FEC Indicator		*/
+enum dvbfe_mpefec {
+	DVBFE_MPEFEC_OFF		= (1 <<  0),
+	DVBFE_MPEFEC_ON			= (1 <<  1)
+};
+
+/* DVB-H Timeslicing Indicator		*/
+enum dvbfe_timeslicing {
+	DVBFE_TIMESLICING_OFF		= (1 <<  0),
+	DVBFE_TIMESLICING_ON		= (1 <<  1)
+};
+
+/* DVB-H parameters			*/
+struct dvbh_params {
+	enum dvbfe_modulation		constellation;
+	enum dvbfe_fec			code_rate_HP;
+	enum dvbfe_fec			code_rate_LP;
+	enum dvbfe_transmission_mode	transmission_mode;
+	enum dvbfe_guard_interval	guard_interval;
+	enum dvbfe_hierarchy		hierarchy;
+	enum dvbfe_alpha		alpha;
+	enum dvbfe_interleaver		interleaver;
+	enum dvbfe_mpefec		mpefec;
+	enum dvbfe_timeslicing		timeslicing;
+	enum dvbfe_stream_priority	priority;
+
+	__u32				bandwidth;
+	__u8				pad[32];
+};
+
+/* ATSC parameters			*/
+struct atsc_params {
+	enum dvbfe_modulation		modulation;
+
+	__u8				pad[32];
+};
+
+/* DVB Frontend Tuning Parameters	*/
+struct dvbfe_params {
+	__u32				frequency;
+	enum fe_spectral_inversion	inversion;
+	enum dvbfe_delsys		delivery;
+
+	__u8				pad[32];
+
+	union {
+		struct dvbs_params	dvbs;
+		struct dss_params	dss;
+		struct dvbs2_params	dvbs2;
+		struct dvbc_params	dvbc;
+		struct dvbt_params	dvbt;
+		struct dvbh_params	dvbh;
+		struct atsc_params	atsc;
+
+		__u8			pad[128];
+	} delsys;
+};
+#define DVBFE_SET_PARAMS		_IOW('o', 83, struct dvbfe_params)
+#define DVBFE_GET_PARAMS		_IOWR('o', 84, struct dvbfe_params)
+
+/* DVB-S capability bitfields		*/
+struct dvbfe_dvbs_info {
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_fec			fec;
+};
+
+/* DSS capability bitfields		*/
+struct dvbfe_dss_info {
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_fec			fec;
+};
+
+/* DVB-S2 capability bitfields		*/
+struct dvbfe_dvbs2_info {
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_fec			fec;
+
+	__u8				pad[32];
+};
+
+/* DVB-C capability bitfields		*/
+struct dvbfe_dvbc_info {
+	enum dvbfe_modulation		modulation;
+};
+
+/* DVB-T capability bitfields		*/
+struct dvbfe_dvbt_info {
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_stream_priority	stream_priority;
+
+	__u8				pad[32];
+};
+
+/* DVB-H capability bitfields		*/
+struct dvbfe_dvbh_info {
+	enum dvbfe_modulation		modulation;
+	enum dvbfe_stream_priority	stream_priority;
+
+	__u8				pad[32];
+};
+
+/* ATSC capability bitfields		*/
+struct dvbfe_atsc_info {
+	enum dvbfe_modulation		modulation;
+
+	__u8				pad[32];
+};
+
+/* DVB Frontend related Information	*/
+struct dvbfe_info {
+	char				name[128];
+
+	/* For Multi Standard tuners, set "delivery"
+	 * to the relevant delivery system to retrieve the
+	 * relevant delivery system related information.
+	 */
+	enum dvbfe_delsys		delivery;
+
+	union {
+		struct dvbfe_dvbs_info	dvbs;
+		struct dvbfe_dss_info	dss;
+		struct dvbfe_dvbs2_info	dvbs2;
+		struct dvbfe_dvbc_info	dvbc;
+		struct dvbfe_dvbt_info	dvbt;
+		struct dvbfe_dvbh_info	dvbh;
+		struct dvbfe_atsc_info	atsc;
+
+		__u8			pad[128];
+	} delsys;
+
+	__u32				frequency_min;
+	__u32				frequency_max;
+	__u32				frequency_step;
+	__u32				frequency_tolerance;
+	__u32				symbol_rate_min;
+	__u32				symbol_rate_max;
+	__u32				symbol_rate_tolerance;
+
+	enum fe_spectral_inversion	inversion;
+
+	__u8				pad[128];
+};
+#define DVBFE_GET_INFO			_IOWR('o', 85, struct dvbfe_info)
+
+enum dvbfe_status {
+	DVBFE_HAS_SIGNAL		= (1 <<  0),	/*  something above noise floor	*/
+	DVBFE_HAS_CARRIER		= (1 <<  1),	/*  Signal found		*/
+	DVBFE_HAS_VITERBI		= (1 <<  2),	/*  FEC is stable		*/
+	DVBFE_HAS_SYNC			= (1 <<  3),	/*  SYNC found			*/
+	DVBFE_HAS_LOCK			= (1 <<  4),	/*  OK ..			*/
+	DVBFE_TIMEDOUT			= (1 <<  5),	/*  no lock in last ~2 s	*/
+	DVBFE_STATUS_DUMMY		= (1 << 31)
+};
+
+/* DVB Frontend events			*/
+struct dvbfe_events {
+	enum dvbfe_status		status;
+
+	__u8				pad[32];
+};
+
+struct dvb_frontend_event {
+	fe_status_t status;
+	struct dvb_frontend_parameters parameters;
+	struct dvbfe_events fe_events;
+	struct dvbfe_params fe_params;
+};
+#define FE_GET_EVENT		   _IOR('o', 78, struct dvb_frontend_event)
+
 #endif /*_DVBFRONTEND_H_*/

