diff -Naur linux-3.6.8/drivers/media/dvb/ddbridge/ddbridge-core.c linux-3.6.8.patch/drivers/media/dvb/ddbridge/ddbridge-core.c
--- linux-3.6.8/drivers/media/dvb/ddbridge/ddbridge-core.c	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ddbridge/ddbridge-core.c	2012-12-03 08:41:17.000000000 +0100
@@ -31,11 +31,11 @@
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
 #include <linux/timer.h>
+#include <linux/version.h>
 #include <linux/i2c.h>
 #include <linux/swab.h>
 #include <linux/vmalloc.h>
 #include "ddbridge.h"
-
 #include "ddbridge-regs.h"
 
 #include "tda18271c2dd.h"
@@ -43,14 +43,60 @@
 #include "stv090x.h"
 #include "lnbh24.h"
 #include "drxk.h"
+#if 0
+#include "stv0367.h"
+#else
+#include "stv0367dd.h"
+#endif
+#if 0
+#include "tda18212.h"
+#else
+#include "tda18212dd.h"
+#endif
+
+static int adapter_alloc;
+module_param(adapter_alloc, int, 0444);
+MODULE_PARM_DESC(adapter_alloc, "0-one adapter per io, 1-one per tab with io, 2-one per tab, 3-one for all");
+
+static int ts_loop = -1;
+module_param(ts_loop, int, 0444);
+MODULE_PARM_DESC(ts_loop, "TS in/out on port ts_loop");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+static struct ddb *ddbs[32];
+
 /* MSI had problems with lost interrupts, fixed but needs testing */
-#undef CONFIG_PCI_MSI
+/* #undef CONFIG_PCI_MSI */
+
+/******************************************************************************/
+
+static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr)
+{
+	writel(val, (char *) (dev->regs+(adr)));
+}
+
+static inline u32 ddbreadl(struct ddb *dev, u32 adr)
+{
+	return readl((char *) (dev->regs+(adr)));
+}
+
+#define ddbcpyto(_dev, _adr, _src, _count)   memcpy_toio((char *) \
+					(_dev->regs + (_adr)), (_src), (_count))
+
+#define ddbcpyfrom(_dev, _dst, _adr, _count) memcpy_fromio((_dst), (char *) \
+					(_dev->regs + (_adr)), (_count))
+
 
 /******************************************************************************/
 
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len};
+
+	return (i2c_transfer(adap, &msg, 1) == 1) ? 0 : -1;
+}
+
 static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
 {
 	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
@@ -58,10 +104,31 @@
 	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
 }
 
+static int i2c_read_regs(struct i2c_adapter *adapter,
+			 u8 adr, u8 reg, u8 *val, u8 len)
+{
+	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+				   .buf  = &reg, .len   = 1},
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = len } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int i2c_read_regs16(struct i2c_adapter *adapter,
+			   u8 adr, u16 reg, u8 *val, u8 len)
+{
+	u8 reg16[2] = { reg >> 8, reg };
+	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
+				   .buf  = (u8 *)&reg16, .len   = 2},
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = len } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
 static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
 {
 	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
-				   .buf  = &reg, .len   = 1 },
+				   .buf  = &reg, .len   = 1},
 				  {.addr = adr,  .flags = I2C_M_RD,
 				   .buf  = val,  .len   = 1 } };
 	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
@@ -70,14 +137,22 @@
 static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
 			  u16 reg, u8 *val)
 {
-	u8 msg[2] = {reg>>8, reg&0xff};
+	u8 msg[2] = {reg >> 8, reg & 0xff};
 	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
 				   .buf  = msg, .len   = 2},
 				  {.addr = adr, .flags = I2C_M_RD,
-				   .buf  = val, .len   = 1} };
+				   .buf  = val, .len   = 1 } };
 	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
 }
 
+static int i2c_write_reg16(struct i2c_adapter *adap, u8 adr,
+			   u16 reg, u8 val)
+{
+	u8 msg[3] = {reg >> 8, reg & 0xff, val};
+
+	return i2c_write(adap, adr, msg, 3);
+}
+
 static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
 {
 	struct ddb *dev = i2c->dev;
@@ -85,18 +160,18 @@
 	u32 val;
 
 	i2c->done = 0;
-	ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND);
+	ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND);
 	stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
 	if (stat <= 0) {
 		printk(KERN_ERR "I2C timeout\n");
 		{ /* MSI debugging*/
-			u32 istat = ddbreadl(INTERRUPT_STATUS);
+			u32 istat = ddbreadl(dev, INTERRUPT_STATUS);
 			printk(KERN_ERR "IRS %08x\n", istat);
-			ddbwritel(istat, INTERRUPT_ACK);
+			ddbwritel(dev, istat, INTERRUPT_ACK);
 		}
 		return -EIO;
 	}
-	val = ddbreadl(i2c->regs+I2C_COMMAND);
+	val = ddbreadl(dev, i2c->regs+I2C_COMMAND);
 	if (val & 0x70000)
 		return -EIO;
 	return 0;
@@ -105,7 +180,7 @@
 static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
 			       struct i2c_msg msg[], int num)
 {
-	struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
+	struct ddb_i2c *i2c = (struct ddb_i2c *) i2c_get_adapdata(adapter);
 	struct ddb *dev = i2c->dev;
 	u8 addr = 0;
 
@@ -116,8 +191,8 @@
 	    !(msg[0].flags & I2C_M_RD)) {
 		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
 			    msg[0].buf, msg[0].len);
-		ddbwritel(msg[0].len|(msg[1].len << 16),
-			  i2c->regs+I2C_TASKLENGTH);
+		ddbwritel(dev, msg[0].len|(msg[1].len << 16),
+			  i2c->regs + I2C_TASKLENGTH);
 		if (!ddb_i2c_cmd(i2c, addr, 1)) {
 			memcpy_fromio(msg[1].buf,
 				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
@@ -125,17 +200,16 @@
 			return num;
 		}
 	}
-
 	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
-		ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len);
-		ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH);
+		ddbcpyto(dev, I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len);
+		ddbwritel(dev, msg[0].len, i2c->regs + I2C_TASKLENGTH);
 		if (!ddb_i2c_cmd(i2c, addr, 2))
 			return num;
 	}
 	if (num == 1 && (msg[0].flags & I2C_M_RD)) {
-		ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
+		ddbwritel(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
 		if (!ddb_i2c_cmd(i2c, addr, 3)) {
-			ddbcpyfrom(msg[0].buf,
+			ddbcpyfrom(dev, msg[0].buf,
 				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
 			return num;
 		}
@@ -160,7 +234,7 @@
 	struct ddb_i2c *i2c;
 	struct i2c_adapter *adap;
 
-	for (i = 0; i < dev->info->port_num; i++) {
+	for (i = 0; i < dev->info->i2c_num; i++) {
 		i2c = &dev->i2c[i];
 		adap = &i2c->adap;
 		i2c_del_adapter(adap);
@@ -173,15 +247,15 @@
 	struct ddb_i2c *i2c;
 	struct i2c_adapter *adap;
 
-	for (i = 0; i < dev->info->port_num; i++) {
+	for (i = 0; i < dev->info->i2c_num; i++) {
 		i2c = &dev->i2c[i];
 		i2c->dev = dev;
 		i2c->nr = i;
 		i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
 		i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
 		i2c->regs = 0x80 + i * 0x20;
-		ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING);
-		ddbwritel((i2c->rbuf << 16) | i2c->wbuf,
+		ddbwritel(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING);
+		ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf,
 			  i2c->regs + I2C_TASKADDRESS);
 		init_waitqueue_head(&i2c->wq);
 
@@ -216,69 +290,94 @@
 /******************************************************************************/
 /******************************************************************************/
 
-#if 0
-static void set_table(struct ddb *dev, u32 off,
-		      dma_addr_t *pbuf, u32 num)
+static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma)
 {
 	u32 i, base;
 	u64 mem;
 
-	base = DMA_BASE_ADDRESS_TABLE + off;
-	for (i = 0; i < num; i++) {
-		mem = pbuf[i];
-		ddbwritel(mem & 0xffffffff, base + i * 8);
-		ddbwritel(mem >> 32, base + i * 8 + 4);
+	if (!dma)
+		return;
+	base = DMA_BASE_ADDRESS_TABLE + dma->nr * 0x100;
+	for (i = 0; i < dma->num; i++) {
+		mem = dma->pbuf[i];
+		ddbwritel(dev, mem & 0xffffffff, base + i * 8);
+		ddbwritel(dev, mem >> 32, base + i * 8 + 4);
 	}
+	dma->bufreg = (dma->div << 16) |
+		((dma->num & 0x1f) << 11) |
+		((dma->size >> 7) & 0x7ff);
 }
-#endif
 
-static void ddb_address_table(struct ddb *dev)
+static void ddb_set_dma_tables(struct ddb *dev)
 {
-	u32 i, j, base;
-	u64 mem;
-	dma_addr_t *pbuf;
+	u32 i;
 
-	for (i = 0; i < dev->info->port_num * 2; i++) {
-		base = DMA_BASE_ADDRESS_TABLE + i * 0x100;
-		pbuf = dev->input[i].pbuf;
-		for (j = 0; j < dev->input[i].dma_buf_num; j++) {
-			mem = pbuf[j];
-			ddbwritel(mem & 0xffffffff, base + j * 8);
-			ddbwritel(mem >> 32, base + j * 8 + 4);
-		}
-	}
-	for (i = 0; i < dev->info->port_num; i++) {
-		base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100;
-		pbuf = dev->output[i].pbuf;
-		for (j = 0; j < dev->output[i].dma_buf_num; j++) {
-			mem = pbuf[j];
-			ddbwritel(mem & 0xffffffff, base + j * 8);
-			ddbwritel(mem >> 32, base + j * 8 + 4);
-		}
-	}
+	for (i = 0; i < dev->info->port_num * 2; i++)
+		ddb_set_dma_table(dev, dev->input[i].dma);
+	for (i = 0; i < dev->info->port_num; i++)
+		ddb_set_dma_table(dev, dev->output[i].dma);
 }
 
-static void io_free(struct pci_dev *pdev, u8 **vbuf,
-		    dma_addr_t *pbuf, u32 size, int num)
+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma)
 {
 	int i;
 
-	for (i = 0; i < num; i++) {
-		if (vbuf[i]) {
-			pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
-			vbuf[i] = 0;
+	if (!dma)
+		return;
+	for (i = 0; i < dma->num; i++) {
+		if (dma->vbuf[i]) {
+			pci_free_consistent(pdev, dma->size,
+					    dma->vbuf[i], dma->pbuf[i]);
+			dma->vbuf[i] = 0;
 		}
 	}
 }
 
-static int io_alloc(struct pci_dev *pdev, u8 **vbuf,
-		    dma_addr_t *pbuf, u32 size, int num)
+static void ddb_redirect_dma(struct ddb *dev,
+			     struct ddb_dma *sdma,
+			     struct ddb_dma *ddma)
+{
+	u32 i, base;
+	u64 mem;
+
+	sdma->bufreg = ddma->bufreg;
+	base = DMA_BASE_ADDRESS_TABLE + sdma->nr * 0x100;
+	for (i = 0; i < ddma->num; i++) {
+		mem = ddma->pbuf[i];
+		ddbwritel(dev, mem & 0xffffffff, base + i * 8);
+		ddbwritel(dev, mem >> 32, base + i * 8 + 4);
+	}
+}
+
+static void ddb_unredirect(struct ddb_port *port)
+{
+	struct ddb_input *ored, *ired;
+
+	ored = port->output->redirect;
+	ired = port->input[0]->redirect;
+
+	if (!ored || !ired)
+		return;
+	if (ired->port->output->redirect == port->input[0]) {
+		ired->port->output->redirect = ored;
+		ddb_set_dma_table(port->dev, port->input[0]->dma);
+		ddb_redirect_dma(ored->port->dev, ored->dma, ired->port->output->dma);
+	} else
+		ddb_set_dma_table(ored->port->dev, ored->dma);
+	ored->redirect = ired;
+	port->input[0]->redirect = 0;
+	port->output->redirect = 0;
+}
+
+static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma)
 {
 	int i;
 
-	for (i = 0; i < num; i++) {
-		vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
-		if (!vbuf[i])
+	if (!dma)
+		return 0;
+	for (i = 0; i < dma->num; i++) {
+		dma->vbuf[i] = pci_alloc_consistent(pdev, dma->size, &dma->pbuf[i]);
+		if (!dma->vbuf[i])
 			return -ENOMEM;
 	}
 	return 0;
@@ -293,34 +392,23 @@
 		port = &dev->port[i];
 		switch (port->class) {
 		case DDB_PORT_TUNER:
-			if (io_alloc(dev->pdev, port->input[0]->vbuf,
-				     port->input[0]->pbuf,
-				     port->input[0]->dma_buf_size,
-				     port->input[0]->dma_buf_num) < 0)
+			if (dma_alloc(dev->pdev, port->input[0]->dma) < 0)
 				return -1;
-			if (io_alloc(dev->pdev, port->input[1]->vbuf,
-				     port->input[1]->pbuf,
-				     port->input[1]->dma_buf_size,
-				     port->input[1]->dma_buf_num) < 0)
+			if (dma_alloc(dev->pdev, port->input[1]->dma) < 0)
 				return -1;
 			break;
 		case DDB_PORT_CI:
-			if (io_alloc(dev->pdev, port->input[0]->vbuf,
-				     port->input[0]->pbuf,
-				     port->input[0]->dma_buf_size,
-				     port->input[0]->dma_buf_num) < 0)
+		case DDB_PORT_LOOP:
+			if (dma_alloc(dev->pdev, port->input[0]->dma) < 0)
 				return -1;
-			if (io_alloc(dev->pdev, port->output->vbuf,
-				     port->output->pbuf,
-				     port->output->dma_buf_size,
-				     port->output->dma_buf_num) < 0)
+			if (dma_alloc(dev->pdev, port->output->dma) < 0)
 				return -1;
 			break;
 		default:
 			break;
 		}
 	}
-	ddb_address_table(dev);
+	ddb_set_dma_tables(dev);
 	return 0;
 }
 
@@ -331,18 +419,11 @@
 
 	for (i = 0; i < dev->info->port_num; i++) {
 		port = &dev->port[i];
-		io_free(dev->pdev, port->input[0]->vbuf,
-			port->input[0]->pbuf,
-			port->input[0]->dma_buf_size,
-			port->input[0]->dma_buf_num);
-		io_free(dev->pdev, port->input[1]->vbuf,
-			port->input[1]->pbuf,
-			port->input[1]->dma_buf_size,
-			port->input[1]->dma_buf_num);
-		io_free(dev->pdev, port->output->vbuf,
-			port->output->pbuf,
-			port->output->dma_buf_size,
-			port->output->dma_buf_num);
+
+		ddb_unredirect(port);
+		dma_free(dev->pdev, port->input[0]->dma);
+		dma_free(dev->pdev, port->input[1]->dma);
+		dma_free(dev->pdev, port->output->dma);
 	}
 }
 
@@ -350,90 +431,116 @@
 {
 	struct ddb *dev = input->port->dev;
 
-	spin_lock_irq(&input->lock);
-	input->cbuf = 0;
-	input->coff = 0;
+	spin_lock_irq(&input->dma->lock);
+	input->dma->cbuf = 0;
+	input->dma->coff = 0;
 
 	/* reset */
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(2, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
-
-	ddbwritel((1 << 16) |
-		  (input->dma_buf_num << 11) |
-		  (input->dma_buf_size >> 7),
-		  DMA_BUFFER_SIZE(input->nr));
-	ddbwritel(0, DMA_BUFFER_ACK(input->nr));
-
-	ddbwritel(1, DMA_BASE_WRITE);
-	ddbwritel(3, DMA_BUFFER_CONTROL(input->nr));
-	ddbwritel(9, TS_INPUT_CONTROL(input->nr));
-	input->running = 1;
-	spin_unlock_irq(&input->lock);
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(dev, 2, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+
+	ddbwritel(dev, input->dma->bufreg, DMA_BUFFER_SIZE(input->dma->nr));
+	ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr));
+
+	ddbwritel(dev, 1, DMA_BASE_WRITE);
+	ddbwritel(dev, 3, DMA_BUFFER_CONTROL(input->dma->nr));
+	ddbwritel(dev, 9, TS_INPUT_CONTROL(input->nr));
+	input->dma->running = 1;
+	spin_unlock_irq(&input->dma->lock);
+	/* printk(KERN_INFO "input_start %d\n", input->nr); */
 }
 
 static void ddb_input_stop(struct ddb_input *input)
 {
 	struct ddb *dev = input->port->dev;
 
-	spin_lock_irq(&input->lock);
-	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
-	ddbwritel(0, DMA_BUFFER_CONTROL(input->nr));
-	input->running = 0;
-	spin_unlock_irq(&input->lock);
+	spin_lock_irq(&input->dma->lock);
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr));
+	input->dma->running = 0;
+	spin_unlock_irq(&input->dma->lock);
 }
 
 static void ddb_output_start(struct ddb_output *output)
 {
 	struct ddb *dev = output->port->dev;
 
-	spin_lock_irq(&output->lock);
-	output->cbuf = 0;
-	output->coff = 0;
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(2, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel((1 << 16) |
-		  (output->dma_buf_num << 11) |
-		  (output->dma_buf_size >> 7),
-		  DMA_BUFFER_SIZE(output->nr + 8));
-	ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8));
-
-	ddbwritel(1, DMA_BASE_READ);
-	ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8));
-	/* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */
-	ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr));
-	output->running = 1;
-	spin_unlock_irq(&output->lock);
+	spin_lock_irq(&output->dma->lock);
+	output->dma->cbuf = 0;
+	output->dma->coff = 0;
+	ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(dev, 0x3c, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(dev, output->dma->bufreg, DMA_BUFFER_SIZE(output->dma->nr));
+	ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr));
+
+	ddbwritel(dev, 1, DMA_BASE_READ);
+	ddbwritel(dev, 3, DMA_BUFFER_CONTROL(output->dma->nr));
+	if (output->port->input[0]->port->class == DDB_PORT_LOOP)
+		ddbwritel(dev, 0x05, TS_OUTPUT_CONTROL(output->nr));
+	else
+		ddbwritel(dev, 0x1d, TS_OUTPUT_CONTROL(output->nr));
+	output->dma->running = 1;
+	spin_unlock_irq(&output->dma->lock);
+	/* printk(KERN_INFO "output_start %d\n", output->nr); */
+}
+
+#if 0
+static void ddb_input_start_all(struct ddb_input *input)
+{
+	struct ddb_input *next;
+
+	ddb_input_start(input);
+	while ((next = input->redirect) &&
+	       next != input) {
+		ddb_input_start(next);
+		ddb_output_start(next->port->output);
+	}
 }
+#endif
 
 static void ddb_output_stop(struct ddb_output *output)
 {
 	struct ddb *dev = output->port->dev;
 
-	spin_lock_irq(&output->lock);
-	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
-	ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8));
-	output->running = 0;
-	spin_unlock_irq(&output->lock);
+	spin_lock_irq(&output->dma->lock);
+	ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
+	ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr));
+	output->dma->running = 0;
+	spin_unlock_irq(&output->dma->lock);
+}
+
+#if 0
+static void ddb_input_stop_all(struct ddb_input *input)
+{
+	struct ddb_input *next;
+
+	ddb_input_stop(input);
+	while ((next = input->redirect) &&
+	       next != input) {
+		ddb_input_stop(next);
+		ddb_output_stop(next->port->output);
+	}
 }
+#endif
 
 static u32 ddb_output_free(struct ddb_output *output)
 {
-	u32 idx, off, stat = output->stat;
+	u32 idx, off, stat = output->dma->stat;
 	s32 diff;
 
 	idx = (stat >> 11) & 0x1f;
 	off = (stat & 0x7ff) << 7;
 
-	if (output->cbuf != idx) {
-		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
-		    (output->dma_buf_size - output->coff <= 188))
+	if (output->dma->cbuf != idx) {
+		if ((((output->dma->cbuf + 1) % output->dma->num) == idx) &&
+		    (output->dma->size - output->dma->coff <= 188))
 			return 0;
 		return 188;
 	}
-	diff = off - output->coff;
+	diff = off - output->dma->coff;
 	if (diff <= 0 || diff > 188)
 		return 188;
 	return 0;
@@ -443,24 +550,24 @@
 				const u8 *buf, size_t count)
 {
 	struct ddb *dev = output->port->dev;
-	u32 idx, off, stat = output->stat;
+	u32 idx, off, stat = output->dma->stat;
 	u32 left = count, len;
 
 	idx = (stat >> 11) & 0x1f;
 	off = (stat & 0x7ff) << 7;
 
 	while (left) {
-		len = output->dma_buf_size - output->coff;
-		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
+		len = output->dma->size - output->dma->coff;
+		if ((((output->dma->cbuf + 1) % output->dma->num) == idx) &&
 		    (off == 0)) {
 			if (len <= 188)
 				break;
 			len -= 188;
 		}
-		if (output->cbuf == idx) {
-			if (off > output->coff) {
+		if (output->dma->cbuf == idx) {
+			if (off > output->dma->coff) {
 #if 1
-				len = off - output->coff;
+				len = off - output->dma->coff;
 				len -= (len % 188);
 				if (len <= 188)
 
@@ -471,68 +578,146 @@
 		}
 		if (len > left)
 			len = left;
-		if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
+		if (copy_from_user(output->dma->vbuf[output->dma->cbuf] +
+				   output->dma->coff,
 				   buf, len))
 			return -EIO;
+		/* printk("cfu %d  %d %d\n", len, output->cbuf, output->coff); */
 		left -= len;
 		buf += len;
-		output->coff += len;
-		if (output->coff == output->dma_buf_size) {
-			output->coff = 0;
-			output->cbuf = ((output->cbuf + 1) % output->dma_buf_num);
+		output->dma->coff += len;
+		if (output->dma->coff == output->dma->size) {
+			output->dma->coff = 0;
+			output->dma->cbuf = ((output->dma->cbuf + 1) %
+					     output->dma->num);
 		}
-		ddbwritel((output->cbuf << 11) | (output->coff >> 7),
-			  DMA_BUFFER_ACK(output->nr + 8));
+		ddbwritel(dev, (output->dma->cbuf << 11) | (output->dma->coff >> 7),
+			  DMA_BUFFER_ACK(output->dma->nr));
 	}
 	return count - left;
 }
 
+#if 0
+static u32 ddb_input_free_bytes(struct ddb_input *input)
+{
+	struct ddb *dev = input->port->dev;
+	u32 idx, off, stat = input->dma->stat;
+	u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr));
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	if (ctrl & 4)
+		return 0;
+	if (input->dma->cbuf != idx)
+		return 1;
+	return 0;
+}
+
+static s32 ddb_output_used_bufs(struct ddb_output *output)
+{
+	u32 idx, off, stat, ctrl;
+	s32 diff;
+
+	spin_lock_irq(&output->dma->lock);
+	stat = output->dma->stat;
+	ctrl = output->dma->ctrl;
+	spin_unlock_irq(&output->dma->lock);
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	if (ctrl & 4)
+		return 0;
+	diff = output->dma->cbuf - idx;
+	if (diff == 0 && off < output->dma->coff)
+		return 0;
+	if (diff <= 0)
+		diff += output->dma->num;
+	return diff;
+}
+
+static s32 ddb_input_free_bufs(struct ddb_input *input)
+{
+	u32 idx, off, stat, ctrl;
+	s32 free;
+
+	spin_lock_irq(&input->dma->lock);
+	ctrl = input->dma->ctrl;
+	stat = input->dma->stat;
+	spin_unlock_irq(&input->dma->lock);
+	if (ctrl & 4)
+		return 0;
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+	free = input->dma->cbuf - idx;
+	if (free == 0 && off < input->dma->coff)
+		return 0;
+	if (free <= 0)
+		free += input->dma->num;
+	return free - 1;
+}
+
+static u32 ddb_output_ok(struct ddb_output *output)
+{
+	struct ddb_input *input = output->port->input[0];
+	s32 diff;
+
+	diff = ddb_input_free_bufs(input) - ddb_output_used_bufs(output);
+	if (diff > 0)
+		return 1;
+	return 0;
+}
+#endif
+
 static u32 ddb_input_avail(struct ddb_input *input)
 {
 	struct ddb *dev = input->port->dev;
-	u32 idx, off, stat = input->stat;
-	u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr));
+	u32 idx, off, stat = input->dma->stat;
+	u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr));
 
 	idx = (stat >> 11) & 0x1f;
 	off = (stat & 0x7ff) << 7;
 
 	if (ctrl & 4) {
 		printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl);
-		ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr));
+		ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr));
 		return 0;
 	}
-	if (input->cbuf != idx)
+	if (input->dma->cbuf != idx || off < input->dma->coff)
 		return 188;
 	return 0;
 }
 
-static ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
+static size_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
 {
 	struct ddb *dev = input->port->dev;
 	u32 left = count;
-	u32 idx, free, stat = input->stat;
+	u32 idx, off, free, stat = input->dma->stat;
 	int ret;
 
 	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
 
 	while (left) {
-		if (input->cbuf == idx)
+		if (input->dma->cbuf == idx)
 			return count - left;
-		free = input->dma_buf_size - input->coff;
+		free = input->dma->size - input->dma->coff;
 		if (free > left)
 			free = left;
-		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
-				   input->coff, free);
+		ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] +
+				   input->dma->coff, free);
 		if (ret)
 			return -EFAULT;
-		input->coff += free;
-		if (input->coff == input->dma_buf_size) {
-			input->coff = 0;
-			input->cbuf = (input->cbuf+1) % input->dma_buf_num;
+		input->dma->coff += free;
+		if (input->dma->coff == input->dma->size) {
+			input->dma->coff = 0;
+			input->dma->cbuf = (input->dma->cbuf+1) %
+				input->dma->num;
 		}
 		left -= free;
-		ddbwritel((input->cbuf << 11) | (input->coff >> 7),
-			  DMA_BUFFER_ACK(input->nr));
+		ddbwritel(dev, (input->dma->cbuf << 11) | (input->dma->coff >> 7),
+			  DMA_BUFFER_ACK(input->dma->nr));
 	}
 	return count;
 }
@@ -554,7 +739,7 @@
 }
 #endif
 
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct ddb_input *input = fe->sec_priv;
 	struct ddb_port *port = input->port;
@@ -562,9 +747,9 @@
 
 	if (enable) {
 		mutex_lock(&port->i2c_gate_lock);
-		status = input->gate_ctrl(fe, 1);
+		status = input->dvb.gate_ctrl(fe, 1);
 	} else {
-		status = input->gate_ctrl(fe, 0);
+		status = input->dvb.gate_ctrl(fe, 0);
 		mutex_unlock(&port->i2c_gate_lock);
 	}
 	return status;
@@ -577,18 +762,88 @@
 	struct drxk_config config;
 
 	memset(&config, 0, sizeof(config));
-	config.microcode_name = "drxk_a3.mc";
-	config.qam_demod_parameter_count = 4;
 	config.adr = 0x29 + (input->nr & 1);
+	config.microcode_name = "drxk_a3.mc";
 
-	fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
-	if (!input->fe) {
+#ifdef USE_API3
+	fe = input->dvb.fe = dvb_attach(drxk_attach, &config, i2c, &input->dvb.fe2);
+#else
+	fe = input->dvb.fe = dvb_attach(drxk_attach, &config, i2c);
+#endif
+	if (!input->dvb.fe) {
 		printk(KERN_ERR "No DRXK found!\n");
 		return -ENODEV;
 	}
 	fe->sec_priv = input;
-	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
-	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+	input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
+	return 0;
+}
+
+#if 0
+struct stv0367_config stv0367_0 = {
+	.demod_address = 0x1f,
+	.xtal = 27000000,
+	.if_khz = 5000,
+	.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+	.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+	.clk_pol = STV0367_RISINGEDGE_CLOCK,
+};
+
+struct stv0367_config stv0367_1 = {
+	.demod_address = 0x1e,
+	.xtal = 27000000,
+	.if_khz = 5000,
+	.if_iq_mode = FE_TER_NORMAL_IF_TUNER,
+	.ts_mode = STV0367_SERIAL_PUNCT_CLOCK,
+	.clk_pol = STV0367_RISINGEDGE_CLOCK,
+};
+
+
+static int demod_attach_stv0367(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct dvb_frontend *fe;
+
+	fe = input->dvb.fe = dvb_attach(stv0367ter_attach,
+				    (input->nr & 1) ? &stv0367_1 : &stv0367_0,
+				    i2c);
+	if (!input->dvb.fe) {
+		printk(KERN_ERR "No stv0367 found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
+	return 0;
+}
+#endif
+
+struct stv0367_cfg stv0367dd_0 = {
+	.adr = 0x1f,
+	.xtal = 27000000,
+};
+
+struct stv0367_cfg stv0367dd_1 = {
+	.adr = 0x1e,
+	.xtal = 27000000,
+};
+
+static int demod_attach_stv0367dd(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct dvb_frontend *fe;
+
+	fe = input->dvb.fe = dvb_attach(stv0367_attach, i2c,
+				    (input->nr & 1) ? &stv0367dd_1 : &stv0367dd_0,
+				    &input->dvb.fe2);
+	if (!input->dvb.fe) {
+		printk(KERN_ERR "No stv0367 found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	input->dvb.gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
 	return 0;
 }
 
@@ -597,18 +852,57 @@
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
 	struct dvb_frontend *fe;
 
-	if (input->fe->ops.i2c_gate_ctrl)
-		input->fe->ops.i2c_gate_ctrl(input->fe, 1);
-	fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60);
+	if (input->dvb.fe->ops.i2c_gate_ctrl)
+		input->dvb.fe->ops.i2c_gate_ctrl(input->dvb.fe, 1);
+	fe = dvb_attach(tda18271c2dd_attach, input->dvb.fe, i2c, 0x60);
+	if (input->dvb.fe->ops.i2c_gate_ctrl)
+		input->dvb.fe->ops.i2c_gate_ctrl(input->dvb.fe, 0);
 	if (!fe) {
 		printk(KERN_ERR "No TDA18271 found!\n");
 		return -ENODEV;
 	}
-	if (input->fe->ops.i2c_gate_ctrl)
-		input->fe->ops.i2c_gate_ctrl(input->fe, 0);
 	return 0;
 }
 
+static int tuner_attach_tda18212dd(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct dvb_frontend *fe;
+
+	fe = dvb_attach(tda18212dd_attach, input->dvb.fe, i2c,
+			(input->nr & 1) ? 0x63 : 0x60);
+	if (!fe) {
+		printk(KERN_ERR "No TDA18212 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+#if 0
+struct tda18212_config tda18212_0 = {
+	.i2c_address = 0x60,
+};
+
+struct tda18212_config tda18212_1 = {
+	.i2c_address = 0x63,
+};
+
+static int tuner_attach_tda18212(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct dvb_frontend *fe;
+	struct tda18212_config *cfg;
+
+	cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0;
+	fe = dvb_attach(tda18212_attach, input->dvb.fe, i2c, cfg);
+	if (!fe) {
+		printk(KERN_ERR "No TDA18212 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+#endif
+
 /******************************************************************************/
 /******************************************************************************/
 /******************************************************************************/
@@ -668,14 +962,14 @@
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
 	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
 
-	input->fe = dvb_attach(stv090x_attach, feconf, i2c,
+	input->dvb.fe = dvb_attach(stv090x_attach, feconf, i2c,
 			       (input->nr & 1) ? STV090x_DEMODULATOR_1
 			       : STV090x_DEMODULATOR_0);
-	if (!input->fe) {
+	if (!input->dvb.fe) {
 		printk(KERN_ERR "No STV0900 found!\n");
 		return -ENODEV;
 	}
-	if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
+	if (!dvb_attach(lnbh24_attach, input->dvb.fe, i2c, 0,
 			0, (input->nr & 1) ?
 			(0x09 - type) : (0x0b - type))) {
 		printk(KERN_ERR "No LNBH24 found!\n");
@@ -692,7 +986,7 @@
 		&stv6110b : &stv6110a;
 	struct stv6110x_devctl *ctl;
 
-	ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
+	ctl = dvb_attach(stv6110x_attach, input->dvb.fe, tunerconf, i2c);
 	if (!ctl) {
 		printk(KERN_ERR "No STV6110X found!\n");
 		return -ENODEV;
@@ -760,10 +1054,10 @@
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct ddb_input *input = dvbdmx->priv;
 
-	if (!input->users)
+	if (!input->dvb.users)
 		ddb_input_start(input);
 
-	return ++input->users;
+	return ++input->dvb.users;
 }
 
 static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
@@ -771,8 +1065,8 @@
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct ddb_input *input = dvbdmx->priv;
 
-	if (--input->users)
-		return input->users;
+	if (--input->dvb.users)
+		return input->dvb.users;
 
 	ddb_input_stop(input);
 	return 0;
@@ -781,116 +1075,200 @@
 
 static void dvb_input_detach(struct ddb_input *input)
 {
-	struct dvb_adapter *adap = &input->adap;
-	struct dvb_demux *dvbdemux = &input->demux;
+	struct dvb_demux *dvbdemux = &input->dvb.demux;
 
-	switch (input->attached) {
+	switch (input->dvb.attached) {
+	case 6:
+		if (input->dvb.fe2)
+			dvb_unregister_frontend(input->dvb.fe2);
+		if (input->dvb.fe)
+			dvb_unregister_frontend(input->dvb.fe);
 	case 5:
-		if (input->fe2)
-			dvb_unregister_frontend(input->fe2);
-		if (input->fe) {
-			dvb_unregister_frontend(input->fe);
-			dvb_frontend_detach(input->fe);
-			input->fe = NULL;
-		}
+		dvb_frontend_detach(input->dvb.fe);
+		input->dvb.fe = NULL;
 	case 4:
-		dvb_net_release(&input->dvbnet);
-
+		dvb_net_release(&input->dvb.dvbnet);
 	case 3:
 		dvbdemux->dmx.close(&dvbdemux->dmx);
 		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &input->hw_frontend);
+					      &input->dvb.hw_frontend);
 		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &input->mem_frontend);
-		dvb_dmxdev_release(&input->dmxdev);
-
+					      &input->dvb.mem_frontend);
+		dvb_dmxdev_release(&input->dvb.dmxdev);
 	case 2:
-		dvb_dmx_release(&input->demux);
-
+		dvb_dmx_release(&input->dvb.demux);
 	case 1:
-		dvb_unregister_adapter(adap);
+		break;
+	}
+	input->dvb.attached = 0;
+}
+
+static int dvb_register_adapters(struct ddb *dev)
+{
+	int i, ret = 0;
+	struct ddb_port *port;
+	struct dvb_adapter *adap;
+
+	if (adapter_alloc == 3) {
+		port = &dev->port[0];
+		adap = port->input[0]->dvb.adap;
+		ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+					   &port->dev->pdev->dev,
+					   adapter_nr);
+		if (ret < 0)
+			return ret;
+		port->input[0]->dvb.adap_registered = 1;
+		for (i = 0; i < dev->info->port_num; i++) {
+			port = &dev->port[i];
+			port->input[0]->dvb.adap = adap;
+			port->input[1]->dvb.adap = adap;
+		}
+		return 0;
+	}
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		switch (port->class) {
+		case DDB_PORT_TUNER:
+			adap = port->input[0]->dvb.adap;
+			ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+						   &port->dev->pdev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->input[0]->dvb.adap_registered = 1;
+
+			if (adapter_alloc > 0) {
+				port->input[1]->dvb.adap = port->input[0]->dvb.adap;
+				break;
+			}
+			adap = port->input[1]->dvb.adap;
+			ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+						   &port->dev->pdev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->input[1]->dvb.adap_registered = 1;
+			break;
+
+		case DDB_PORT_CI:
+		case DDB_PORT_LOOP:
+			adap = port->input[0]->dvb.adap;
+			ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+						   &port->dev->pdev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->input[0]->dvb.adap_registered = 1;
+			break;
+		default:
+			if (adapter_alloc < 2)
+				break;
+			adap = port->input[0]->dvb.adap;
+			ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+						   &port->dev->pdev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->input[0]->dvb.adap_registered = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+static void dvb_unregister_adapters(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+	struct ddb_input *input;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+
+		input = port->input[0];
+		if (input->dvb.adap_registered)
+			dvb_unregister_adapter(input->dvb.adap);
+		input->dvb.adap_registered = 0;
+
+		input = port->input[1];
+		if (input->dvb.adap_registered)
+			dvb_unregister_adapter(input->dvb.adap);
+		input->dvb.adap_registered = 0;
 	}
-	input->attached = 0;
 }
 
+
 static int dvb_input_attach(struct ddb_input *input)
 {
-	int ret;
+	int ret = 0;
 	struct ddb_port *port = input->port;
-	struct dvb_adapter *adap = &input->adap;
-	struct dvb_demux *dvbdemux = &input->demux;
+	struct dvb_adapter *adap = input->dvb.adap;
+	struct dvb_demux *dvbdemux = &input->dvb.demux;
 
-	ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
-				   &input->port->dev->pdev->dev,
-				   adapter_nr);
-	if (ret < 0) {
-		printk(KERN_ERR "ddbridge: Could not register adapter."
-		       "Check if you enabled enough adapters in dvb-core!\n");
-		return ret;
-	}
-	input->attached = 1;
+	input->dvb.attached = 1;
 
 	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
 				      start_feed,
 				      stop_feed, input);
 	if (ret < 0)
 		return ret;
-	input->attached = 2;
+	input->dvb.attached = 2;
 
-	ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
-					 &input->hw_frontend,
-					 &input->mem_frontend, adap);
+	ret = my_dvb_dmxdev_ts_card_init(&input->dvb.dmxdev,
+					 &input->dvb.demux,
+					 &input->dvb.hw_frontend,
+					 &input->dvb.mem_frontend, adap);
 	if (ret < 0)
 		return ret;
-	input->attached = 3;
+	input->dvb.attached = 3;
 
-	ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
+	ret = dvb_net_init(adap, &input->dvb.dvbnet, input->dvb.dmxdev.demux);
 	if (ret < 0)
 		return ret;
-	input->attached = 4;
+	input->dvb.attached = 4;
 
-	input->fe = 0;
+	input->dvb.fe = 0;
 	switch (port->type) {
 	case DDB_TUNER_DVBS_ST:
 		if (demod_attach_stv0900(input, 0) < 0)
 			return -ENODEV;
 		if (tuner_attach_stv6110(input, 0) < 0)
 			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
 		break;
 	case DDB_TUNER_DVBS_ST_AA:
 		if (demod_attach_stv0900(input, 1) < 0)
 			return -ENODEV;
 		if (tuner_attach_stv6110(input, 1) < 0)
 			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
 		break;
 	case DDB_TUNER_DVBCT_TR:
 		if (demod_attach_drxk(input) < 0)
 			return -ENODEV;
 		if (tuner_attach_tda18271(input) < 0)
 			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
-		if (input->fe2) {
-			if (dvb_register_frontend(adap, input->fe2) < 0)
-				return -ENODEV;
-			input->fe2->tuner_priv = input->fe->tuner_priv;
-			memcpy(&input->fe2->ops.tuner_ops,
-			       &input->fe->ops.tuner_ops,
-			       sizeof(struct dvb_tuner_ops));
-		}
 		break;
+	case DDB_TUNER_DVBCT_ST:
+		if (demod_attach_stv0367dd(input) < 0)
+			return -ENODEV;
+		if (tuner_attach_tda18212dd(input) < 0)
+			return -ENODEV;
+		break;
+	}
+	input->dvb.attached = 5;
+	if (input->dvb.fe) {
+		if (dvb_register_frontend(adap, input->dvb.fe) < 0)
+			return -ENODEV;
+	}
+	if (input->dvb.fe2) {
+		if (dvb_register_frontend(adap, input->dvb.fe2) < 0)
+			return -ENODEV;
+		input->dvb.fe2->tuner_priv = input->dvb.fe->tuner_priv;
+		memcpy(&input->dvb.fe2->ops.tuner_ops,
+		       &input->dvb.fe->ops.tuner_ops,
+		       sizeof(struct dvb_tuner_ops));
 	}
-	input->attached = 5;
+	input->dvb.attached = 6;
 	return 0;
 }
 
@@ -910,7 +1288,8 @@
 			if (file->f_flags & O_NONBLOCK)
 				break;
 			if (wait_event_interruptible(
-				    output->wq, ddb_output_free(output) >= 188) < 0)
+				    output->dma->wq,
+				    ddb_output_free(output) >= 188) < 0)
 				break;
 		}
 		stat = ddb_output_write(output, buf, left);
@@ -937,7 +1316,7 @@
 			if (file->f_flags & O_NONBLOCK)
 				break;
 			if (wait_event_interruptible(
-				    input->wq, ddb_input_avail(input) >= 188) < 0)
+				    input->dma->wq, ddb_input_avail(input) >= 188) < 0)
 				break;
 		}
 		read = ddb_input_read(input, buf, left);
@@ -970,21 +1349,53 @@
 	return mask;
 }
 
-static const struct file_operations ci_fops = {
-	.owner   = THIS_MODULE,
-	.read    = ts_read,
-	.write   = ts_write,
-	.open    = dvb_generic_open,
-	.release = dvb_generic_release,
-	.poll    = ts_poll,
-	.mmap    = 0,
-};
-
-static struct dvb_device dvbdev_ci = {
+#if 0
+static int ts_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+
+
+	return dvb_generic_release(inode, file);
+}
+
+static unsigned int ts_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+
+	err = dvb_generic_open(inode, file);
+	if (err < 0)
+		return err;
+
+#if 0
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+		ddb_input_start(input);
+	else
+		ddb_output_start(output);
+#endif
+	return err;
+}
+#endif
+
+static const struct file_operations ci_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ts_read,
+	.write   = ts_write,
+	.open    = dvb_generic_open,
+	.release = dvb_generic_release,
+	.poll    = ts_poll,
+	.mmap    = 0,
+};
+
+static struct dvb_device dvbdev_ci = {
 	.priv    = 0,
-	.readers = -1,
-	.writers = -1,
-	.users   = -1,
+	.readers = 1,
+	.writers = 1,
+	.users   = 2,
 	.fops    = &ci_fops,
 };
 
@@ -992,53 +1403,297 @@
 /****************************************************************************/
 /****************************************************************************/
 
+static int set_redirect(u32 i, u32 p)
+{
+	struct ddb *idev = ddbs[(i >> 4) & 0x1f];
+	struct ddb_input *input;
+	struct ddb *pdev = ddbs[(p >> 4) & 0x1f];
+	struct ddb_port *port;
+
+	if (!idev || !pdev)
+		return -EINVAL;
+
+	port = &pdev->port[p & 3];
+	if (port->class != DDB_PORT_CI && port->class != DDB_PORT_LOOP)
+		return -EINVAL;
+
+	ddb_unredirect(port);
+	if (i == 8)
+		return 0;
+	input = &idev->input[i & 7];
+	if (input->port->class != DDB_PORT_TUNER)
+		port->input[0]->redirect = input->redirect;
+	else
+		port->input[0]->redirect = input;
+	input->redirect = port->input[0];
+	port->output->redirect = input;
+
+	ddb_redirect_dma(input->port->dev, input->dma, port->output->dma);
+	return 0;
+}
+
+static void input_write_output(struct ddb_input *input,
+			       struct ddb_output *output)
+{
+	ddbwritel(output->port->dev,
+		  input->dma->stat, DMA_BUFFER_ACK(output->dma->nr));
+}
+
+static void output_ack_input(struct ddb_output *output,
+			     struct ddb_input *input)
+{
+	ddbwritel(input->port->dev,
+		  output->dma->stat, DMA_BUFFER_ACK(input->dma->nr));
+}
+
+static void input_write_dvb(struct ddb_input *input, struct ddb_dvb *dvb)
+{
+	struct ddb_dma *dma = input->dma;
+	struct ddb *dev = input->port->dev;
+
+	if (4 & ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)))
+		printk(KERN_ERR "Overflow dma %d\n", dma->nr);
+	while (dma->cbuf != ((dma->stat >> 11) & 0x1f)
+	       || (4 & ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr)))) {
+		dvb_dmx_swfilter_packets(&dvb->demux,
+					 dma->vbuf[dma->cbuf],
+					 dma->size / 188);
+		dma->cbuf = (dma->cbuf + 1) % dma->num;
+		ddbwritel(dev, (dma->cbuf << 11),  DMA_BUFFER_ACK(dma->nr));
+		dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
+	}
+}
+
 static void input_tasklet(unsigned long data)
 {
 	struct ddb_input *input = (struct ddb_input *) data;
+	struct ddb_dma *dma = input->dma;
 	struct ddb *dev = input->port->dev;
 
-	spin_lock(&input->lock);
-	if (!input->running) {
-		spin_unlock(&input->lock);
+	spin_lock(&dma->lock);
+	if (!dma->running) {
+		spin_unlock(&dma->lock);
 		return;
 	}
-	input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
+	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
 
 	if (input->port->class == DDB_PORT_TUNER) {
-		if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))
-			printk(KERN_ERR "Overflow input %d\n", input->nr);
-		while (input->cbuf != ((input->stat >> 11) & 0x1f)
-		       || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) {
-			dvb_dmx_swfilter_packets(&input->demux,
-						 input->vbuf[input->cbuf],
-						 input->dma_buf_size / 188);
-
-			input->cbuf = (input->cbuf + 1) % input->dma_buf_num;
-			ddbwritel((input->cbuf << 11),
-				  DMA_BUFFER_ACK(input->nr));
-			input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
-		       }
-	}
-	if (input->port->class == DDB_PORT_CI)
-		wake_up(&input->wq);
-	spin_unlock(&input->lock);
+		if (input->redirect)
+			input_write_output(input,
+					   input->redirect->port->output);
+		else
+			input_write_dvb(input, &input->dvb);
+	}
+	if (input->port->class == DDB_PORT_CI ||
+	    input->port->class == DDB_PORT_LOOP) {
+		if (input->redirect) {
+			if (input->redirect->port->class == DDB_PORT_TUNER)
+				input_write_dvb(input, &input->redirect->dvb);
+			else
+				input_write_output(input,
+						   input->redirect->port->output);
+		} else
+			wake_up(&dma->wq);
+	}
+	spin_unlock(&dma->lock);
 }
 
 static void output_tasklet(unsigned long data)
 {
 	struct ddb_output *output = (struct ddb_output *) data;
+	struct ddb_dma *dma = output->dma;
 	struct ddb *dev = output->port->dev;
 
-	spin_lock(&output->lock);
-	if (!output->running) {
-		spin_unlock(&output->lock);
+	spin_lock(&dma->lock);
+	if (!dma->running) {
+		spin_unlock(&dma->lock);
 		return;
 	}
-	output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
-	wake_up(&output->wq);
-	spin_unlock(&output->lock);
+	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
+	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
+	if (output->redirect)
+		output_ack_input(output, output->redirect);
+	wake_up(&dma->wq);
+	spin_unlock(&dma->lock);
+}
+
+#if 0
+static void io_tasklet(unsigned long data)
+{
+	struct ddb_dma *dma = (struct ddb_dma *) data;
+
+	spin_lock(&dma->lock);
+	if (!dma->running) {
+		spin_unlock(&dma->lock);
+		return;
+	}
+	dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
+	dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
+	if (dma->nr & 8)
+		handle_output((struct ddb_output *) dma->io);
+	else
+		handle_input((struct ddb_input *) dma->io);
+	wake_up(&dma->wq);
+	spin_unlock(&dma->lock);
+}
+#endif
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static int wait_ci_ready(struct ddb_ci *ci)
+{
+	u32 count = 100;
+
+	do {
+		if (ddbreadl(ci->port->dev,
+			     CI_CONTROL(ci->nr)) & CI_READY)
+			break;
+		msleep(1);
+		if ((--count) == 0)
+			return -1;
+	} while (1);
+	return 0;
+}
+
+static int read_attribute_mem(struct dvb_ca_en50221 *ca,
+			      int slot, int address)
+{
+	struct ddb_ci *ci = ca->data;
+	u32 val, off = (address >> 1) & (CI_BUFFER_SIZE-1);
+
+	if (address > CI_BUFFER_SIZE)
+		return -1;
+	ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address,
+		  CI_DO_READ_ATTRIBUTES(ci->nr));
+	wait_ci_ready(ci);
+	val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off);
+	/* printk("%04x: %02x\n", address, val); */
+	return val;
+}
+
+static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot,
+			       int address, u8 value)
+{
+	struct ddb_ci *ci = ca->data;
+
+	ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
+		  CI_DO_ATTRIBUTE_RW(ci->nr));
+	wait_ci_ready(ci);
+	return 0;
+}
+
+static int read_cam_control(struct dvb_ca_en50221 *ca,
+			    int slot, u8 address)
+{
+	u32 count = 100;
+	struct ddb_ci *ci = ca->data;
+	u32 res;
+
+	ddbwritel(ci->port->dev, CI_READ_CMD | address,
+		  CI_DO_IO_RW(ci->nr));
+	do {
+		res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr));
+		if (res & CI_READY)
+			break;
+		msleep(1);
+		if ((--count) == 0)
+			return -1;
+	} while (1);
+	return 0xff & res;
+}
+
+static int write_cam_control(struct dvb_ca_en50221 *ca, int slot,
+			     u8 address, u8 value)
+{
+	struct ddb_ci *ci = ca->data;
+
+	ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address,
+		  CI_DO_IO_RW(ci->nr));
+	wait_ci_ready(ci);
+	return 0;
 }
 
+static int slot_reset(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct ddb_ci *ci = ca->data;
+
+	printk(KERN_INFO "slot reset %d\n", ci->nr);
+	ddbwritel(ci->port->dev, CI_POWER_ON,
+		  CI_CONTROL(ci->nr));
+	msleep(300);
+	ddbwritel(ci->port->dev, CI_POWER_ON | CI_RESET_CAM,
+		  CI_CONTROL(ci->nr));
+	ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON | CI_RESET_CAM,
+		  CI_CONTROL(ci->nr));
+	udelay(20);
+	ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON,
+		  CI_CONTROL(ci->nr));
+	return 0;
+}
+
+static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct ddb_ci *ci = ca->data;
+
+	printk(KERN_INFO "slot shutdown\n");
+	ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr));
+	return 0;
+}
+
+static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
+{
+	struct ddb_ci *ci = ca->data;
+	u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
+
+	ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE,
+		  CI_CONTROL(ci->nr));
+	return 0;
+}
+
+static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
+{
+	struct ddb_ci *ci = ca->data;
+	u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr));
+	int stat = 0;
+
+	if (val & CI_CAM_DETECT)
+		stat |= DVB_CA_EN50221_POLL_CAM_PRESENT;
+	if (val & CI_CAM_READY)
+		stat |= DVB_CA_EN50221_POLL_CAM_READY;
+	return stat;
+}
+
+static struct dvb_ca_en50221 en_templ = {
+	.read_attribute_mem  = read_attribute_mem,
+	.write_attribute_mem = write_attribute_mem,
+	.read_cam_control    = read_cam_control,
+	.write_cam_control   = write_cam_control,
+	.slot_reset          = slot_reset,
+	.slot_shutdown       = slot_shutdown,
+	.slot_ts_enable      = slot_ts_enable,
+	.poll_slot_status    = poll_slot_status,
+};
+
+static void ci_attach(struct ddb_port *port)
+{
+	struct ddb_ci *ci = 0;
+
+	ci = kzalloc(sizeof(*ci), GFP_KERNEL);
+	if (!ci)
+		return;
+	memcpy(&ci->en, &en_templ, sizeof(en_templ));
+	ci->en.data = ci;
+	port->en = &ci->en;
+	ci->port = port;
+	ci->nr = port->nr - 2;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
 
 struct cxd2099_cfg cxd_cfg = {
 	.bitrate =  62000,
@@ -1049,28 +1704,22 @@
 
 static int ddb_ci_attach(struct ddb_port *port)
 {
-	int ret;
-
-	ret = dvb_register_adapter(&port->output->adap,
-				   "DDBridge",
-				   THIS_MODULE,
-				   &port->dev->pdev->dev,
-				   adapter_nr);
-	if (ret < 0)
-		return ret;
-	port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
-	if (!port->en) {
-		dvb_unregister_adapter(&port->output->adap);
-		return -ENODEV;
+	if (port->type == DDB_CI_EXTERNAL_SONY) {
+		port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
+		if (!port->en)
+			return -ENODEV;
+		dvb_ca_en50221_init(port->input[0]->dvb.adap,
+				    port->en, 0, 1);
 	}
-	ddb_input_start(port->input[0]);
-	ddb_output_start(port->output);
-	dvb_ca_en50221_init(&port->output->adap,
-			    port->en, 0, 1);
-	ret = dvb_register_device(&port->output->adap, &port->output->dev,
-				  &dvbdev_ci, (void *) port->output,
-				  DVB_DEVICE_SEC);
-	return ret;
+#if 1
+	if (port->type == DDB_CI_INTERNAL) {
+		ci_attach(port);
+		if (!port->en)
+			return -ENODEV;
+		dvb_ca_en50221_init(port->input[0]->dvb.adap, port->en, 0, 1);
+	}
+#endif
+	return 0;
 }
 
 static int ddb_port_attach(struct ddb_port *port)
@@ -1086,6 +1735,15 @@
 		break;
 	case DDB_PORT_CI:
 		ret = ddb_ci_attach(port);
+		if (ret < 0)
+			break;
+	case DDB_PORT_LOOP:
+		ddb_input_start(port->input[0]);
+		ddb_output_start(port->output);
+		ret = dvb_register_device(port->input[0]->dvb.adap,
+					  &port->input[0]->dvb.dev,
+					  &dvbdev_ci, (void *) port->output,
+					  DVB_DEVICE_SEC);
 		break;
 	default:
 		break;
@@ -1100,6 +1758,10 @@
 	int i, ret = 0;
 	struct ddb_port *port;
 
+	ret = dvb_register_adapters(dev);
+	if (ret < 0)
+		return ret;
+
 	for (i = 0; i < dev->info->port_num; i++) {
 		port = &dev->port[i];
 		ret = ddb_port_attach(port);
@@ -1122,25 +1784,26 @@
 			dvb_input_detach(port->input[1]);
 			break;
 		case DDB_PORT_CI:
-			if (port->output->dev)
-				dvb_unregister_device(port->output->dev);
+		case DDB_PORT_LOOP:
+			if (port->input[0]->dvb.dev)
+				dvb_unregister_device(port->input[0]->dvb.dev);
+			ddb_input_stop(port->input[0]);
+			ddb_output_stop(port->output);
 			if (port->en) {
-				ddb_input_stop(port->input[0]);
-				ddb_output_stop(port->output);
 				dvb_ca_en50221_release(port->en);
 				kfree(port->en);
 				port->en = 0;
-				dvb_unregister_adapter(&port->output->adap);
 			}
 			break;
 		}
 	}
+	dvb_unregister_adapters(dev);
 }
 
 /****************************************************************************/
 /****************************************************************************/
 
-static int port_has_ci(struct ddb_port *port)
+static int port_has_cxd(struct ddb_port *port)
 {
 	u8 val;
 	return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
@@ -1172,6 +1835,21 @@
 	return 1;
 }
 
+static int port_has_stv0367(struct ddb_port *port)
+{
+	u8 val;
+
+	if (i2c_read_reg16(&port->i2c->adap, 0x1e, 0xf000, &val) < 0)
+		return 0;
+	if (val != 0x60)
+		return 0;
+	if (i2c_read_reg16(&port->i2c->adap, 0x1f, 0xf000, &val) < 0)
+		return 0;
+	if (val != 0x60)
+		return 0;
+	return 1;
+}
+
 static void ddb_port_probe(struct ddb_port *port)
 {
 	struct ddb *dev = port->dev;
@@ -1179,62 +1857,92 @@
 
 	port->class = DDB_PORT_NONE;
 
-	if (port_has_ci(port)) {
+	if (port->nr > 1 && dev->info->type == DDB_OCTOPUS_CI) {
+		modname = "CI internal";
+		port->class = DDB_PORT_CI;
+		port->type = DDB_CI_INTERNAL;
+	} else if (port_has_cxd(port)) {
 		modname = "CI";
 		port->class = DDB_PORT_CI;
-		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+		port->type = DDB_CI_EXTERNAL_SONY;
+		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
 	} else if (port_has_stv0900(port)) {
 		modname = "DUAL DVB-S2";
 		port->class = DDB_PORT_TUNER;
 		port->type = DDB_TUNER_DVBS_ST;
-		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
 	} else if (port_has_stv0900_aa(port)) {
 		modname = "DUAL DVB-S2";
 		port->class = DDB_PORT_TUNER;
 		port->type = DDB_TUNER_DVBS_ST_AA;
-		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
 	} else if (port_has_drxks(port)) {
 		modname = "DUAL DVB-C/T";
 		port->class = DDB_PORT_TUNER;
 		port->type = DDB_TUNER_DVBCT_TR;
-		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_stv0367(port)) {
+		modname = "DUAL DVB-C/T";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBCT_ST;
+		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+	} else if (port->nr == ts_loop) {
+		modname = "TS LOOP";
+		port->class = DDB_PORT_LOOP;
+	}
+	printk(KERN_INFO "Port %d (TAB %d): %s\n", port->nr, port->nr+1, modname);
+}
+
+static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io)
+{
+	unsigned long priv = (unsigned long) io;
+
+	dma->io = io;
+	dma->nr = nr;
+	spin_lock_init(&dma->lock);
+	init_waitqueue_head(&dma->wq);
+	if (nr & 8) {
+		tasklet_init(&dma->tasklet, output_tasklet, priv);
+		dma->num = OUTPUT_DMA_BUFS;
+		dma->size = OUTPUT_DMA_SIZE;
+		dma->div = OUTPUT_DMA_IRQ_DIV;
+	} else {
+		tasklet_init(&dma->tasklet, input_tasklet, priv);
+		dma->num = INPUT_DMA_BUFS;
+		dma->size = INPUT_DMA_SIZE;
+		dma->div = INPUT_DMA_IRQ_DIV;
 	}
-	printk(KERN_INFO "Port %d (TAB %d): %s\n",
-			 port->nr, port->nr+1, modname);
 }
 
-static void ddb_input_init(struct ddb_port *port, int nr)
+static void ddb_input_init(struct ddb_port *port, int nr, int pnr)
 {
 	struct ddb *dev = port->dev;
 	struct ddb_input *input = &dev->input[nr];
 
+	port->input[pnr] = input;
 	input->nr = nr;
 	input->port = port;
-	input->dma_buf_num = INPUT_DMA_BUFS;
-	input->dma_buf_size = INPUT_DMA_SIZE;
-	ddbwritel(0, TS_INPUT_CONTROL(nr));
-	ddbwritel(2, TS_INPUT_CONTROL(nr));
-	ddbwritel(0, TS_INPUT_CONTROL(nr));
-	ddbwritel(0, DMA_BUFFER_ACK(nr));
-	tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input);
-	spin_lock_init(&input->lock);
-	init_waitqueue_head(&input->wq);
+	input->dma = &dev->dma[nr];
+	ddb_dma_init(input->dma, nr, (void *) input);
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
+	ddbwritel(dev, 2, TS_INPUT_CONTROL(nr));
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
+	ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr));
+	input->dvb.adap = &dev->adap[input->nr];
 }
 
 static void ddb_output_init(struct ddb_port *port, int nr)
 {
 	struct ddb *dev = port->dev;
 	struct ddb_output *output = &dev->output[nr];
+	port->output = output;
 	output->nr = nr;
 	output->port = port;
-	output->dma_buf_num = OUTPUT_DMA_BUFS;
-	output->dma_buf_size = OUTPUT_DMA_SIZE;
-
-	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
-	ddbwritel(2, TS_OUTPUT_CONTROL(nr));
-	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
-	tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output);
-	init_waitqueue_head(&output->wq);
+	output->dma = &dev->dma[nr + 8];
+	ddb_dma_init(output->dma, nr + 8, (void *) output);
+	ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
+	ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr));
+	ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
 }
 
 static void ddb_ports_init(struct ddb *dev)
@@ -1247,14 +1955,16 @@
 		port->dev = dev;
 		port->nr = i;
 		port->i2c = &dev->i2c[i];
-		port->input[0] = &dev->input[2 * i];
-		port->input[1] = &dev->input[2 * i + 1];
-		port->output = &dev->output[i];
 
 		mutex_init(&port->i2c_gate_lock);
 		ddb_port_probe(port);
-		ddb_input_init(port, 2 * i);
-		ddb_input_init(port, 2 * i + 1);
+		if (i >= 2 && dev->info->type == DDB_OCTOPUS_CI) {
+			ddb_input_init(port, 2 + i, 0);
+			ddb_input_init(port, 4 + i, 1);
+		} else {
+			ddb_input_init(port, 2 * i, 0);
+			ddb_input_init(port, 2 * i + 1, 1);
+		}
 		ddb_output_init(port, i);
 	}
 }
@@ -1267,9 +1977,12 @@
 	for (i = 0; i < dev->info->port_num; i++) {
 		port = &dev->port[i];
 		port->dev = dev;
-		tasklet_kill(&port->input[0]->tasklet);
-		tasklet_kill(&port->input[1]->tasklet);
-		tasklet_kill(&port->output->tasklet);
+		if (port->input[0])
+			tasklet_kill(&port->input[0]->dma->tasklet);
+		if (port->input[1])
+			tasklet_kill(&port->input[1]->dma->tasklet);
+		if (port->output)
+			tasklet_kill(&port->output->dma->tasklet);
 	}
 }
 
@@ -1288,13 +2001,18 @@
 static irqreturn_t irq_handler(int irq, void *dev_id)
 {
 	struct ddb *dev = (struct ddb *) dev_id;
-	u32 s = ddbreadl(INTERRUPT_STATUS);
+	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
 
 	if (!s)
 		return IRQ_NONE;
 
 	do {
-		ddbwritel(s, INTERRUPT_ACK);
+		ddbwritel(dev, s, INTERRUPT_ACK);
+
+		if (s & 0x0000000f)
+			dev->i2c_irq++;
+		if (s & 0x000fff00)
+			dev->ts_irq++;
 
 		if (s & 0x00000001)
 			irq_handle_i2c(dev, 0);
@@ -1306,33 +2024,32 @@
 			irq_handle_i2c(dev, 3);
 
 		if (s & 0x00000100)
-			tasklet_schedule(&dev->input[0].tasklet);
+			tasklet_schedule(&dev->dma[0].tasklet);
 		if (s & 0x00000200)
-			tasklet_schedule(&dev->input[1].tasklet);
+			tasklet_schedule(&dev->dma[1].tasklet);
 		if (s & 0x00000400)
-			tasklet_schedule(&dev->input[2].tasklet);
+			tasklet_schedule(&dev->dma[2].tasklet);
 		if (s & 0x00000800)
-			tasklet_schedule(&dev->input[3].tasklet);
+			tasklet_schedule(&dev->dma[3].tasklet);
 		if (s & 0x00001000)
-			tasklet_schedule(&dev->input[4].tasklet);
+			tasklet_schedule(&dev->dma[4].tasklet);
 		if (s & 0x00002000)
-			tasklet_schedule(&dev->input[5].tasklet);
+			tasklet_schedule(&dev->dma[5].tasklet);
 		if (s & 0x00004000)
-			tasklet_schedule(&dev->input[6].tasklet);
+			tasklet_schedule(&dev->dma[6].tasklet);
 		if (s & 0x00008000)
-			tasklet_schedule(&dev->input[7].tasklet);
-
+			tasklet_schedule(&dev->dma[7].tasklet);
 		if (s & 0x00010000)
-			tasklet_schedule(&dev->output[0].tasklet);
+			tasklet_schedule(&dev->dma[8].tasklet);
 		if (s & 0x00020000)
-			tasklet_schedule(&dev->output[1].tasklet);
+			tasklet_schedule(&dev->dma[9].tasklet);
 		if (s & 0x00040000)
-			tasklet_schedule(&dev->output[2].tasklet);
+			tasklet_schedule(&dev->dma[10].tasklet);
 		if (s & 0x00080000)
-			tasklet_schedule(&dev->output[3].tasklet);
+			tasklet_schedule(&dev->dma[11].tasklet);
 
-		/* if (s & 0x000f0000)	printk(KERN_DEBUG "%08x\n", istat); */
-	} while ((s = ddbreadl(INTERRUPT_STATUS)));
+		/* if (s & 0x000f0000)	printk("%08x\n", istat); */
+	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
 
 	return IRQ_HANDLED;
 }
@@ -1346,21 +2063,21 @@
 	u32 data, shift;
 
 	if (wlen > 4)
-		ddbwritel(1, SPI_CONTROL);
+		ddbwritel(dev, 1, SPI_CONTROL);
 	while (wlen > 4) {
 		/* FIXME: check for big-endian */
 		data = swab32(*(u32 *)wbuf);
 		wbuf += 4;
 		wlen -= 4;
-		ddbwritel(data, SPI_DATA);
-		while (ddbreadl(SPI_CONTROL) & 0x0004)
+		ddbwritel(dev, data, SPI_DATA);
+		while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
 			;
 	}
 
 	if (rlen)
-		ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
+		ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
 	else
-		ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
+		ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
 
 	data = 0;
 	shift = ((4 - wlen) * 8);
@@ -1372,33 +2089,33 @@
 	}
 	if (shift)
 		data <<= shift;
-	ddbwritel(data, SPI_DATA);
-	while (ddbreadl(SPI_CONTROL) & 0x0004)
+	ddbwritel(dev, data, SPI_DATA);
+	while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
 		;
 
 	if (!rlen) {
-		ddbwritel(0, SPI_CONTROL);
+		ddbwritel(dev, 0, SPI_CONTROL);
 		return 0;
 	}
 	if (rlen > 4)
-		ddbwritel(1, SPI_CONTROL);
+		ddbwritel(dev, 1, SPI_CONTROL);
 
 	while (rlen > 4) {
-		ddbwritel(0xffffffff, SPI_DATA);
-		while (ddbreadl(SPI_CONTROL) & 0x0004)
+		ddbwritel(dev, 0xffffffff, SPI_DATA);
+		while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
 			;
-		data = ddbreadl(SPI_DATA);
+		data = ddbreadl(dev, SPI_DATA);
 		*(u32 *) rbuf = swab32(data);
 		rbuf += 4;
 		rlen -= 4;
 	}
-	ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
-	ddbwritel(0xffffffff, SPI_DATA);
-	while (ddbreadl(SPI_CONTROL) & 0x0004)
+	ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
+	ddbwritel(dev, 0xffffffff, SPI_DATA);
+	while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
 		;
 
-	data = ddbreadl(SPI_DATA);
-	ddbwritel(0, SPI_CONTROL);
+	data = ddbreadl(dev, SPI_DATA);
+	ddbwritel(dev, 0, SPI_CONTROL);
 
 	if (rlen < 4)
 		data <<= ((4 - rlen) * 8);
@@ -1421,14 +2138,21 @@
 	__u32 read_len;
 };
 
+struct ddb_gpio {
+	__u32 mask;
+	__u32 data;
+};
+
+
 #define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
+#define IOCTL_DDB_GPIO_IN  _IOWR(DDB_MAGIC, 0x01, struct ddb_gpio)
+#define IOCTL_DDB_GPIO_OUT _IOWR(DDB_MAGIC, 0x02, struct ddb_gpio)
 
 #define DDB_NAME "ddbridge"
 
 static u32 ddb_num;
-static struct ddb *ddbs[32];
-static struct class *ddb_class;
 static int ddb_major;
+static DEFINE_MUTEX(ddb_mutex);
 
 static int ddb_open(struct inode *inode, struct file *file)
 {
@@ -1470,6 +2194,16 @@
 			return -EFAULT;
 		break;
 	}
+	case IOCTL_DDB_GPIO_OUT:
+	{
+		struct ddb_gpio gpio;
+		if (copy_from_user(&gpio, parg, sizeof(gpio)))
+			break;
+		ddbwritel(dev, gpio.mask, GPIO_DIRECTION);
+		ddbwritel(dev, gpio.data, GPIO_OUTPUT);
+		res = 0;
+		break;
+	}
 	default:
 		return -ENOTTY;
 	}
@@ -1481,41 +2215,248 @@
 	.open           = ddb_open,
 };
 
-static char *ddb_devnode(struct device *device, umode_t *mode)
+static char *ddb_devnode(struct device *device, mode_t *mode)
 {
 	struct ddb *dev = dev_get_drvdata(device);
 
 	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
 }
 
+static ssize_t ports_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "%d\n", dev->info->port_num);
+}
+
+static ssize_t ts_irq_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "%d\n", dev->ts_irq);
+}
+
+static ssize_t i2c_irq_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "%d\n", dev->i2c_irq);
+}
+
+static char *class_name[] = {
+	"NONE", "CI", "TUNER", "LOOP"
+};
+
+static char *type_name[] = {
+	"NONE", "DVBS_ST", "DVBS_ST_AA", "DVBCT_TR", "DVBCT_ST", "INTERNAL", "CXD2099",
+};
+
+static ssize_t fan_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	u32 val;
+
+	val = ddbreadl(dev, GPIO_OUTPUT) & 1;
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t fan_store(struct device *device, struct device_attribute *d,
+			 const char *buf, size_t count)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	unsigned val;
+
+	if (sscanf(buf, "%u\n", &val) != 1)
+		return -EINVAL;
+	ddbwritel(dev, 1, GPIO_DIRECTION);
+	ddbwritel(dev, val & 1, GPIO_OUTPUT);
+	return count;
+}
+
+static ssize_t temp_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	int temp;
+	u8 tmp[2];
+
+	if (!dev->info->temp_num)
+		return sprintf(buf, "no sensor\n");
+	if (i2c_read_regs(&dev->i2c[0].adap, 0x48, 0, tmp, 2) < 0)
+		return sprintf(buf, "read_error\n");
+	temp = (tmp[0] << 3) | (tmp[1] >> 5);
+	temp *= 125;
+	return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t mod_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	int num = attr->attr.name[3] - 0x30;
+
+	return sprintf(buf, "%s:%s\n",
+		       class_name[dev->port[num].class],
+		       type_name[dev->port[num].type]);
+}
+
+static ssize_t led_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	int num = attr->attr.name[3] - 0x30;
+
+	return sprintf(buf, "%d\n", dev->leds & (1 << num) ? 1 : 0);
+}
+
+
+static void ddb_set_led(struct ddb *dev, int num, int val)
+{
+	if (!dev->info->led_num)
+		return;
+	switch (dev->port[num].class) {
+	case DDB_PORT_TUNER:
+		switch (dev->port[num].type) {
+		case DDB_TUNER_DVBS_ST:
+			printk(KERN_INFO "LED %d %d\n", num, val);
+			i2c_write_reg16(&dev->i2c[num].adap,
+					0x69, 0xf14c, val ? 2 : 0);
+			break;
+		case DDB_TUNER_DVBCT_ST:
+			printk(KERN_INFO "LED %d %d\n", num, val);
+			i2c_write_reg16(&dev->i2c[num].adap,
+					0x1f, 0xf00e, 0);
+			i2c_write_reg16(&dev->i2c[num].adap,
+					0x1f, 0xf00f, val ? 1 : 0);
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static ssize_t led_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	int num = attr->attr.name[3] - 0x30;
+	unsigned val;
+
+	if (sscanf(buf, "%u\n", &val) != 1)
+		return -EINVAL;
+	if (val)
+		dev->leds |= (1 << num);
+	else
+		dev->leds &= ~(1 << num);
+	ddb_set_led(dev, num, val);
+	return count;
+}
+
+static ssize_t snr_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	char snr[32];
+	int num = attr->attr.name[3] - 0x30;
+
+	/* serial number at 0x100-0x11f */
+	if (i2c_read_regs16(&dev->i2c[num].adap, 0x57, 0x100, snr, 32) < 0)
+		return sprintf(buf, "NO SNR\n");
+	snr[31] = 0; /* in case it is not terminated on EEPROM */
+	return sprintf(buf, "%s\n", snr);
+}
+
+
+static ssize_t snr_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	int num = attr->attr.name[3] - 0x30;
+	u8 snr[34] = { 0x01, 0x00 };
+
+	if (count > 31)
+		return -EINVAL;
+	memcpy(snr + 2, buf, count);
+	i2c_write(&dev->i2c[num].adap, 0x57, snr, 34);
+	return count;
+}
+
+static ssize_t redirect_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	return 0;
+}
+
+static ssize_t redirect_store(struct device *device, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	unsigned int i, p;
+	int res;
+
+	if (sscanf(buf, "%x %x\n", &i, &p) != 2)
+		return -EINVAL;
+	printk(KERN_INFO "redirect: %02x, %02x\n", i, p);
+	res = set_redirect(i, p);
+	if (res < 0)
+		return res;
+	return count;
+}
+
+#define __ATTR_MRO(_name, _show) {				\
+	.attr	= { .name = __stringify(_name), .mode = 0444 },	\
+	.show	= _show,					\
+}
+
+struct device_attribute ddb_attrs[] = {
+	__ATTR_RO(ports),
+	__ATTR_RO(ts_irq),
+	__ATTR_RO(i2c_irq),
+	__ATTR_MRO(mod0, mod_show),
+	__ATTR_MRO(mod1, mod_show),
+	__ATTR_MRO(mod2, mod_show),
+	__ATTR_MRO(mod3, mod_show),
+	__ATTR_RO(temp),
+	__ATTR(fan, 0666, fan_show, fan_store),
+	__ATTR(led0, 0666, led_show, led_store),
+	__ATTR(led1, 0666, led_show, led_store),
+	__ATTR(led2, 0666, led_show, led_store),
+	__ATTR(led3, 0666, led_show, led_store),
+	__ATTR(snr0, 0666, snr_show, snr_store),
+	__ATTR(snr1, 0666, snr_show, snr_store),
+	__ATTR(snr2, 0666, snr_show, snr_store),
+	__ATTR(snr3, 0666, snr_show, snr_store),
+	__ATTR(redirect, 0666, redirect_show, redirect_store),
+	__ATTR_NULL
+};
+
+static struct class ddb_class = {
+	.name		= "ddbridge",
+	.owner          = THIS_MODULE,
+	.dev_attrs	= ddb_attrs,
+	.devnode        = ddb_devnode,
+};
+
 static int ddb_class_create(void)
 {
 	ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops);
 	if (ddb_major < 0)
 		return ddb_major;
-
-	ddb_class = class_create(THIS_MODULE, DDB_NAME);
-	if (IS_ERR(ddb_class)) {
-		unregister_chrdev(ddb_major, DDB_NAME);
+	if (class_register(&ddb_class) < 0)
 		return -1;
-	}
-	ddb_class->devnode = ddb_devnode;
 	return 0;
 }
 
 static void ddb_class_destroy(void)
 {
-	class_destroy(ddb_class);
+	class_unregister(&ddb_class);
 	unregister_chrdev(ddb_major, DDB_NAME);
 }
 
 static int ddb_device_create(struct ddb *dev)
 {
+	mutex_lock(&ddb_mutex);
 	dev->nr = ddb_num++;
-	dev->ddb_dev = device_create(ddb_class, NULL,
+	ddbs[dev->nr] = dev;
+	mutex_unlock(&ddb_mutex);
+	dev->ddb_dev = device_create(&ddb_class, &dev->pdev->dev,
 				     MKDEV(ddb_major, dev->nr),
 				     dev, "ddbridge%d", dev->nr);
-	ddbs[dev->nr] = dev;
 	if (IS_ERR(dev->ddb_dev))
 		return -1;
 	return 0;
@@ -1523,10 +2464,9 @@
 
 static void ddb_device_destroy(struct ddb *dev)
 {
-	ddb_num--;
 	if (IS_ERR(dev->ddb_dev))
 		return;
-	device_destroy(ddb_class, MKDEV(ddb_major, 0));
+	device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr));
 }
 
 
@@ -1549,7 +2489,7 @@
 	ddb_ports_detach(dev);
 	ddb_i2c_release(dev);
 
-	ddbwritel(0, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0, INTERRUPT_ENABLE);
 	free_irq(dev->pdev->irq, dev);
 #ifdef CONFIG_PCI_MSI
 	if (dev->msi)
@@ -1564,7 +2504,6 @@
 	pci_disable_device(pdev);
 }
 
-
 static int __devinit ddb_probe(struct pci_dev *pdev,
 			       const struct pci_device_id *id)
 {
@@ -1575,10 +2514,9 @@
 	if (pci_enable_device(pdev) < 0)
 		return -ENODEV;
 
-	dev = vmalloc(sizeof(struct ddb));
+	dev = vzalloc(sizeof(struct ddb));
 	if (dev == NULL)
 		return -ENOMEM;
-	memset(dev, 0, sizeof(struct ddb));
 
 	dev->pdev = pdev;
 	pci_set_drvdata(pdev, dev);
@@ -1591,7 +2529,8 @@
 		stat = -ENOMEM;
 		goto fail;
 	}
-	printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
+	printk(KERN_INFO "HW %08x REG %08x\n",
+	       ddbreadl(dev, 0), ddbreadl(dev, 4));
 
 #ifdef CONFIG_PCI_MSI
 	if (pci_msi_enabled())
@@ -1607,11 +2546,11 @@
 			   irq_flag, "DDBridge", (void *) dev);
 	if (stat < 0)
 		goto fail1;
-	ddbwritel(0, DMA_BASE_WRITE);
-	ddbwritel(0, DMA_BASE_READ);
-	ddbwritel(0xffffffff, INTERRUPT_ACK);
-	ddbwritel(0xfff0f, INTERRUPT_ENABLE);
-	ddbwritel(0, MSI1_ENABLE);
+	ddbwritel(dev, 0, DMA_BASE_WRITE);
+	ddbwritel(dev, 0, DMA_BASE_READ);
+	ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);
+	ddbwritel(dev, 0x000fff0f, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0, MSI1_ENABLE);
 
 	if (ddb_i2c_init(dev) < 0)
 		goto fail1;
@@ -1622,7 +2561,13 @@
 	}
 	if (ddb_ports_attach(dev) < 0)
 		goto fail3;
+
 	ddb_device_create(dev);
+
+	if (dev->info->fan_num)	{
+		ddbwritel(dev, 1, GPIO_DIRECTION);
+		ddbwritel(dev, 1, GPIO_OUTPUT);
+	}
 	return 0;
 
 fail3:
@@ -1632,11 +2577,14 @@
 fail2:
 	printk(KERN_ERR "fail2\n");
 	ddb_buffers_free(dev);
+	ddb_i2c_release(dev);
 fail1:
 	printk(KERN_ERR "fail1\n");
+	free_irq(dev->pdev->irq, dev);
+#ifdef CONFIG_PCI_MSI
 	if (dev->msi)
 		pci_disable_msi(dev->pdev);
-	free_irq(dev->pdev->irq, dev);
+#endif
 fail:
 	printk(KERN_ERR "fail\n");
 	ddb_unmap(dev);
@@ -1658,23 +2606,71 @@
 	.type     = DDB_OCTOPUS,
 	.name     = "Digital Devices Octopus DVB adapter",
 	.port_num = 4,
+	.i2c_num  = 4,
 };
 
 static struct ddb_info ddb_octopus_le = {
 	.type     = DDB_OCTOPUS,
 	.name     = "Digital Devices Octopus LE DVB adapter",
 	.port_num = 2,
+	.i2c_num  = 2,
+};
+
+static struct ddb_info ddb_octopus_oem = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus OEM",
+	.port_num = 4,
+	.i2c_num  = 4,
+	.led_num  = 1,
+	.fan_num  = 1,
+	.temp_num = 1,
+};
+
+static struct ddb_info ddb_octopus_mini = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus Mini",
+	.port_num = 4,
+	.i2c_num  = 4,
 };
 
 static struct ddb_info ddb_v6 = {
 	.type     = DDB_OCTOPUS,
 	.name     = "Digital Devices Cine S2 V6 DVB adapter",
 	.port_num = 3,
+	.i2c_num  = 3,
+};
+
+static struct ddb_info ddb_dvbct = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices DVBCT V6.1 DVB adapter",
+	.port_num = 3,
+	.i2c_num  = 3,
+};
+
+static struct ddb_info ddb_satixS2v3 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Mystique SaTiX-S2 V3 DVB adapter",
+	.port_num = 3,
+	.i2c_num  = 3,
+};
+
+static struct ddb_info ddb_ci = {
+	.type     = DDB_OCTOPUS_CI,
+	.name     = "Digital Devices Octopus CI",
+	.port_num = 4,
+	.i2c_num  = 2,
+};
+
+static struct ddb_info ddb_cis = {
+	.type     = DDB_OCTOPUS_CI,
+	.name     = "Digital Devices Octopus CI single",
+	.port_num = 3,
+	.i2c_num  = 2,
 };
 
 #define DDVID 0xdd01 /* Digital Devices Vendor ID */
 
-#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {	\
+#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \
 	.vendor      = _vend,    .device    = _dev, \
 	.subvendor   = _subvend, .subdevice = _subdev, \
 	.driver_data = (unsigned long)&_driverdata }
@@ -1683,8 +2679,13 @@
 	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0003, ddb_octopus_oem),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus_mini),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
+	DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
+	DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci),
+	DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis),
 	/* in case sub-ids got deleted in flash */
 	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
 	{0}
@@ -1696,16 +2697,21 @@
 	.name        = "DDBridge",
 	.id_table    = ddb_id_tbl,
 	.probe       = ddb_probe,
-	.remove      = __devexit_p(ddb_remove),
+	.remove      = ddb_remove,
 };
 
 static __init int module_init_ddbridge(void)
 {
+	int stat;
+
 	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
 	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
 	if (ddb_class_create())
 		return -1;
-	return pci_register_driver(&ddb_pci_driver);
+	stat = pci_register_driver(&ddb_pci_driver);
+	if (stat < 0)
+		ddb_class_destroy();
+	return stat;
 }
 
 static __exit void module_exit_ddbridge(void)
@@ -1720,4 +2726,4 @@
 MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
 MODULE_AUTHOR("Ralph Metzler");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0.5");
+MODULE_VERSION("0.8");
diff -Naur linux-3.6.8/drivers/media/dvb/ddbridge/ddbridge.h linux-3.6.8.patch/drivers/media/dvb/ddbridge/ddbridge.h
--- linux-3.6.8/drivers/media/dvb/ddbridge/ddbridge.h	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ddbridge/ddbridge.h	2012-12-03 08:41:17.000000000 +0100
@@ -32,7 +32,10 @@
 #include <asm/dma.h>
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/ca.h>
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
 #include <linux/socket.h>
+#include <linux/device.h>
 
 #include "dmxdev.h"
 #include "dvbdev.h"
@@ -52,43 +55,53 @@
 	int   type;
 #define DDB_NONE         0
 #define DDB_OCTOPUS      1
+#define DDB_OCTOPUS_CI   2
 	char *name;
 	int   port_num;
-	u32   port_type[DDB_MAX_PORT];
+	int   i2c_num;
+	int   led_num;
+	int   fan_num;
+	int   temp_num;
 };
 
 /* DMA_SIZE MUST be divisible by 188 and 128 !!! */
 
-#define INPUT_DMA_MAX_BUFS 32      /* hardware table limit */
+#define DMA_MAX_BUFS 32      /* hardware table limit */
+
 #define INPUT_DMA_BUFS 8
 #define INPUT_DMA_SIZE (128*47*21)
+#define INPUT_DMA_IRQ_DIV 1
 
-#define OUTPUT_DMA_MAX_BUFS 32
 #define OUTPUT_DMA_BUFS 8
 #define OUTPUT_DMA_SIZE (128*47*21)
+#define OUTPUT_DMA_IRQ_DIV 1
 
 struct ddb;
 struct ddb_port;
 
-struct ddb_input {
-	struct ddb_port       *port;
+struct ddb_dma {
+	void                  *io;
 	u32                    nr;
-	int                    attached;
-
-	dma_addr_t             pbuf[INPUT_DMA_MAX_BUFS];
-	u8                    *vbuf[INPUT_DMA_MAX_BUFS];
-	u32                    dma_buf_num;
-	u32                    dma_buf_size;
+	dma_addr_t             pbuf[DMA_MAX_BUFS];
+	u8                    *vbuf[DMA_MAX_BUFS];
+	u32                    num;
+	u32                    size;
+	u32                    div;
+	u32                    bufreg;
 
 	struct tasklet_struct  tasklet;
 	spinlock_t             lock;
 	wait_queue_head_t      wq;
 	int                    running;
 	u32                    stat;
+	u32                    ctrl;
 	u32                    cbuf;
 	u32                    coff;
+};
 
-	struct dvb_adapter     adap;
+struct ddb_dvb {
+	struct dvb_adapter    *adap;
+	int                    adap_registered;
 	struct dvb_device     *dev;
 	struct dvb_frontend   *fe;
 	struct dvb_frontend   *fe2;
@@ -99,32 +112,36 @@
 	struct dmx_frontend    mem_frontend;
 	int                    users;
 	int (*gate_ctrl)(struct dvb_frontend *, int);
+	int                    attached;
 };
 
-struct ddb_output {
+struct ddb_ci {
+	struct dvb_ca_en50221  en;
 	struct ddb_port       *port;
 	u32                    nr;
-	dma_addr_t             pbuf[OUTPUT_DMA_MAX_BUFS];
-	u8                    *vbuf[OUTPUT_DMA_MAX_BUFS];
-	u32                    dma_buf_num;
-	u32                    dma_buf_size;
-	struct tasklet_struct  tasklet;
-	spinlock_t             lock;
-	wait_queue_head_t      wq;
-	int                    running;
-	u32                    stat;
-	u32                    cbuf;
-	u32                    coff;
+};
 
-	struct dvb_adapter     adap;
-	struct dvb_device     *dev;
+
+struct ddb_input {
+	struct ddb_port       *port;
+	u32                    nr;
+	struct ddb_dma        *dma;
+	struct ddb_input      *redirect;
+
+	struct ddb_dvb         dvb;
+};
+
+struct ddb_output {
+	struct ddb_port       *port;
+	u32                    nr;
+	struct ddb_dma        *dma;
+	struct ddb_input      *redirect;
 };
 
 struct ddb_i2c {
 	struct ddb            *dev;
 	u32                    nr;
 	struct i2c_adapter     adap;
-	struct i2c_adapter     adap2;
 	u32                    regs;
 	u32                    rbuf;
 	u32                    wbuf;
@@ -141,12 +158,15 @@
 #define DDB_PORT_NONE           0
 #define DDB_PORT_CI             1
 #define DDB_PORT_TUNER          2
+#define DDB_PORT_LOOP           3
 	u32                    type;
 #define DDB_TUNER_NONE          0
 #define DDB_TUNER_DVBS_ST       1
 #define DDB_TUNER_DVBS_ST_AA    2
-#define DDB_TUNER_DVBCT_TR     16
-#define DDB_TUNER_DVBCT_ST     17
+#define DDB_TUNER_DVBCT_TR      3
+#define DDB_TUNER_DVBCT_ST      4
+#define DDB_CI_INTERNAL         5
+#define DDB_CI_EXTERNAL_SONY    6
 	u32                    adr;
 
 	struct ddb_input      *input[2];
@@ -161,25 +181,20 @@
 	struct ddb_i2c         i2c[DDB_MAX_I2C];
 	struct ddb_input       input[DDB_MAX_INPUT];
 	struct ddb_output      output[DDB_MAX_OUTPUT];
+	struct dvb_adapter     adap[DDB_MAX_INPUT];
+	struct ddb_dma         dma[DDB_MAX_INPUT + DDB_MAX_OUTPUT];
 
 	struct device         *ddb_dev;
-	int                    nr;
+	u32                    nr;
 	u8                     iobuf[1028];
 
 	struct ddb_info       *info;
 	int                    msi;
-};
-
-/****************************************************************************/
 
-#define ddbwritel(_val, _adr)        writel((_val), \
-				     (char *) (dev->regs+(_adr)))
-#define ddbreadl(_adr)               readl((char *) (dev->regs+(_adr)))
-#define ddbcpyto(_adr, _src, _count) memcpy_toio((char *)	\
-				     (dev->regs+(_adr)), (_src), (_count))
-#define ddbcpyfrom(_dst, _adr, _count) memcpy_fromio((_dst), (char *) \
-				       (dev->regs+(_adr)), (_count))
+	u8                     leds;
 
-/****************************************************************************/
+	u32                    ts_irq;
+	u32                    i2c_irq;
+};
 
 #endif
diff -Naur linux-3.6.8/drivers/media/dvb/ddbridge/ddbridge-regs.h linux-3.6.8.patch/drivers/media/dvb/ddbridge/ddbridge-regs.h
--- linux-3.6.8/drivers/media/dvb/ddbridge/ddbridge-regs.h	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ddbridge/ddbridge-regs.h	2012-12-03 08:41:17.000000000 +0100
@@ -21,11 +21,12 @@
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  */
 
-/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */
+/* DD-DVBBridgeV1.h 388 2011-07-13 20:47:08Z manfred */
 
 /* Register Definitions */
 
-#define CUR_REGISTERMAP_VERSION 0x10000
+#define CUR_REGISTERMAP_VERSION     0x10003
+#define CUR_REGISTERMAP_VERSION_CI  0x10000
 
 #define HARDWARE_VERSION       0x00
 #define REGISTERMAP_VERSION    0x04
@@ -36,8 +37,14 @@
 #define SPI_CONTROL     0x10
 #define SPI_DATA        0x14
 
-/* ------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* GPIO */
+
+#define GPIO_OUTPUT      0x20
+#define GPIO_INPUT       0x24
+#define GPIO_DIRECTION   0x28
 
+/* -------------------------------------------------------------------------- */
 /* Interrupt controller                                     */
 /* How many MSI's are available depends on HW (Min 2 max 8) */
 /* How many are usable also depends on Host platform        */
@@ -149,3 +156,46 @@
 #define DMA_BASE_ADDRESS_TABLE  (0x2000)
 #define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
 
+/* -------------------------------------------------------------------------- */
+/* CI Interface (only CI-Bridge) */
+
+#define CI_BASE                     (0x400)
+#define CI_CONTROL(i)               (CI_BASE + (i) * 32 + 0x00)
+
+#define CI_DO_ATTRIBUTE_RW(i)       (CI_BASE + (i) * 32 + 0x04)
+#define CI_DO_IO_RW(i)              (CI_BASE + (i) * 32 + 0x08)
+#define CI_READDATA(i)              (CI_BASE + (i) * 32 + 0x0c)
+#define CI_DO_READ_ATTRIBUTES(i)    (CI_BASE + (i) * 32 + 0x10)
+
+#define CI_RESET_CAM                    (0x00000001)
+#define CI_POWER_ON                     (0x00000002)
+#define CI_ENABLE                       (0x00000004)
+#define CI_BLOCKIO_ENABLE               (0x00000008)
+#define CI_BYPASS_DISABLE               (0x00000010)
+#define CI_DISABLE_AUTO_OFF             (0x00000020)
+
+#define CI_CAM_READY                    (0x00010000)
+#define CI_CAM_DETECT                   (0x00020000)
+#define CI_READY                        (0x80000000)
+#define CI_BLOCKIO_ACTIVE               (0x40000000)
+#define CI_BLOCKIO_RCVDATA              (0x20000000)
+#define CI_BLOCKIO_SEND_PENDING         (0x10000000)
+#define CI_BLOCKIO_SEND_COMPLETE        (0x08000000)
+
+#define CI_READ_CMD                     (0x40000000)
+#define CI_WRITE_CMD                    (0x80000000)
+
+#define CI_BLOCKIO_SEND(i)              (CI_BASE + (i) * 32 + 0x14)
+#define CI_BLOCKIO_RECEIVE(i)           (CI_BASE + (i) * 32 + 0x18)
+
+#define CI_BLOCKIO_SEND_COMMAND         (0x80000000)
+#define CI_BLOCKIO_SEND_COMPLETE_ACK    (0x40000000)
+#define CI_BLOCKIO_RCVDATA_ACK          (0x40000000)
+
+#define CI_BUFFER_BASE                  (0x3000)
+#define CI_BUFFER_SIZE                  (0x0800)
+#define CI_BLOCKIO_BUFFER_SIZE          (CI_BUFFER_SIZE/2)
+
+#define CI_BUFFER(i)                    (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE)
+#define CI_BLOCKIO_RECEIVE_BUFFER(i)    (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE)
+#define CI_BLOCKIO_SEND_BUFFER(i)       (CI_BUFFER_BASE + (i) * CI_BUFFER_SIZE + CI_BLOCKIO_BUFFER_SIZE)
diff -Naur linux-3.6.8/drivers/media/dvb/ddbridge/Kconfig linux-3.6.8.patch/drivers/media/dvb/ddbridge/Kconfig
--- linux-3.6.8/drivers/media/dvb/ddbridge/Kconfig	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ddbridge/Kconfig	2012-12-03 08:41:17.000000000 +0100
@@ -1,11 +1,14 @@
 config DVB_DDBRIDGE
 	tristate "Digital Devices bridge support"
 	depends on DVB_CORE && PCI && I2C
+	select DVB_CXD2099
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
 	select DVB_STV6110x if !DVB_FE_CUSTOMISE
 	select DVB_STV090x if !DVB_FE_CUSTOMISE
 	select DVB_DRXK if !DVB_FE_CUSTOMISE
 	select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+	select DVB_STV0367DD if !DVB_FE_CUSTOMISE
+	select DVB_TDA18212DD if !DVB_FE_CUSTOMISE
 	---help---
 	  Support for cards with the Digital Devices PCI express bridge:
 	  - Octopus PCIe Bridge
@@ -14,5 +17,6 @@
 	  - DuoFlex S2 Octopus
 	  - DuoFlex CT Octopus
 	  - cineS2(v6)
+	  - cineCT(v6)
 
 	  Say Y if you own such a card and want to use it.
diff -Naur linux-3.6.8/drivers/media/dvb/frontends/Kconfig linux-3.6.8.patch/drivers/media/dvb/frontends/Kconfig
--- linux-3.6.8/drivers/media/dvb/frontends/Kconfig	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/frontends/Kconfig	2012-12-03 08:53:41.676515316 +0100
@@ -71,6 +71,24 @@
 
 	  Say Y when you want to support this tuner.
 
+config DVB_STV0367DD
+	tristate "STV 0367 (DD)"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  STV 0367 DVB-C/T demodulator (Digital Devices driver).
+
+	  Say Y when you want to support this frontend.
+
+config DVB_TDA18212DD
+	tristate "NXP TDA18212 silicon tuner (DD)"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  NXP TDA18212 silicon tuner (Digital Devices driver).
+
+	  Say Y when you want to support this tuner.
+
 comment "DVB-S (satellite) frontends"
 	depends on DVB_CORE
 
diff -Naur linux-3.6.8/drivers/media/dvb/frontends/Makefile linux-3.6.8.patch/drivers/media/dvb/frontends/Makefile
--- linux-3.6.8/drivers/media/dvb/frontends/Makefile	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/frontends/Makefile	2012-12-03 08:54:42.673022901 +0100
@@ -95,6 +95,8 @@
 obj-$(CONFIG_DVB_CXD2820R) += cxd2820r.o
 obj-$(CONFIG_DVB_DRXK) += drxk.o
 obj-$(CONFIG_DVB_TDA18271C2DD) += tda18271c2dd.o
+obj-$(CONFIG_DVB_STV0367DD) += stv0367dd.o
+obj-$(CONFIG_DVB_TDA18212DD) += tda18212dd.o
 obj-$(CONFIG_DVB_IT913X_FE) += it913x-fe.o
 obj-$(CONFIG_DVB_A8293) += a8293.o
 obj-$(CONFIG_DVB_TDA10071) += tda10071.o
diff -Naur linux-3.6.8/drivers/media/dvb/frontends/stv0367dd.c linux-3.6.8.patch/drivers/media/dvb/frontends/stv0367dd.c
--- linux-3.6.8/drivers/media/dvb/frontends/stv0367dd.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/frontends/stv0367dd.c	2012-12-03 09:05:24.906890534 +0100
@@ -0,0 +1,2269 @@
+/*
+ * stv0367dd: STV0367 DVB-C/T demodulator driver
+ *
+ * Copyright (C) 2011 Digital Devices GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/version.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+#include "stv0367dd.h"
+#include "stv0367dd_regs.h"
+
+enum omode { OM_NONE, OM_DVBT, OM_DVBC, OM_QAM_ITU_C };
+enum {  QAM_MOD_QAM4 = 0,
+	QAM_MOD_QAM16,
+	QAM_MOD_QAM32,
+	QAM_MOD_QAM64,
+	QAM_MOD_QAM128,
+	QAM_MOD_QAM256,
+	QAM_MOD_QAM512,
+	QAM_MOD_QAM1024
+};
+
+enum {QAM_SPECT_NORMAL, QAM_SPECT_INVERTED };
+
+enum {
+	QAM_FEC_A = 1,					/* J83 Annex A */
+	QAM_FEC_B = (1<<1),				/* J83 Annex B */
+	QAM_FEC_C = (1<<2)				/* J83 Annex C */
+};
+
+enum EDemodState { Off, QAMSet, OFDMSet, QAMStarted, OFDMStarted };
+
+struct stv_state {
+#ifdef USE_API3
+	struct dvb_frontend c_frontend;
+	struct dvb_frontend t_frontend;
+#else
+	struct dvb_frontend frontend;
+#endif
+	fe_modulation_t modulation;
+	u32 symbol_rate;
+	u32 bandwidth;
+	struct device *dev;
+
+	struct i2c_adapter *i2c;
+	u8     adr;
+	void  *priv;
+
+	struct mutex mutex;
+	struct mutex ctlock;
+
+	u32 master_clock;
+	u32 adc_clock;
+	u8 ID;
+	u8 I2CRPT;
+	u32 omode;
+	u8  qam_inversion;
+
+	s32 IF;
+
+	s32    m_FECTimeOut;
+	s32    m_DemodTimeOut;
+	s32    m_SignalTimeOut;
+	s32    m_DemodLockTime;
+	s32    m_FFTTimeOut;
+	s32    m_TSTimeOut;
+
+	bool    m_bFirstTimeLock;
+
+	u8    m_Save_QAM_AGC_CTL;
+
+	enum EDemodState demod_state;
+
+	u8    m_OFDM_FFTMode;          // 0 = 2k, 1 = 8k, 2 = 4k
+	u8    m_OFDM_Modulation;   //
+	u8    m_OFDM_FEC;          //
+	u8    m_OFDM_Guard;
+
+	u32   ucblocks;
+};
+
+struct init_table {
+	u16  adr;
+	u8   data;
+};
+
+struct init_table base_init[] = {
+	{ R367_IOCFG0,     0x80 },
+	{ R367_DAC0R,      0x00 },
+	{ R367_IOCFG1,     0x00 },
+	{ R367_DAC1R,      0x00 },
+	{ R367_IOCFG2,     0x00 },
+	{ R367_SDFR,       0x00 },
+	{ R367_AUX_CLK,    0x00 },
+	{ R367_FREESYS1,   0x00 },
+	{ R367_FREESYS2,   0x00 },
+	{ R367_FREESYS3,   0x00 },
+	{ R367_GPIO_CFG,   0x55 },
+	{ R367_GPIO_CMD,   0x01 },
+	{ R367_TSTRES,     0x00 },
+	{ R367_ANACTRL,    0x00 },
+	{ R367_TSTBUS,     0x00 },
+	{ R367_RF_AGC2,    0x20 },
+	{ R367_ANADIGCTRL, 0x0b },
+	{ R367_PLLMDIV,    0x01 },
+	{ R367_PLLNDIV,    0x08 },
+	{ R367_PLLSETUP,   0x18 },
+	{ R367_DUAL_AD12,  0x04 },
+	{ R367_TSTBIST,    0x00 },
+	{ 0x0000,          0x00 }
+};
+
+struct init_table qam_init[] = {
+	{ R367_QAM_CTRL_1,                  0x06 },// Orginal 0x04
+	{ R367_QAM_CTRL_2,                  0x03 },
+	{ R367_QAM_IT_STATUS1,              0x2b },
+	{ R367_QAM_IT_STATUS2,              0x08 },
+	{ R367_QAM_IT_EN1,                  0x00 },
+	{ R367_QAM_IT_EN2,                  0x00 },
+	{ R367_QAM_CTRL_STATUS,             0x04 },
+	{ R367_QAM_TEST_CTL,                0x00 },
+	{ R367_QAM_AGC_CTL,                 0x73 },
+	{ R367_QAM_AGC_IF_CFG,              0x50 },
+	{ R367_QAM_AGC_RF_CFG,              0x02 },// RF Freeze
+	{ R367_QAM_AGC_PWM_CFG,             0x03 },
+	{ R367_QAM_AGC_PWR_REF_L,           0x5a },
+	{ R367_QAM_AGC_PWR_REF_H,           0x00 },
+	{ R367_QAM_AGC_RF_TH_L,             0xff },
+	{ R367_QAM_AGC_RF_TH_H,             0x07 },
+	{ R367_QAM_AGC_IF_LTH_L,            0x00 },
+	{ R367_QAM_AGC_IF_LTH_H,            0x08 },
+	{ R367_QAM_AGC_IF_HTH_L,            0xff },
+	{ R367_QAM_AGC_IF_HTH_H,            0x07 },
+	{ R367_QAM_AGC_PWR_RD_L,            0xa0 },
+	{ R367_QAM_AGC_PWR_RD_M,            0xe9 },
+	{ R367_QAM_AGC_PWR_RD_H,            0x03 },
+	{ R367_QAM_AGC_PWM_IFCMD_L,         0xe4 },
+	{ R367_QAM_AGC_PWM_IFCMD_H,         0x00 },
+	{ R367_QAM_AGC_PWM_RFCMD_L,         0xff },
+	{ R367_QAM_AGC_PWM_RFCMD_H,         0x07 },
+	{ R367_QAM_IQDEM_CFG,               0x01 },
+	{ R367_QAM_MIX_NCO_LL,              0x22 },
+	{ R367_QAM_MIX_NCO_HL,              0x96 },
+	{ R367_QAM_MIX_NCO_HH,              0x55 },
+	{ R367_QAM_SRC_NCO_LL,              0xff },
+	{ R367_QAM_SRC_NCO_LH,              0x0c },
+	{ R367_QAM_SRC_NCO_HL,              0xf5 },
+	{ R367_QAM_SRC_NCO_HH,              0x20 },
+	{ R367_QAM_IQDEM_GAIN_SRC_L,        0x06 },
+	{ R367_QAM_IQDEM_GAIN_SRC_H,        0x01 },
+	{ R367_QAM_IQDEM_DCRM_CFG_LL,       0xfe },
+	{ R367_QAM_IQDEM_DCRM_CFG_LH,       0xff },
+	{ R367_QAM_IQDEM_DCRM_CFG_HL,       0x0f },
+	{ R367_QAM_IQDEM_DCRM_CFG_HH,       0x00 },
+	{ R367_QAM_IQDEM_ADJ_COEFF0,        0x34 },
+	{ R367_QAM_IQDEM_ADJ_COEFF1,        0xae },
+	{ R367_QAM_IQDEM_ADJ_COEFF2,        0x46 },
+	{ R367_QAM_IQDEM_ADJ_COEFF3,        0x77 },
+	{ R367_QAM_IQDEM_ADJ_COEFF4,        0x96 },
+	{ R367_QAM_IQDEM_ADJ_COEFF5,        0x69 },
+	{ R367_QAM_IQDEM_ADJ_COEFF6,        0xc7 },
+	{ R367_QAM_IQDEM_ADJ_COEFF7,        0x01 },
+	{ R367_QAM_IQDEM_ADJ_EN,            0x04 },
+	{ R367_QAM_IQDEM_ADJ_AGC_REF,       0x94 },
+	{ R367_QAM_ALLPASSFILT1,            0xc9 },
+	{ R367_QAM_ALLPASSFILT2,            0x2d },
+	{ R367_QAM_ALLPASSFILT3,            0xa3 },
+	{ R367_QAM_ALLPASSFILT4,            0xfb },
+	{ R367_QAM_ALLPASSFILT5,            0xf6 },
+	{ R367_QAM_ALLPASSFILT6,            0x45 },
+	{ R367_QAM_ALLPASSFILT7,            0x6f },
+	{ R367_QAM_ALLPASSFILT8,            0x7e },
+	{ R367_QAM_ALLPASSFILT9,            0x05 },
+	{ R367_QAM_ALLPASSFILT10,           0x0a },
+	{ R367_QAM_ALLPASSFILT11,           0x51 },
+	{ R367_QAM_TRL_AGC_CFG,             0x20 },
+	{ R367_QAM_TRL_LPF_CFG,             0x28 },
+	{ R367_QAM_TRL_LPF_ACQ_GAIN,        0x44 },
+	{ R367_QAM_TRL_LPF_TRK_GAIN,        0x22 },
+	{ R367_QAM_TRL_LPF_OUT_GAIN,        0x03 },
+	{ R367_QAM_TRL_LOCKDET_LTH,         0x04 },
+	{ R367_QAM_TRL_LOCKDET_HTH,         0x11 },
+	{ R367_QAM_TRL_LOCKDET_TRGVAL,      0x20 },
+	{ R367_QAM_IQ_QAM,			0x01 },
+	{ R367_QAM_FSM_STATE,               0xa0 },
+	{ R367_QAM_FSM_CTL,                 0x08 },
+	{ R367_QAM_FSM_STS,                 0x0c },
+	{ R367_QAM_FSM_SNR0_HTH,            0x00 },
+	{ R367_QAM_FSM_SNR1_HTH,            0x00 },
+	{ R367_QAM_FSM_SNR2_HTH,            0x00 },
+	{ R367_QAM_FSM_SNR0_LTH,            0x00 },
+	{ R367_QAM_FSM_SNR1_LTH,            0x00 },
+	{ R367_QAM_FSM_EQA1_HTH,            0x00 },
+	{ R367_QAM_FSM_TEMPO,               0x32 },
+	{ R367_QAM_FSM_CONFIG,              0x03 },
+	{ R367_QAM_EQU_I_TESTTAP_L,         0x11 },
+	{ R367_QAM_EQU_I_TESTTAP_M,         0x00 },
+	{ R367_QAM_EQU_I_TESTTAP_H,         0x00 },
+	{ R367_QAM_EQU_TESTAP_CFG,          0x00 },
+	{ R367_QAM_EQU_Q_TESTTAP_L,         0xff },
+	{ R367_QAM_EQU_Q_TESTTAP_M,         0x00 },
+	{ R367_QAM_EQU_Q_TESTTAP_H,         0x00 },
+	{ R367_QAM_EQU_TAP_CTRL,            0x00 },
+	{ R367_QAM_EQU_CTR_CRL_CONTROL_L,   0x11 },
+	{ R367_QAM_EQU_CTR_CRL_CONTROL_H,   0x05 },
+	{ R367_QAM_EQU_CTR_HIPOW_L,         0x00 },
+	{ R367_QAM_EQU_CTR_HIPOW_H,         0x00 },
+	{ R367_QAM_EQU_I_EQU_LO,            0xef },
+	{ R367_QAM_EQU_I_EQU_HI,            0x00 },
+	{ R367_QAM_EQU_Q_EQU_LO,            0xee },
+	{ R367_QAM_EQU_Q_EQU_HI,            0x00 },
+	{ R367_QAM_EQU_MAPPER,              0xc5 },
+	{ R367_QAM_EQU_SWEEP_RATE,          0x80 },
+	{ R367_QAM_EQU_SNR_LO,              0x64 },
+	{ R367_QAM_EQU_SNR_HI,              0x03 },
+	{ R367_QAM_EQU_GAMMA_LO,            0x00 },
+	{ R367_QAM_EQU_GAMMA_HI,            0x00 },
+	{ R367_QAM_EQU_ERR_GAIN,            0x36 },
+	{ R367_QAM_EQU_RADIUS,              0xaa },
+	{ R367_QAM_EQU_FFE_MAINTAP,         0x00 },
+	{ R367_QAM_EQU_FFE_LEAKAGE,         0x63 },
+	{ R367_QAM_EQU_FFE_MAINTAP_POS,     0xdf },
+	{ R367_QAM_EQU_GAIN_WIDE,           0x88 },
+	{ R367_QAM_EQU_GAIN_NARROW,         0x41 },
+	{ R367_QAM_EQU_CTR_LPF_GAIN,        0xd1 },
+	{ R367_QAM_EQU_CRL_LPF_GAIN,        0xa7 },
+	{ R367_QAM_EQU_GLOBAL_GAIN,         0x06 },
+	{ R367_QAM_EQU_CRL_LD_SEN,          0x85 },
+	{ R367_QAM_EQU_CRL_LD_VAL,          0xe2 },
+	{ R367_QAM_EQU_CRL_TFR,             0x20 },
+	{ R367_QAM_EQU_CRL_BISTH_LO,        0x00 },
+	{ R367_QAM_EQU_CRL_BISTH_HI,        0x00 },
+	{ R367_QAM_EQU_SWEEP_RANGE_LO,      0x00 },
+	{ R367_QAM_EQU_SWEEP_RANGE_HI,      0x00 },
+	{ R367_QAM_EQU_CRL_LIMITER,         0x40 },
+	{ R367_QAM_EQU_MODULUS_MAP,         0x90 },
+	{ R367_QAM_EQU_PNT_GAIN,            0xa7 },
+	{ R367_QAM_FEC_AC_CTR_0,            0x16 },
+	{ R367_QAM_FEC_AC_CTR_1,            0x0b },
+	{ R367_QAM_FEC_AC_CTR_2,            0x88 },
+	{ R367_QAM_FEC_AC_CTR_3,            0x02 },
+	{ R367_QAM_FEC_STATUS,              0x12 },
+	{ R367_QAM_RS_COUNTER_0,            0x7d },
+	{ R367_QAM_RS_COUNTER_1,            0xd0 },
+	{ R367_QAM_RS_COUNTER_2,            0x19 },
+	{ R367_QAM_RS_COUNTER_3,            0x0b },
+	{ R367_QAM_RS_COUNTER_4,            0xa3 },
+	{ R367_QAM_RS_COUNTER_5,            0x00 },
+	{ R367_QAM_BERT_0,                  0x01 },
+	{ R367_QAM_BERT_1,                  0x25 },
+	{ R367_QAM_BERT_2,                  0x41 },
+	{ R367_QAM_BERT_3,                  0x39 },
+	{ R367_QAM_OUTFORMAT_0,             0xc2 },
+	{ R367_QAM_OUTFORMAT_1,             0x22 },
+	{ R367_QAM_SMOOTHER_2,              0x28 },
+	{ R367_QAM_TSMF_CTRL_0,             0x01 },
+	{ R367_QAM_TSMF_CTRL_1,             0xc6 },
+	{ R367_QAM_TSMF_CTRL_3,             0x43 },
+	{ R367_QAM_TS_ON_ID_0,              0x00 },
+	{ R367_QAM_TS_ON_ID_1,              0x00 },
+	{ R367_QAM_TS_ON_ID_2,              0x00 },
+	{ R367_QAM_TS_ON_ID_3,              0x00 },
+	{ R367_QAM_RE_STATUS_0,             0x00 },
+	{ R367_QAM_RE_STATUS_1,             0x00 },
+	{ R367_QAM_RE_STATUS_2,             0x00 },
+	{ R367_QAM_RE_STATUS_3,             0x00 },
+	{ R367_QAM_TS_STATUS_0,             0x00 },
+	{ R367_QAM_TS_STATUS_1,             0x00 },
+	{ R367_QAM_TS_STATUS_2,             0xa0 },
+	{ R367_QAM_TS_STATUS_3,             0x00 },
+	{ R367_QAM_T_O_ID_0,                0x00 },
+	{ R367_QAM_T_O_ID_1,                0x00 },
+	{ R367_QAM_T_O_ID_2,                0x00 },
+	{ R367_QAM_T_O_ID_3,                0x00 },
+	{ 0x0000, 0x00 } // EOT
+};
+
+struct init_table ofdm_init[] = {
+	//{R367_OFDM_ID                   ,0x60},
+	//{R367_OFDM_I2CRPT 				,0x22},
+	//{R367_OFDM_TOPCTRL				,0x02},
+	//{R367_OFDM_IOCFG0				,0x40},
+	//{R367_OFDM_DAC0R				,0x00},
+	//{R367_OFDM_IOCFG1				,0x00},
+	//{R367_OFDM_DAC1R				,0x00},
+	//{R367_OFDM_IOCFG2				,0x62},
+	//{R367_OFDM_SDFR 				,0x00},
+	//{R367_OFDM_STATUS				,0xf8},
+	//{R367_OFDM_AUX_CLK				,0x0a},
+	//{R367_OFDM_FREESYS1			,0x00},
+	//{R367_OFDM_FREESYS2			,0x00},
+	//{R367_OFDM_FREESYS3			,0x00},
+	//{R367_OFDM_GPIO_CFG			,0x55},
+	//{R367_OFDM_GPIO_CMD			,0x00},
+	{R367_OFDM_AGC2MAX				,0xff},
+	{R367_OFDM_AGC2MIN				,0x00},
+	{R367_OFDM_AGC1MAX				,0xff},
+	{R367_OFDM_AGC1MIN				,0x00},
+	{R367_OFDM_AGCR					,0xbc},
+	{R367_OFDM_AGC2TH				,0x00},
+	//{R367_OFDM_AGC12C				,0x01}, //Note: This defines AGC pins, also needed for QAM
+	{R367_OFDM_AGCCTRL1			,0x85},
+	{R367_OFDM_AGCCTRL2			,0x1f},
+	{R367_OFDM_AGC1VAL1			,0x00},
+	{R367_OFDM_AGC1VAL2			,0x00},
+	{R367_OFDM_AGC2VAL1			,0x6f},
+	{R367_OFDM_AGC2VAL2			,0x05},
+	{R367_OFDM_AGC2PGA				,0x00},
+	{R367_OFDM_OVF_RATE1			,0x00},
+	{R367_OFDM_OVF_RATE2			,0x00},
+	{R367_OFDM_GAIN_SRC1			,0x2b},
+	{R367_OFDM_GAIN_SRC2			,0x04},
+	{R367_OFDM_INC_DEROT1			,0x55},
+	{R367_OFDM_INC_DEROT2			,0x55},
+	{R367_OFDM_PPM_CPAMP_DIR		,0x2c},
+	{R367_OFDM_PPM_CPAMP_INV		,0x00},
+	{R367_OFDM_FREESTFE_1			,0x00},
+	{R367_OFDM_FREESTFE_2			,0x1c},
+	{R367_OFDM_DCOFFSET			,0x00},
+	{R367_OFDM_EN_PROCESS			,0x05},
+	{R367_OFDM_SDI_SMOOTHER		,0x80},
+	{R367_OFDM_FE_LOOP_OPEN		,0x1c},
+	{R367_OFDM_FREQOFF1			,0x00},
+	{R367_OFDM_FREQOFF2			,0x00},
+	{R367_OFDM_FREQOFF3			,0x00},
+	{R367_OFDM_TIMOFF1				,0x00},
+	{R367_OFDM_TIMOFF2				,0x00},
+	{R367_OFDM_EPQ					,0x02},
+	{R367_OFDM_EPQAUTO				,0x01},
+	{R367_OFDM_SYR_UPDATE			,0xf5},
+	{R367_OFDM_CHPFREE						,0x00},
+	{R367_OFDM_PPM_STATE_MAC		      ,0x23},
+	{R367_OFDM_INR_THRESHOLD		      ,0xff},
+	{R367_OFDM_EPQ_TPS_ID_CELL	      ,0xf9},
+	{R367_OFDM_EPQ_CFG				      ,0x00},
+	{R367_OFDM_EPQ_STATUS			      ,0x01},
+	{R367_OFDM_AUTORELOCK			      ,0x81},
+	{R367_OFDM_BER_THR_VMSB		      ,0x00},
+	{R367_OFDM_BER_THR_MSB		      ,0x00},
+	{R367_OFDM_BER_THR_LSB		      ,0x00},
+	{R367_OFDM_CCD					      ,0x83},
+	{R367_OFDM_SPECTR_CFG			      ,0x00},
+	{R367_OFDM_CHC_DUMMY			      ,0x18},
+	{R367_OFDM_INC_CTL				      ,0x88},
+	{R367_OFDM_INCTHRES_COR1		      ,0xb4},
+	{R367_OFDM_INCTHRES_COR2		      ,0x96},
+	{R367_OFDM_INCTHRES_DET1		      ,0x0e},
+	{R367_OFDM_INCTHRES_DET2		      ,0x11},
+	{R367_OFDM_IIR_CELLNB				   ,0x8d},
+	{R367_OFDM_IIRCX_COEFF1_MSB	      ,0x00},
+	{R367_OFDM_IIRCX_COEFF1_LSB	      ,0x00},
+	{R367_OFDM_IIRCX_COEFF2_MSB	      ,0x09},
+	{R367_OFDM_IIRCX_COEFF2_LSB	      ,0x18},
+	{R367_OFDM_IIRCX_COEFF3_MSB	      ,0x14},
+	{R367_OFDM_IIRCX_COEFF3_LSB	      ,0x9c},
+	{R367_OFDM_IIRCX_COEFF4_MSB	      ,0x00},
+	{R367_OFDM_IIRCX_COEFF4_LSB	      ,0x00},
+	{R367_OFDM_IIRCX_COEFF5_MSB	      ,0x36},
+	{R367_OFDM_IIRCX_COEFF5_LSB			,0x42},
+	{R367_OFDM_FEPATH_CFG			      ,0x00},
+	{R367_OFDM_PMC1_FUNC			      ,0x65},
+	{R367_OFDM_PMC1_FOR			      ,0x00},
+	{R367_OFDM_PMC2_FUNC			      ,0x00},
+	{R367_OFDM_STATUS_ERR_DA		      ,0xe0},
+	{R367_OFDM_DIG_AGC_R			      ,0xfe},
+	{R367_OFDM_COMAGC_TARMSB		      ,0x0b},
+	{R367_OFDM_COM_AGC_TAR_ENMODE     ,0x41},
+	{R367_OFDM_COM_AGC_CFG			   ,0x3e},
+	{R367_OFDM_COM_AGC_GAIN1				,0x39},
+	{R367_OFDM_AUT_AGC_TARGETMSB	   ,0x0b},
+	{R367_OFDM_LOCK_DET_MSB			   ,0x01},
+	{R367_OFDM_AGCTAR_LOCK_LSBS		   ,0x40},
+	{R367_OFDM_AUT_GAIN_EN		      ,0xf4},
+	{R367_OFDM_AUT_CFG				      ,0xf0},
+	{R367_OFDM_LOCKN				      ,0x23},
+	{R367_OFDM_INT_X_3				      ,0x00},
+	{R367_OFDM_INT_X_2				      ,0x03},
+	{R367_OFDM_INT_X_1				      ,0x8d},
+	{R367_OFDM_INT_X_0				      ,0xa0},
+	{R367_OFDM_MIN_ERRX_MSB		      ,0x00},
+	{R367_OFDM_COR_CTL				      ,0x00},
+	{R367_OFDM_COR_STAT			      ,0xf6},
+	{R367_OFDM_COR_INTEN			      ,0x00},
+	{R367_OFDM_COR_INTSTAT		      ,0x3f},
+	{R367_OFDM_COR_MODEGUARD		      ,0x03},
+	{R367_OFDM_AGC_CTL				      ,0x08},
+	{R367_OFDM_AGC_MANUAL1		      ,0x00},
+	{R367_OFDM_AGC_MANUAL2		      ,0x00},
+	{R367_OFDM_AGC_TARG			      ,0x16},
+	{R367_OFDM_AGC_GAIN1			      ,0x53},
+	{R367_OFDM_AGC_GAIN2			      ,0x1d},
+	{R367_OFDM_RESERVED_1			      ,0x00},
+	{R367_OFDM_RESERVED_2			      ,0x00},
+	{R367_OFDM_RESERVED_3			      ,0x00},
+	{R367_OFDM_CAS_CTL				      ,0x44},
+	{R367_OFDM_CAS_FREQ			      ,0xb3},
+	{R367_OFDM_CAS_DAGCGAIN		      ,0x12},
+	{R367_OFDM_SYR_CTL				      ,0x04},
+	{R367_OFDM_SYR_STAT			      ,0x10},
+	{R367_OFDM_SYR_NCO1			      ,0x00},
+	{R367_OFDM_SYR_NCO2			      ,0x00},
+	{R367_OFDM_SYR_OFFSET1		      ,0x00},
+	{R367_OFDM_SYR_OFFSET2		      ,0x00},
+	{R367_OFDM_FFT_CTL				      ,0x00},
+	{R367_OFDM_SCR_CTL				      ,0x70},
+	{R367_OFDM_PPM_CTL1			      ,0xf8},
+	{R367_OFDM_TRL_CTL				      ,0xac},
+	{R367_OFDM_TRL_NOMRATE1		      ,0x1e},
+	{R367_OFDM_TRL_NOMRATE2		      ,0x58},
+	{R367_OFDM_TRL_TIME1			      ,0x1d},
+	{R367_OFDM_TRL_TIME2			      ,0xfc},
+	{R367_OFDM_CRL_CTL				      ,0x24},
+	{R367_OFDM_CRL_FREQ1			      ,0xad},
+	{R367_OFDM_CRL_FREQ2			      ,0x9d},
+	{R367_OFDM_CRL_FREQ3			      ,0xff},
+	{R367_OFDM_CHC_CTL		       ,0x01},
+	{R367_OFDM_CHC_SNR				      ,0xf0},
+	{R367_OFDM_BDI_CTL				      ,0x00},
+	{R367_OFDM_DMP_CTL				      ,0x00},
+	{R367_OFDM_TPS_RCVD1			      ,0x30},
+	{R367_OFDM_TPS_RCVD2			      ,0x02},
+	{R367_OFDM_TPS_RCVD3			      ,0x01},
+	{R367_OFDM_TPS_RCVD4			      ,0x00},
+	{R367_OFDM_TPS_ID_CELL1		      ,0x00},
+	{R367_OFDM_TPS_ID_CELL2		      ,0x00},
+	{R367_OFDM_TPS_RCVD5_SET1	      ,0x02},
+	{R367_OFDM_TPS_SET2			      ,0x02},
+	{R367_OFDM_TPS_SET3			      ,0x01},
+	{R367_OFDM_TPS_CTL				      ,0x00},
+	{R367_OFDM_CTL_FFTOSNUM		      ,0x34},
+	{R367_OFDM_TESTSELECT			      ,0x09},
+	{R367_OFDM_MSC_REV 			      ,0x0a},
+	{R367_OFDM_PIR_CTL 			      ,0x00},
+	{R367_OFDM_SNR_CARRIER1 		      ,0xa1},
+	{R367_OFDM_SNR_CARRIER2		      ,0x9a},
+	{R367_OFDM_PPM_CPAMP			      ,0x2c},
+	{R367_OFDM_TSM_AP0				      ,0x00},
+	{R367_OFDM_TSM_AP1				      ,0x00},
+	{R367_OFDM_TSM_AP2 			      ,0x00},
+	{R367_OFDM_TSM_AP3				      ,0x00},
+	{R367_OFDM_TSM_AP4				      ,0x00},
+	{R367_OFDM_TSM_AP5				      ,0x00},
+	{R367_OFDM_TSM_AP6				      ,0x00},
+	{R367_OFDM_TSM_AP7				      ,0x00},
+	//{R367_OFDM_TSTRES				 ,0x00},
+	//{R367_OFDM_ANACTRL				 ,0x0D},/*caution PLL stopped, to be restarted at init!!!*/
+	//{R367_OFDM_TSTBUS				      ,0x00},
+	//{R367_OFDM_TSTRATE				      ,0x00},
+	{R367_OFDM_CONSTMODE			      ,0x01},
+	{R367_OFDM_CONSTCARR1			      ,0x00},
+	{R367_OFDM_CONSTCARR2			      ,0x00},
+	{R367_OFDM_ICONSTEL			      ,0x0a},
+	{R367_OFDM_QCONSTEL			      ,0x15},
+	{R367_OFDM_TSTBISTRES0		      ,0x00},
+	{R367_OFDM_TSTBISTRES1		      ,0x00},
+	{R367_OFDM_TSTBISTRES2		      ,0x28},
+	{R367_OFDM_TSTBISTRES3		      ,0x00},
+	//{R367_OFDM_RF_AGC1				      ,0xff},
+	//{R367_OFDM_RF_AGC2				      ,0x83},
+	//{R367_OFDM_ANADIGCTRL			      ,0x19},
+	//{R367_OFDM_PLLMDIV				      ,0x0c},
+	//{R367_OFDM_PLLNDIV				      ,0x55},
+	//{R367_OFDM_PLLSETUP			      ,0x18},
+	//{R367_OFDM_DUAL_AD12			      ,0x00},
+	//{R367_OFDM_TSTBIST				      ,0x00},
+	//{R367_OFDM_PAD_COMP_CTRL		      ,0x00},
+	//{R367_OFDM_PAD_COMP_WR		      ,0x00},
+	//{R367_OFDM_PAD_COMP_RD		      ,0xe0},
+	{R367_OFDM_SYR_TARGET_FFTADJT_MSB	,0x00},
+	{R367_OFDM_SYR_TARGET_FFTADJT_LSB ,0x00},
+	{R367_OFDM_SYR_TARGET_CHCADJT_MSB ,0x00},
+	{R367_OFDM_SYR_TARGET_CHCADJT_LSB ,0x00},
+	{R367_OFDM_SYR_FLAG			 ,0x00},
+	{R367_OFDM_CRL_TARGET1		 ,0x00},
+	{R367_OFDM_CRL_TARGET2		 ,0x00},
+	{R367_OFDM_CRL_TARGET3		 ,0x00},
+	{R367_OFDM_CRL_TARGET4		 ,0x00},
+	{R367_OFDM_CRL_FLAG			 ,0x00},
+	{R367_OFDM_TRL_TARGET1		 ,0x00},
+	{R367_OFDM_TRL_TARGET2		 ,0x00},
+	{R367_OFDM_TRL_CHC				 ,0x00},
+	{R367_OFDM_CHC_SNR_TARG		 ,0x00},
+	{R367_OFDM_TOP_TRACK			      ,0x00},
+	{R367_OFDM_TRACKER_FREE1		 ,0x00},
+	{R367_OFDM_ERROR_CRL1			 ,0x00},
+	{R367_OFDM_ERROR_CRL2			 ,0x00},
+	{R367_OFDM_ERROR_CRL3			 ,0x00},
+	{R367_OFDM_ERROR_CRL4			 ,0x00},
+	{R367_OFDM_DEC_NCO1			 ,0x2c},
+	{R367_OFDM_DEC_NCO2			 ,0x0f},
+	{R367_OFDM_DEC_NCO3			 ,0x20},
+	{R367_OFDM_SNR					 ,0xf1},
+	{R367_OFDM_SYR_FFTADJ1		      ,0x00},
+	{R367_OFDM_SYR_FFTADJ2		 ,0x00},
+	{R367_OFDM_SYR_CHCADJ1		 ,0x00},
+	{R367_OFDM_SYR_CHCADJ2		 ,0x00},
+	{R367_OFDM_SYR_OFF				 ,0x00},
+	{R367_OFDM_PPM_OFFSET1		      ,0x00},
+	{R367_OFDM_PPM_OFFSET2		 ,0x03},
+	{R367_OFDM_TRACKER_FREE2		 ,0x00},
+	{R367_OFDM_DEBG_LT10			 ,0x00},
+	{R367_OFDM_DEBG_LT11			 ,0x00},
+	{R367_OFDM_DEBG_LT12			      ,0x00},
+	{R367_OFDM_DEBG_LT13			 ,0x00},
+	{R367_OFDM_DEBG_LT14			 ,0x00},
+	{R367_OFDM_DEBG_LT15			 ,0x00},
+	{R367_OFDM_DEBG_LT16			 ,0x00},
+	{R367_OFDM_DEBG_LT17			 ,0x00},
+	{R367_OFDM_DEBG_LT18			 ,0x00},
+	{R367_OFDM_DEBG_LT19			 ,0x00},
+	{R367_OFDM_DEBG_LT1A			 ,0x00},
+	{R367_OFDM_DEBG_LT1B			 ,0x00},
+	{R367_OFDM_DEBG_LT1C 			 ,0x00},
+	{R367_OFDM_DEBG_LT1D 			 ,0x00},
+	{R367_OFDM_DEBG_LT1E			 ,0x00},
+	{R367_OFDM_DEBG_LT1F			 ,0x00},
+	{R367_OFDM_RCCFGH				 ,0x00},
+	{R367_OFDM_RCCFGM						,0x00},
+	{R367_OFDM_RCCFGL						,0x00},
+	{R367_OFDM_RCINSDELH					,0x00},
+	{R367_OFDM_RCINSDELM			 ,0x00},
+	{R367_OFDM_RCINSDELL			 ,0x00},
+	{R367_OFDM_RCSTATUS			 ,0x00},
+	{R367_OFDM_RCSPEED 			 ,0x6f},
+	{R367_OFDM_RCDEBUGM			 ,0xe7},
+	{R367_OFDM_RCDEBUGL			 ,0x9b},
+	{R367_OFDM_RCOBSCFG			 ,0x00},
+	{R367_OFDM_RCOBSM 				 ,0x00},
+	{R367_OFDM_RCOBSL 				 ,0x00},
+	{R367_OFDM_RCFECSPY			 ,0x00},
+	{R367_OFDM_RCFSPYCFG 			 ,0x00},
+	{R367_OFDM_RCFSPYDATA			 ,0x00},
+	{R367_OFDM_RCFSPYOUT 			 ,0x00},
+	{R367_OFDM_RCFSTATUS 			 ,0x00},
+	{R367_OFDM_RCFGOODPACK		 ,0x00},
+	{R367_OFDM_RCFPACKCNT 		 ,0x00},
+	{R367_OFDM_RCFSPYMISC 		 ,0x00},
+	{R367_OFDM_RCFBERCPT4 		 ,0x00},
+	{R367_OFDM_RCFBERCPT3 		 ,0x00},
+	{R367_OFDM_RCFBERCPT2 		 ,0x00},
+	{R367_OFDM_RCFBERCPT1 		 ,0x00},
+	{R367_OFDM_RCFBERCPT0 		 ,0x00},
+	{R367_OFDM_RCFBERERR2 		 ,0x00},
+	{R367_OFDM_RCFBERERR1 		 ,0x00},
+	{R367_OFDM_RCFBERERR0 		 ,0x00},
+	{R367_OFDM_RCFSTATESM 		 ,0x00},
+	{R367_OFDM_RCFSTATESL 		 ,0x00},
+	{R367_OFDM_RCFSPYBER  		 ,0x00},
+	{R367_OFDM_RCFSPYDISTM		 ,0x00},
+	{R367_OFDM_RCFSPYDISTL		 ,0x00},
+	{R367_OFDM_RCFSPYOBS7 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS6 		      ,0x00},
+	{R367_OFDM_RCFSPYOBS5 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS4 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS3 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS2 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS1 		 ,0x00},
+	{R367_OFDM_RCFSPYOBS0			 ,0x00},
+	//{R367_OFDM_TSGENERAL 			 ,0x00},
+	//{R367_OFDM_RC1SPEED  			 ,0x6f},
+	//{R367_OFDM_TSGSTATUS			 ,0x18},
+	{R367_OFDM_FECM					 ,0x01},
+	{R367_OFDM_VTH12				 ,0xff},
+	{R367_OFDM_VTH23				 ,0xa1},
+	{R367_OFDM_VTH34				 ,0x64},
+	{R367_OFDM_VTH56				 ,0x40},
+	{R367_OFDM_VTH67				 ,0x00},
+	{R367_OFDM_VTH78				 ,0x2c},
+	{R367_OFDM_VITCURPUN			 ,0x12},
+	{R367_OFDM_VERROR				 ,0x01},
+	{R367_OFDM_PRVIT				 ,0x3f},
+	{R367_OFDM_VAVSRVIT			 ,0x00},
+	{R367_OFDM_VSTATUSVIT			 ,0xbd},
+	{R367_OFDM_VTHINUSE 			 ,0xa1},
+	{R367_OFDM_KDIV12				 ,0x20},
+	{R367_OFDM_KDIV23				 ,0x40},
+	{R367_OFDM_KDIV34				 ,0x20},
+	{R367_OFDM_KDIV56				 ,0x30},
+	{R367_OFDM_KDIV67				 ,0x00},
+	{R367_OFDM_KDIV78				 ,0x30},
+	{R367_OFDM_SIGPOWER 			 ,0x54},
+	{R367_OFDM_DEMAPVIT 			 ,0x40},
+	{R367_OFDM_VITSCALE 			 ,0x00},
+	{R367_OFDM_FFEC1PRG 			 ,0x00},
+	{R367_OFDM_FVITCURPUN 		 ,0x12},
+	{R367_OFDM_FVERROR 			 ,0x01},
+	{R367_OFDM_FVSTATUSVIT		 ,0xbd},
+	{R367_OFDM_DEBUG_LT1			 ,0x00},
+	{R367_OFDM_DEBUG_LT2			 ,0x00},
+	{R367_OFDM_DEBUG_LT3			 ,0x00},
+	{R367_OFDM_TSTSFMET  			 ,0x00},
+	{R367_OFDM_SELOUT				 ,0x00},
+	{R367_OFDM_TSYNC				 ,0x00},
+	{R367_OFDM_TSTERR				 ,0x00},
+	{R367_OFDM_TSFSYNC   			 ,0x00},
+	{R367_OFDM_TSTSFERR  			 ,0x00},
+	{R367_OFDM_TSTTSSF1  			 ,0x01},
+	{R367_OFDM_TSTTSSF2  			 ,0x1f},
+	{R367_OFDM_TSTTSSF3  			 ,0x00},
+	{R367_OFDM_TSTTS1   			 ,0x00},
+	{R367_OFDM_TSTTS2   			      ,0x1f},
+	{R367_OFDM_TSTTS3   			 ,0x01},
+	{R367_OFDM_TSTTS4   			 ,0x00},
+	{R367_OFDM_TSTTSRC  			 ,0x00},
+	{R367_OFDM_TSTTSRS  			 ,0x00},
+	{R367_OFDM_TSSTATEM			 ,0xb0},
+	{R367_OFDM_TSSTATEL			 ,0x40},
+	{R367_OFDM_TSCFGH  			 ,0x80},
+	{R367_OFDM_TSCFGM  			 ,0x00},
+	{R367_OFDM_TSCFGL  			 ,0x20},
+	{R367_OFDM_TSSYNC  			 ,0x00},
+	{R367_OFDM_TSINSDELH			 ,0x00},
+	{R367_OFDM_TSINSDELM 			 ,0x00},
+	{R367_OFDM_TSINSDELL			 ,0x00},
+	{R367_OFDM_TSDIVN				 ,0x03},
+	{R367_OFDM_TSDIVPM				 ,0x00},
+	{R367_OFDM_TSDIVPL				 ,0x00},
+	{R367_OFDM_TSDIVQM 			 ,0x00},
+	{R367_OFDM_TSDIVQL				 ,0x00},
+	{R367_OFDM_TSDILSTKM			 ,0x00},
+	{R367_OFDM_TSDILSTKL			 ,0x00},
+	{R367_OFDM_TSSPEED				 ,0x6f},
+	{R367_OFDM_TSSTATUS			 ,0x81},
+	{R367_OFDM_TSSTATUS2			 ,0x6a},
+	{R367_OFDM_TSBITRATEM			 ,0x0f},
+	{R367_OFDM_TSBITRATEL			 ,0xc6},
+	{R367_OFDM_TSPACKLENM			 ,0x00},
+	{R367_OFDM_TSPACKLENL			 ,0xfc},
+	{R367_OFDM_TSBLOCLENM			 ,0x0a},
+	{R367_OFDM_TSBLOCLENL			 ,0x80},
+	{R367_OFDM_TSDLYH 				 ,0x90},
+	{R367_OFDM_TSDLYM				 ,0x68},
+	{R367_OFDM_TSDLYL				 ,0x01},
+	{R367_OFDM_TSNPDAV				 ,0x00},
+	{R367_OFDM_TSBUFSTATH 		 ,0x00},
+	{R367_OFDM_TSBUFSTATM 		 ,0x00},
+	{R367_OFDM_TSBUFSTATL			 ,0x00},
+	{R367_OFDM_TSDEBUGM			 ,0xcf},
+	{R367_OFDM_TSDEBUGL			 ,0x1e},
+	{R367_OFDM_TSDLYSETH 			 ,0x00},
+	{R367_OFDM_TSDLYSETM			 ,0x68},
+	{R367_OFDM_TSDLYSETL			 ,0x00},
+	{R367_OFDM_TSOBSCFG			 ,0x00},
+	{R367_OFDM_TSOBSM 				 ,0x47},
+	{R367_OFDM_TSOBSL				 ,0x1f},
+	{R367_OFDM_ERRCTRL1			 ,0x95},
+	{R367_OFDM_ERRCNT1H 			 ,0x80},
+	{R367_OFDM_ERRCNT1M 			 ,0x00},
+	{R367_OFDM_ERRCNT1L 			 ,0x00},
+	{R367_OFDM_ERRCTRL2			 ,0x95},
+	{R367_OFDM_ERRCNT2H			 ,0x00},
+	{R367_OFDM_ERRCNT2M			 ,0x00},
+	{R367_OFDM_ERRCNT2L			 ,0x00},
+	{R367_OFDM_FECSPY 				 ,0x88},
+	{R367_OFDM_FSPYCFG				 ,0x2c},
+	{R367_OFDM_FSPYDATA			 ,0x3a},
+	{R367_OFDM_FSPYOUT				 ,0x06},
+	{R367_OFDM_FSTATUS				 ,0x61},
+	{R367_OFDM_FGOODPACK			 ,0xff},
+	{R367_OFDM_FPACKCNT			 ,0xff},
+	{R367_OFDM_FSPYMISC 			 ,0x66},
+	{R367_OFDM_FBERCPT4 			 ,0x00},
+	{R367_OFDM_FBERCPT3			 ,0x00},
+	{R367_OFDM_FBERCPT2			 ,0x36},
+	{R367_OFDM_FBERCPT1			 ,0x36},
+	{R367_OFDM_FBERCPT0 			 ,0x14},
+	{R367_OFDM_FBERERR2			 ,0x00},
+	{R367_OFDM_FBERERR1			 ,0x03},
+	{R367_OFDM_FBERERR0			 ,0x28},
+	{R367_OFDM_FSTATESM			 ,0x00},
+	{R367_OFDM_FSTATESL			 ,0x02},
+	{R367_OFDM_FSPYBER 			 ,0x00},
+	{R367_OFDM_FSPYDISTM			 ,0x01},
+	{R367_OFDM_FSPYDISTL			 ,0x9f},
+	{R367_OFDM_FSPYOBS7 			 ,0xc9},
+	{R367_OFDM_FSPYOBS6 			 ,0x99},
+	{R367_OFDM_FSPYOBS5			 ,0x08},
+	{R367_OFDM_FSPYOBS4			 ,0xec},
+	{R367_OFDM_FSPYOBS3			 ,0x01},
+	{R367_OFDM_FSPYOBS2			 ,0x0f},
+	{R367_OFDM_FSPYOBS1			 ,0xf5},
+	{R367_OFDM_FSPYOBS0			 ,0x08},
+	{R367_OFDM_SFDEMAP 			 ,0x40},
+	{R367_OFDM_SFERROR 			 ,0x00},
+	{R367_OFDM_SFAVSR  			 ,0x30},
+	{R367_OFDM_SFECSTATUS			 ,0xcc},
+	{R367_OFDM_SFKDIV12			 ,0x20},
+	{R367_OFDM_SFKDIV23			 ,0x40},
+	{R367_OFDM_SFKDIV34			 ,0x20},
+	{R367_OFDM_SFKDIV56			 ,0x20},
+	{R367_OFDM_SFKDIV67			 ,0x00},
+	{R367_OFDM_SFKDIV78			 ,0x20},
+	{R367_OFDM_SFDILSTKM			 ,0x00},
+	{R367_OFDM_SFDILSTKL 			 ,0x00},
+	{R367_OFDM_SFSTATUS			 ,0xb5},
+	{R367_OFDM_SFDLYH				 ,0x90},
+	{R367_OFDM_SFDLYM				 ,0x60},
+	{R367_OFDM_SFDLYL				 ,0x01},
+	{R367_OFDM_SFDLYSETH			 ,0xc0},
+	{R367_OFDM_SFDLYSETM			 ,0x60},
+	{R367_OFDM_SFDLYSETL			 ,0x00},
+	{R367_OFDM_SFOBSCFG 			 ,0x00},
+	{R367_OFDM_SFOBSM 				 ,0x47},
+	{R367_OFDM_SFOBSL				 ,0x05},
+	{R367_OFDM_SFECINFO 			 ,0x40},
+	{R367_OFDM_SFERRCTRL 			 ,0x74},
+	{R367_OFDM_SFERRCNTH			 ,0x80},
+	{R367_OFDM_SFERRCNTM 			 ,0x00},
+	{R367_OFDM_SFERRCNTL			 ,0x00},
+	{R367_OFDM_SYMBRATEM			 ,0x2f},
+	{R367_OFDM_SYMBRATEL			      ,0x50},
+	{R367_OFDM_SYMBSTATUS			 ,0x7f},
+	{R367_OFDM_SYMBCFG 			 ,0x00},
+	{R367_OFDM_SYMBFIFOM 			 ,0xf4},
+	{R367_OFDM_SYMBFIFOL 			 ,0x0d},
+	{R367_OFDM_SYMBOFFSM 			 ,0xf0},
+	{R367_OFDM_SYMBOFFSL 			 ,0x2d},
+	//{R367_OFDM_DEBUG_LT4			 ,0x00},
+	//{R367_OFDM_DEBUG_LT5			 ,0x00},
+	//{R367_OFDM_DEBUG_LT6			 ,0x00},
+	//{R367_OFDM_DEBUG_LT7			 ,0x00},
+	//{R367_OFDM_DEBUG_LT8			 ,0x00},
+	//{R367_OFDM_DEBUG_LT9			 ,0x00},
+	{ 0x0000, 0x00 } // EOT
+};
+
+inline u32 MulDiv32(u32 a, u32 b, u32 c)
+{
+	u64 tmp64;
+
+	tmp64 = (u64)a * (u64)b;
+	do_div(tmp64, c);
+
+	return (u32) tmp64;
+}
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msg =
+		{.addr = adr, .flags = 0, .buf = data, .len = len};
+
+	if (i2c_transfer(adap, &msg, 1) != 1) {
+		printk("stv0367: i2c_write error\n");
+		return -1;
+	}
+	return 0;
+}
+
+#if 0
+static int i2c_read(struct i2c_adapter *adap,
+		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
+{
+	struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0,
+				     .buf = msg, .len = len},
+				   { .addr = adr, .flags = I2C_M_RD,
+				     .buf = answ, .len = alen } };
+	if (i2c_transfer(adap, msgs, 2) != 2) {
+		printk("stv0367: i2c_read error\n");
+		return -1;
+	}
+	return 0;
+}
+#endif
+
+static int writereg(struct stv_state *state, u16 reg, u8 dat)
+{
+	u8 mm[3] = { (reg >> 8), reg & 0xff, dat };
+
+	return i2c_write(state->i2c, state->adr, mm, 3);
+}
+
+static int readreg(struct stv_state *state, u16 reg, u8 *val)
+{
+	u8 msg[2] = {reg >> 8, reg & 0xff};
+	struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0,
+				   .buf  = msg, .len   = 2},
+				  {.addr = state->adr, .flags = I2C_M_RD,
+				   .buf  = val, .len   = 1}};
+	return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int readregs(struct stv_state *state, u16 reg, u8 *val, int count)
+{
+	u8 msg[2] = {reg >> 8, reg & 0xff};
+	struct i2c_msg msgs[2] = {{.addr = state->adr, .flags = 0,
+				   .buf  = msg, .len   = 2},
+				  {.addr = state->adr, .flags = I2C_M_RD,
+				   .buf  = val, .len   = count}};
+	return (i2c_transfer(state->i2c, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int write_init_table(struct stv_state *state, struct init_table *tab)
+{
+	while (1) {
+		if (!tab->adr)
+			break;
+		if (writereg(state, tab->adr, tab->data) < 0)
+			return -1;
+		tab++;
+	}
+	return 0;
+}
+
+static int qam_set_modulation(struct stv_state *state)
+{
+	int stat = 0;
+
+	switch(state->modulation) {
+	case QAM_16:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM16 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x64);       /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);   /* Set digital AGC reference */
+		writereg(state, R367_QAM_FSM_STATE,0x90);
+		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0x8a);
+		break;
+	case QAM_32:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM32 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x6e);       /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);   /* Set digital AGC reference */
+		writereg(state, R367_QAM_FSM_STATE,0xb0);
+		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xb7);
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x9d);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
+		break;
+	case QAM_64:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM64 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a);       /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x82);   /* Set digital AGC reference */
+		if(state->symbol_rate>4500000)
+		{
+			writereg(state, R367_QAM_FSM_STATE,0xb0);
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa5);
+		}
+		else if(state->symbol_rate>2500000) // 25000000
+		{
+			writereg(state, R367_QAM_FSM_STATE,0xa0);
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6);
+		}
+		else
+		{
+			writereg(state, R367_QAM_FSM_STATE,0xa0);
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1);
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
+		}
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x95);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0x99);
+		break;
+	case QAM_128:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM128 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x76);       /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x00);	/* Set digital AGC reference */
+		writereg(state, R367_QAM_FSM_STATE,0x90);
+		writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xb1);
+		if(state->symbol_rate>4500000) // 45000000
+		{
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
+		}
+		else if(state->symbol_rate>2500000) // 25000000
+		{
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa6);
+		}
+		else
+		{
+			writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0x97);
+		}
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x8e);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x7f);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
+		break;
+	case QAM_256:
+		writereg(state, R367_QAM_EQU_MAPPER,state->qam_inversion | QAM_MOD_QAM256 );
+		writereg(state, R367_QAM_AGC_PWR_REF_L,0x5a);     /* Set analog AGC reference */
+		writereg(state, R367_QAM_IQDEM_ADJ_AGC_REF,0x94); /* Set digital AGC reference */
+		writereg(state, R367_QAM_FSM_STATE,0xa0);
+		if(state->symbol_rate>4500000) // 45000000
+		{
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+		}
+		else if(state->symbol_rate>2500000) // 25000000
+		{
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xc1);
+		}
+		else
+		{
+			writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,0xd1);
+		}
+		writereg(state, R367_QAM_EQU_CRL_LPF_GAIN,0xa7);
+		writereg(state, R367_QAM_EQU_CRL_LD_SEN,0x85);
+		writereg(state, R367_QAM_EQU_CRL_LIMITER,0x40);
+		writereg(state, R367_QAM_EQU_PNT_GAIN,0xa7);
+		break;
+	default:
+		stat = -EINVAL;
+		break;
+	}
+	return stat;
+}
+
+
+static int QAM_SetSymbolRate(struct stv_state *state)
+{
+	int status = 0;
+	u32 sr = state->symbol_rate;
+	u32 Corr = 0;
+	u32 Temp, Temp1, AdpClk;
+
+	switch(state->modulation) {
+	default:
+	case QAM_16:   Corr = 1032; break;
+	case QAM_32:   Corr =  954; break;
+	case QAM_64:   Corr =  983; break;
+	case QAM_128:  Corr =  957; break;
+	case QAM_256:  Corr =  948; break;
+	}
+
+	// Transfer ration
+	Temp = (256*sr) / state->adc_clock;
+	writereg(state, R367_QAM_EQU_CRL_TFR,(Temp));
+
+	/* Symbol rate and SRC gain calculation */
+	AdpClk = (state->master_clock)/2000; /* TRL works at half the system clock */
+
+	Temp = state->symbol_rate;
+	Temp1 = sr;
+
+	if(sr < 2097152)				/* 2097152 = 2^21 */
+	{
+		Temp  = ((((sr * 2048) / AdpClk) * 16384 ) / 125 ) * 8;
+		Temp1 = (((((sr * 2048) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 10000000;
+	}
+	else if(sr < 4194304)			/* 4194304 = 2**22 */
+	{
+		Temp  = ((((sr * 1024) / AdpClk) * 16384 ) / 125 ) * 16;
+		Temp1 = (((((sr * 1024) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 5000000;
+	}
+	else if(sr < 8388608)			/* 8388608 = 2**23 */
+	{
+		Temp  = ((((sr * 512) / AdpClk) * 16384 ) / 125 ) * 32;
+		Temp1 = (((((sr * 512) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 2500000;
+	}
+	else
+	{
+		Temp  = ((((sr * 256) / AdpClk) * 16384 ) / 125 ) * 64;
+		Temp1 = (((((sr * 256) / 439 ) * 256 ) / AdpClk ) * Corr * 9 ) / 1250000;
+	}
+
+	///* Filters' coefficients are calculated and written into registers only if the filters are enabled */
+	//if (ChipGetField(hChip,F367qam_ADJ_EN)) // Is disabled from init!
+	//{
+	//    FE_367qam_SetIirAdjacentcoefficient(hChip, MasterClk_Hz, SymbolRate);
+	//}
+	///* AllPass filter is never used on this IC */
+	//ChipSetField(hChip,F367qam_ALLPASSFILT_EN,0); // should be disabled from init!
+
+	writereg(state, R367_QAM_SRC_NCO_LL,(Temp));
+	writereg(state, R367_QAM_SRC_NCO_LH,(Temp>>8));
+	writereg(state, R367_QAM_SRC_NCO_HL,(Temp>>16));
+	writereg(state, R367_QAM_SRC_NCO_HH,(Temp>>24));
+
+	writereg(state, R367_QAM_IQDEM_GAIN_SRC_L,(Temp1));
+	writereg(state, R367_QAM_IQDEM_GAIN_SRC_H,(Temp1>>8));
+	return status;
+}
+
+
+static int QAM_SetDerotFrequency(struct stv_state *state, u32 DerotFrequency)
+{
+	int status = 0;
+	u32 Sampled_IF;
+
+	do {
+		//if (DerotFrequency < 1000000)
+		//    DerotFrequency = state->adc_clock/4; /* ZIF operation */
+		if (DerotFrequency > state->adc_clock)
+			DerotFrequency = DerotFrequency - state->adc_clock;	// User Alias
+
+		Sampled_IF = ((32768 * (DerotFrequency/1000)) / (state->adc_clock/1000)) * 256;
+		if(Sampled_IF > 8388607)
+			Sampled_IF = 8388607;
+
+		writereg(state, R367_QAM_MIX_NCO_LL, (Sampled_IF));
+		writereg(state, R367_QAM_MIX_NCO_HL, (Sampled_IF>>8));
+		writereg(state, R367_QAM_MIX_NCO_HH, (Sampled_IF>>16));
+	} while(0);
+
+	return status;
+}
+
+
+
+static int QAM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency)
+{
+	int status = 0;
+	u32 AGCTimeOut = 25;
+	u32 TRLTimeOut = 100000000 / state->symbol_rate;
+	u32 CRLSymbols = 0;
+	u32 EQLTimeOut = 100;
+	u32 SearchRange = state->symbol_rate / 25;
+	u32 CRLTimeOut;
+	u8 Temp;
+
+	if( state->demod_state != QAMSet ) {
+		writereg(state, R367_DEBUG_LT4,0x00);
+		writereg(state, R367_DEBUG_LT5,0x01);
+		writereg(state, R367_DEBUG_LT6,0x06);// R367_QAM_CTRL_1
+		writereg(state, R367_DEBUG_LT7,0x03);// R367_QAM_CTRL_2
+		writereg(state, R367_DEBUG_LT8,0x00);
+		writereg(state, R367_DEBUG_LT9,0x00);
+
+		// Tuner Setup
+		writereg(state, R367_ANADIGCTRL,0x8B); /* Buffer Q disabled, I Enabled, signed ADC */
+		writereg(state, R367_DUAL_AD12,0x04); /* ADCQ disabled */
+
+		// Clock setup
+		writereg(state, R367_ANACTRL,0x0D); /* PLL bypassed and disabled */
+		writereg(state, R367_TOPCTRL,0x10); // Set QAM
+
+		writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */
+		writereg(state, R367_PLLNDIV,232);
+		writereg(state, R367_PLLSETUP,0x18);  /* ADC clock is equal to system clock */
+
+		msleep(50);
+		writereg(state, R367_ANACTRL,0x00); /* PLL enabled and used */
+
+		state->master_clock = 58000000;
+		state->adc_clock = 58000000;
+
+		state->demod_state = QAMSet;
+	}
+
+	state->m_bFirstTimeLock = true;
+	state->m_DemodLockTime  = -1;
+
+	qam_set_modulation(state);
+	QAM_SetSymbolRate(state);
+
+	// Will make problems on low symbol rates ( < 2500000 )
+
+	switch(state->modulation) {
+	default:
+	case QAM_16:   CRLSymbols = 150000; break;
+	case QAM_32:   CRLSymbols = 250000; break;
+	case QAM_64:   CRLSymbols = 200000; break;
+	case QAM_128:  CRLSymbols = 250000; break;
+	case QAM_256:  CRLSymbols = 250000; break;
+	}
+
+	CRLTimeOut = (25 * CRLSymbols * (SearchRange/1000)) / (state->symbol_rate/1000);
+	CRLTimeOut = (1000 * CRLTimeOut) / state->symbol_rate;
+	if( CRLTimeOut < 50 ) CRLTimeOut = 50;
+
+	state->m_FECTimeOut = 20;
+	state->m_DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut;
+	state->m_SignalTimeOut = AGCTimeOut + TRLTimeOut;
+
+	// QAM_AGC_ACCUMRSTSEL = 0;
+	readreg(state, R367_QAM_AGC_CTL,&state->m_Save_QAM_AGC_CTL);
+	writereg(state, R367_QAM_AGC_CTL,state->m_Save_QAM_AGC_CTL & ~0x0F);
+
+	// QAM_MODULUSMAP_EN = 0
+	readreg(state, R367_QAM_EQU_PNT_GAIN,&Temp);
+	writereg(state, R367_QAM_EQU_PNT_GAIN,Temp & ~0x40);
+
+	// QAM_SWEEP_EN = 0
+	readreg(state, R367_QAM_EQU_CTR_LPF_GAIN,&Temp);
+	writereg(state, R367_QAM_EQU_CTR_LPF_GAIN,Temp & ~0x08);
+
+	QAM_SetDerotFrequency(state, IntermediateFrequency);
+
+	// Release TRL
+	writereg(state, R367_QAM_CTRL_1,0x00);
+
+	state->IF = IntermediateFrequency;
+	state->demod_state = QAMStarted;
+
+	return status;
+}
+
+static int OFDM_Start(struct stv_state *state, s32 offsetFreq,s32 IntermediateFrequency)
+{
+	int status = 0;
+	u8 GAIN_SRC1;
+	u32 Derot;
+	u8 SYR_CTL;
+	u8 tmp1;
+	u8 tmp2;
+
+	if ( state->demod_state != OFDMSet ) {
+		// QAM Disable
+		writereg(state, R367_DEBUG_LT4, 0x00);
+		writereg(state, R367_DEBUG_LT5, 0x00);
+		writereg(state, R367_DEBUG_LT6, 0x00);// R367_QAM_CTRL_1
+		writereg(state, R367_DEBUG_LT7, 0x00);// R367_QAM_CTRL_2
+		writereg(state, R367_DEBUG_LT8, 0x00);
+		writereg(state, R367_DEBUG_LT9, 0x00);
+
+		// Tuner Setup
+		writereg(state, R367_ANADIGCTRL, 0x89); /* Buffer Q disabled, I Enabled, unsigned ADC */
+		writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */
+
+		// Clock setup
+		writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */
+		writereg(state, R367_TOPCTRL, 0x00); // Set OFDM
+
+		writereg(state, R367_PLLMDIV, 1); /* IC runs at 54 MHz with a 27 MHz crystal */
+		writereg(state, R367_PLLNDIV, 8);
+		writereg(state, R367_PLLSETUP, 0x18);  /* ADC clock is equal to system clock */
+
+		msleep(50);
+		writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */
+
+		state->master_clock = 54000000;
+		state->adc_clock    = 54000000;
+
+		state->demod_state = OFDMSet;
+	}
+
+	state->m_bFirstTimeLock = true;
+	state->m_DemodLockTime  = -1;
+
+	// Set inversion in GAIN_SRC1 (fixed from init)
+	//  is in GAIN_SRC1, see below
+
+	GAIN_SRC1 = 0xA0;
+	// Bandwidth
+
+	// Fixed values for 54 MHz
+	switch(state->bandwidth) {
+	case 0:
+	case 8000000:
+		// Normrate = 44384;
+		writereg(state, R367_OFDM_TRL_CTL,0x14);
+		writereg(state, R367_OFDM_TRL_NOMRATE1,0xB0);
+		writereg(state, R367_OFDM_TRL_NOMRATE2,0x56);
+		// Gain SRC = 2774
+		writereg(state, R367_OFDM_GAIN_SRC1,0x0A | GAIN_SRC1);
+		writereg(state, R367_OFDM_GAIN_SRC2,0xD6);
+		break;
+	case 7000000:
+		// Normrate = 38836;
+		writereg(state, R367_OFDM_TRL_CTL,0x14);
+		writereg(state, R367_OFDM_TRL_NOMRATE1,0xDA);
+		writereg(state, R367_OFDM_TRL_NOMRATE2,0x4B);
+		// Gain SRC = 2427
+		writereg(state, R367_OFDM_GAIN_SRC1,0x09 | GAIN_SRC1);
+		writereg(state, R367_OFDM_GAIN_SRC2,0x7B);
+		break;
+	case 6000000:
+		// Normrate = 33288;
+		writereg(state, R367_OFDM_TRL_CTL,0x14);
+		writereg(state, R367_OFDM_TRL_NOMRATE1,0x04);
+		writereg(state, R367_OFDM_TRL_NOMRATE2,0x41);
+		// Gain SRC = 2080
+		writereg(state, R367_OFDM_GAIN_SRC1,0x08 | GAIN_SRC1);
+		writereg(state, R367_OFDM_GAIN_SRC2,0x20);
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	Derot = ((IntermediateFrequency/1000) * 65536) / (state->master_clock / 1000);
+
+	writereg(state, R367_OFDM_INC_DEROT1,(Derot>>8));
+	writereg(state, R367_OFDM_INC_DEROT2,(Derot));
+
+	readreg(state, R367_OFDM_SYR_CTL,&SYR_CTL);
+	SYR_CTL  &= ~0x78;
+	writereg(state, R367_OFDM_SYR_CTL,SYR_CTL);    // EchoPos = 0
+
+
+	writereg(state, R367_OFDM_COR_MODEGUARD,0x03); // Force = 0, Mode = 0, Guard = 3
+	SYR_CTL &= 0x01;
+	writereg(state, R367_OFDM_SYR_CTL,SYR_CTL);    // SYR_TR_DIS = 0
+
+	msleep(5);
+
+	writereg(state, R367_OFDM_COR_CTL,0x20);    // Start core
+
+	// -- Begin M.V.
+	// Reset FEC and Read Solomon
+	readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
+	readreg(state, R367_TSGENERAL,&tmp2);
+	writereg(state, R367_OFDM_SFDLYSETH,tmp1 | 0x08);
+	writereg(state, R367_TSGENERAL,tmp2 | 0x01);
+	// -- End M.V.
+
+	state->m_SignalTimeOut = 200;
+	state->IF = IntermediateFrequency;
+	state->demod_state = OFDMStarted;
+	state->m_DemodTimeOut = 0;
+	state->m_FECTimeOut = 0;
+	state->m_TSTimeOut = 0;
+
+	return status;
+}
+
+#if 0
+static int Stop(struct stv_state *state)
+{
+	int status = 0;
+
+	switch(state->demod_state)
+	{
+	case QAMStarted:
+		status = writereg(state, R367_QAM_CTRL_1,0x06);
+		state->demod_state = QAMSet;
+		break;
+	case OFDMStarted:
+		status = writereg(state, R367_OFDM_COR_CTL,0x00);
+		state->demod_state = OFDMSet;
+		break;
+	default:
+		break;
+	}
+	return status;
+}
+#endif
+
+static s32 Log10x100(u32 x)
+{
+	static u32 LookupTable[100] = {
+		101157945, 103514217, 105925373, 108392691, 110917482,
+		113501082, 116144861, 118850223, 121618600, 124451461, // 800.5 - 809.5
+		127350308, 130316678, 133352143, 136458314, 139636836,
+		142889396, 146217717, 149623566, 153108746, 156675107, // 810.5 - 819.5
+		160324539, 164058977, 167880402, 171790839, 175792361,
+		179887092, 184077200, 188364909, 192752491, 197242274, // 820.5 - 829.5
+		201836636, 206538016, 211348904, 216271852, 221309471,
+		226464431, 231739465, 237137371, 242661010, 248313311, // 830.5 - 839.5
+		254097271, 260015956, 266072506, 272270131, 278612117,
+		285101827, 291742701, 298538262, 305492111, 312607937, // 840.5 - 849.5
+		319889511, 327340695, 334965439, 342767787, 350751874,
+		358921935, 367282300, 375837404, 384591782, 393550075, // 850.5 - 859.5
+		402717034, 412097519, 421696503, 431519077, 441570447,
+		451855944, 462381021, 473151259, 484172368, 495450191, // 860.5 - 869.5
+		506990708, 518800039, 530884444, 543250331, 555904257,
+		568852931, 582103218, 595662144, 609536897, 623734835, // 870.5 - 879.5
+		638263486, 653130553, 668343918, 683911647, 699841996,
+		716143410, 732824533, 749894209, 767361489, 785235635, // 880.5 - 889.5
+		803526122, 822242650, 841395142, 860993752, 881048873,
+		901571138, 922571427, 944060876, 966050879, 988553095, // 890.5 - 899.5
+	};
+	s32 y;
+	int i;
+
+	if (x == 0)
+		return 0;
+	y = 800;
+	if (x >= 1000000000) {
+		x /= 10;
+		y += 100;
+	}
+
+	while (x < 100000000) {
+		x *= 10;
+		y -= 100;
+	}
+	i = 0;
+	while (i < 100 && x > LookupTable[i])
+		i += 1;
+	y += i;
+	return y;
+}
+
+static int QAM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise)
+{
+	u32 RegValAvg = 0;
+	u8 RegVal[2];
+	int status = 0, i;
+
+	*pSignalToNoise = 0;
+	for (i = 0; i < 10; i += 1 ) {
+		readregs(state, R367_QAM_EQU_SNR_LO, RegVal, 2);
+		RegValAvg += RegVal[0] + 256 * RegVal[1];
+	}
+	if (RegValAvg != 0) {
+		s32 Power = 1;
+		switch(state->modulation) {
+		case QAM_16:
+			Power = 20480;
+			break;
+		case QAM_32:
+			Power = 23040;
+			break;
+		case QAM_64:
+			Power = 21504;
+			break;
+		case QAM_128:
+			Power = 23616; break;
+		case QAM_256:
+			Power = 21760; break;
+		default:
+			break;
+		}
+		*pSignalToNoise = Log10x100((Power * 320) / RegValAvg);
+	} else {
+		*pSignalToNoise = 380;
+	}
+	return status;
+}
+
+static int OFDM_GetSignalToNoise(struct stv_state *state, s32 *pSignalToNoise)
+{
+	u8 CHC_SNR = 0;
+
+	int status = readreg(state, R367_OFDM_CHC_SNR, &CHC_SNR);
+	if (status >= 0) {
+		// Note: very unclear documentation on this.
+		//   Datasheet states snr = CHC_SNR/4 dB  -> way to high values!
+		//   Software  snr = ( 1000 * CHC_SNR ) / 8 / 32 / 10; -> to low values
+		//   Comment in SW states this should be ( 1000 * CHC_SNR ) / 4 / 32 / 10; for the 367
+		//   361/362 Datasheet: snr = CHC_SNR/8 dB -> this looks best
+		*pSignalToNoise = ( (s32)CHC_SNR * 10) / 8;
+	}
+	//printk("SNR %d\n", *pSignalToNoise);
+	return status;
+}
+
+#if 0
+static int DVBC_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
+{
+	*pQuality = 100;
+	return 0;
+};
+
+static int DVBT_GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
+{
+	static s32 QE_SN[] = {
+		51, // QPSK 1/2
+		69, // QPSK 2/3
+		79, // QPSK 3/4
+		89, // QPSK 5/6
+		97, // QPSK 7/8
+		108, // 16-QAM 1/2
+		131, // 16-QAM 2/3
+		146, // 16-QAM 3/4
+		156, // 16-QAM 5/6
+		160, // 16-QAM 7/8
+		165, // 64-QAM 1/2
+		187, // 64-QAM 2/3
+		202, // 64-QAM 3/4
+		216, // 64-QAM 5/6
+		225, // 64-QAM 7/8
+	};
+	u8 TPS_Received[2];
+	int Constellation;
+	int CodeRate;
+	s32 SignalToNoiseRel, BERQuality;
+
+	*pQuality = 0;
+	readregs(state, R367_OFDM_TPS_RCVD2, TPS_Received, sizeof(TPS_Received));
+	Constellation = TPS_Received[0] & 0x03;
+	CodeRate = TPS_Received[1] & 0x07;
+
+	if( Constellation > 2 || CodeRate > 5 )
+		return -1;
+	SignalToNoiseRel = SignalToNoise - QE_SN[Constellation * 5 + CodeRate];
+	BERQuality = 100;
+
+	if( SignalToNoiseRel < -70 )
+		*pQuality = 0;
+	else if( SignalToNoiseRel < 30 ) {
+		*pQuality = ((SignalToNoiseRel + 70) * BERQuality)/100;
+	} else
+		*pQuality = BERQuality;
+	return 0;
+};
+
+static s32 DVBCQuality(struct stv_state *state, s32 SignalToNoise)
+{
+	s32 SignalToNoiseRel = 0;
+	s32 Quality = 0;
+	s32 BERQuality = 100;
+
+	switch(state->modulation) {
+	case QAM_16:  SignalToNoiseRel = SignalToNoise - 200 ; break;
+	case QAM_32:  SignalToNoiseRel = SignalToNoise - 230 ; break; // Not in NorDig
+	case QAM_64:  SignalToNoiseRel = SignalToNoise - 260 ; break;
+	case QAM_128: SignalToNoiseRel = SignalToNoise - 290 ; break;
+	case QAM_256: SignalToNoiseRel = SignalToNoise - 320 ; break;
+	}
+
+	if( SignalToNoiseRel < -70 ) Quality = 0;
+	else if( SignalToNoiseRel < 30 )
+	{
+		Quality = ((SignalToNoiseRel + 70) * BERQuality)/100;
+	}
+	else
+	Quality = BERQuality;
+
+	return Quality;
+}
+
+static int GetQuality(struct stv_state *state, s32 SignalToNoise, s32 *pQuality)
+{
+	*pQuality = 0;
+	switch(state->demod_state)
+	{
+	case QAMStarted:
+		*pQuality = DVBCQuality(state, SignalToNoise);
+		break;
+	case OFDMStarted:
+		return DVBT_GetQuality(state, SignalToNoise, pQuality);
+	}
+	return 0;
+};
+#endif
+
+static int attach_init(struct stv_state *state)
+{
+	int stat = 0;
+
+	stat = readreg(state, R367_ID, &state->ID);
+	if ( stat < 0 || state->ID != 0x60 )
+		return -ENODEV;
+	printk("stv0367 found\n");
+
+	writereg(state, R367_TOPCTRL, 0x10);
+	write_init_table(state, base_init);
+	write_init_table(state, qam_init);
+
+	writereg(state, R367_TOPCTRL, 0x00);
+	write_init_table(state, ofdm_init);
+
+	writereg(state, R367_OFDM_GAIN_SRC1, 0x2A);
+	writereg(state, R367_OFDM_GAIN_SRC2, 0xD6);
+	writereg(state, R367_OFDM_INC_DEROT1, 0x55);
+	writereg(state, R367_OFDM_INC_DEROT2, 0x55);
+	writereg(state, R367_OFDM_TRL_CTL, 0x14);
+	writereg(state, R367_OFDM_TRL_NOMRATE1, 0xAE);
+	writereg(state, R367_OFDM_TRL_NOMRATE2, 0x56);
+	writereg(state, R367_OFDM_FEPATH_CFG, 0x0);
+
+	// OFDM TS Setup
+
+	writereg(state, R367_OFDM_TSCFGH, 0x70);
+	writereg(state, R367_OFDM_TSCFGM, 0xC0);
+	writereg(state, R367_OFDM_TSCFGL, 0x20);
+	writereg(state, R367_OFDM_TSSPEED, 0x40);        // Fixed at 54 MHz
+	//writereg(state, R367_TSTBUS, 0x80);      // Invert CLK
+
+	writereg(state, R367_OFDM_TSCFGH, 0x71);
+	writereg(state, R367_OFDM_TSCFGH, 0x70);
+
+	writereg(state, R367_TOPCTRL, 0x10);
+
+	// Also needed for QAM
+	writereg(state, R367_OFDM_AGC12C, 0x01); // AGC Pin setup
+
+	writereg(state, R367_OFDM_AGCCTRL1, 0x8A); //
+
+	// QAM TS setup, note exact format also depends on descrambler settings
+	writereg(state, R367_QAM_OUTFORMAT_0, 0x85); // Inverted Clock, Swap, serial
+	// writereg(state, R367_QAM_OUTFORMAT_1, 0x00); //
+
+	// Clock setup
+	writereg(state, R367_ANACTRL, 0x0D); /* PLL bypassed and disabled */
+
+	if( state->master_clock == 58000000 ) {
+		writereg(state, R367_PLLMDIV,27); /* IC runs at 58 MHz with a 27 MHz crystal */
+		writereg(state, R367_PLLNDIV,232);
+	} else {
+		writereg(state, R367_PLLMDIV,1); /* IC runs at 54 MHz with a 27 MHz crystal */
+		writereg(state, R367_PLLNDIV,8);
+	}
+	writereg(state, R367_PLLSETUP, 0x18);  /* ADC clock is equal to system clock */
+
+	// Tuner setup
+	writereg(state, R367_ANADIGCTRL, 0x8b); /* Buffer Q disabled, I Enabled, signed ADC */
+	writereg(state, R367_DUAL_AD12, 0x04); /* ADCQ disabled */
+
+	writereg(state, R367_QAM_FSM_SNR2_HTH, 0x23); /* Improves the C/N lock limit */
+	writereg(state, R367_QAM_IQ_QAM, 0x01); /* ZIF/IF Automatic mode */
+	writereg(state, R367_QAM_EQU_FFE_LEAKAGE, 0x83); /* Improving burst noise performances */
+	writereg(state, R367_QAM_IQDEM_ADJ_EN, 0x05); /* Improving ACI performances */
+
+	writereg(state, R367_ANACTRL, 0x00); /* PLL enabled and used */
+
+	writereg(state, R367_I2CRPT, state->I2CRPT);
+	state->demod_state    = QAMSet;
+	return stat;
+}
+
+#ifdef USE_API3
+static void c_release(struct dvb_frontend* fe)
+#else
+static void release(struct dvb_frontend* fe)
+#endif
+{
+	struct stv_state *state=fe->demodulator_priv;
+	printk("%s\n", __FUNCTION__);
+	kfree(state);
+}
+
+#ifdef USE_API3
+static int c_init (struct dvb_frontend *fe)
+{
+	struct stv_state *state=fe->demodulator_priv;
+
+	if (mutex_trylock(&state->ctlock)==0)
+		return -EBUSY;
+	state->omode = OM_DVBC;
+	return 0;
+}
+
+static int c_sleep(struct dvb_frontend* fe)
+{
+	struct stv_state *state=fe->demodulator_priv;
+
+	mutex_unlock(&state->ctlock);
+	return 0;
+}
+#endif
+
+static int gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	u8 i2crpt = state->I2CRPT & ~0x80;
+
+	if (enable)
+		i2crpt |= 0x80;
+	if (writereg(state, R367_I2CRPT, i2crpt) < 0)
+		return -1;
+	state->I2CRPT = i2crpt;
+	return 0;
+}
+
+#if 0
+static int c_track(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	return DVBFE_ALGO_SEARCH_AGAIN;
+}
+#endif
+
+#if 0
+int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+#endif
+
+static int ofdm_lock(struct stv_state *state)
+{
+	int status = 0;
+	u8 OFDM_Status;
+	s32 DemodTimeOut = 10;
+	s32 FECTimeOut = 0;
+	s32 TSTimeOut = 0;
+	u8 CPAMPMin = 255;
+	u8 CPAMPValue;
+	u8 SYR_STAT;
+	u8 FFTMode;
+	u8 TSStatus;
+
+	msleep(state->m_SignalTimeOut);
+	readreg(state, R367_OFDM_STATUS,&OFDM_Status);
+
+	if (!(OFDM_Status & 0x40))
+		return -1;
+	//printk("lock 1\n");
+
+	readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT);
+	FFTMode = (SYR_STAT & 0x0C) >> 2;
+
+	switch(FFTMode)
+	{
+	    case 0: // 2K
+		DemodTimeOut = 10;
+		FECTimeOut = 150;
+		TSTimeOut = 125;
+		CPAMPMin = 20;
+		break;
+	    case 1: // 8K
+		DemodTimeOut = 55;
+		FECTimeOut = 600;
+		TSTimeOut = 500;
+		CPAMPMin = 80;
+		break;
+	    case 2: // 4K
+		DemodTimeOut = 40;
+		FECTimeOut = 300;
+		TSTimeOut = 250;
+		CPAMPMin = 30;
+		break;
+	}
+	state->m_OFDM_FFTMode = FFTMode;
+	readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue);
+	msleep(DemodTimeOut);
+	{
+	    // Release FEC and Read Solomon Reset
+	    u8 tmp1;
+	    u8 tmp2;
+	    readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
+	    readreg(state, R367_TSGENERAL,&tmp2);
+	    writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08);
+	    writereg(state, R367_TSGENERAL,tmp2 & ~0x01);
+	}
+	msleep(FECTimeOut);
+	if( (OFDM_Status & 0x98) != 0x98 )
+		;//return -1;
+	//printk("lock 2\n");
+
+	{
+	    u8 Guard = (SYR_STAT & 0x03);
+	    if(Guard < 2)
+	    {
+		u8 tmp;
+		readreg(state, R367_OFDM_SYR_CTL,&tmp);
+		writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN
+		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
+		writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER
+	    } else {
+		u8 tmp;
+		readreg(state, R367_OFDM_SYR_CTL,&tmp);
+		writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN
+		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
+		writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER
+	    }
+
+	    // apply Sfec workaround if 8K 64QAM CR!=1/2
+	    if( FFTMode == 1)
+	    {
+		u8 tmp[2];
+		readregs(state, R367_OFDM_TPS_RCVD2, tmp, 2);
+		if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) )
+		{
+		    writereg(state, R367_OFDM_SFDLYSETH,0xc0);
+		    writereg(state, R367_OFDM_SFDLYSETM,0x60);
+		    writereg(state, R367_OFDM_SFDLYSETL,0x00);
+		}
+		else
+		{
+		    writereg(state, R367_OFDM_SFDLYSETH,0x00);
+		}
+	    }
+	}
+	msleep(TSTimeOut);
+	readreg(state, R367_OFDM_TSSTATUS,&TSStatus);
+	if( (TSStatus & 0x80) != 0x80 )
+		return -1;
+	//printk("lock 3\n");
+	return status;
+}
+
+
+
+#ifdef USE_API3
+static int set_parameters(struct dvb_frontend *fe,
+			  struct dvb_frontend_parameters *p)
+{
+	int stat;
+	struct stv_state *state = fe->demodulator_priv;
+	u32 OF = 0;
+	u32 IF;
+
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe, p);
+
+	switch (state->omode) {
+	case OM_DVBC:
+	case OM_QAM_ITU_C:
+		state->modulation = p->u.qam.modulation;
+		state->symbol_rate = p->u.qam.symbol_rate;
+		break;
+	case OM_DVBT:
+		switch (p->u.ofdm.bandwidth) {
+		case BANDWIDTH_AUTO:
+		case BANDWIDTH_8_MHZ:
+			state->bandwidth = 8000000;
+			break;
+		case BANDWIDTH_7_MHZ:
+			state->bandwidth = 7000000;
+			break;
+		case BANDWIDTH_6_MHZ:
+			state->bandwidth = 6000000;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+#else
+static int set_parameters(struct dvb_frontend *fe)
+{
+	int stat;
+	struct stv_state *state = fe->demodulator_priv;
+	u32 OF = 0;
+	u32 IF;
+
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBC_ANNEX_A:
+		state->omode = OM_DVBC;
+		/* symbol rate 0 might cause an oops */
+		if (fe->dtv_property_cache.symbol_rate == 0) {
+			printk(KERN_ERR "stv0367dd: Invalid symbol rate\n");
+			return -EINVAL;
+		}
+		break;
+	case SYS_DVBT:
+		state->omode = OM_DVBT;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (fe->ops.tuner_ops.set_params)
+		fe->ops.tuner_ops.set_params(fe);
+	state->modulation = fe->dtv_property_cache.modulation;
+	state->symbol_rate = fe->dtv_property_cache.symbol_rate;
+	state->bandwidth = fe->dtv_property_cache.bandwidth_hz;
+#endif
+	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+	//fe->ops.tuner_ops.get_frequency(fe, &IF);
+
+	switch(state->omode) {
+	case OM_DVBT:
+		stat = OFDM_Start(state, OF, IF);
+		ofdm_lock(state);
+		break;
+	case OM_DVBC:
+	case OM_QAM_ITU_C:
+		stat = QAM_Start(state, OF, IF);
+		break;
+	default:
+		stat = -EINVAL;
+	}
+	//printk("%s IF=%d OF=%d done\n", __FUNCTION__, IF, OF);
+	return stat;
+}
+
+#if 0
+static int c_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	//struct stv_state *state = fe->demodulator_priv;
+	//printk("%s\n", __FUNCTION__);
+	return 0;
+}
+
+static int OFDM_GetLockStatus(struct stv_state *state, LOCK_STATUS* pLockStatus, s32 Time)
+{
+	int status = STATUS_SUCCESS;
+	u8 OFDM_Status;
+	s32 DemodTimeOut = 0;
+	s32 FECTimeOut = 0;
+	s32 TSTimeOut = 0;
+	u8 CPAMPMin = 255;
+	u8 CPAMPValue;
+	bool SYRLock;
+	u8 SYR_STAT;
+	u8 FFTMode;
+	u8 TSStatus;
+
+	readreg(state, R367_OFDM_STATUS,&OFDM_Status);
+
+	SYRLock = (OFDM_Status & 0x40) != 0;
+
+	if( Time > m_SignalTimeOut && !SYRLock )
+	{
+	    *pLockStatus = NEVER_LOCK;
+	    break;
+	}
+
+	if( !SYRLock ) break;
+
+	*pLockStatus = SIGNAL_PRESENT;
+
+	// Check Mode
+
+	readreg(state, R367_OFDM_SYR_STAT,&SYR_STAT);
+	FFTMode = (SYR_STAT & 0x0C) >> 2;
+
+	switch(FFTMode)
+	{
+	    case 0: // 2K
+		DemodTimeOut = 10;
+		FECTimeOut = 150;
+		TSTimeOut = 125;
+		CPAMPMin = 20;
+		break;
+	    case 1: // 8K
+		DemodTimeOut = 55;
+		FECTimeOut = 600;
+		TSTimeOut = 500;
+		CPAMPMin = 80;
+		break;
+	    case 2: // 4K
+		DemodTimeOut = 40;
+		FECTimeOut = 300;
+		TSTimeOut = 250;
+		CPAMPMin = 30;
+		break;
+	}
+
+	m_OFDM_FFTMode = FFTMode;
+
+	if( m_DemodTimeOut == 0 && m_bFirstTimeLock )
+	{
+	    m_DemodTimeOut = Time + DemodTimeOut;
+	    //break;
+	}
+
+	readreg(state, R367_OFDM_PPM_CPAMP_DIR,&CPAMPValue);
+
+	if( Time <= m_DemodTimeOut && CPAMPValue < CPAMPMin )
+	{
+	    break;
+	}
+
+	if( CPAMPValue < CPAMPMin && m_bFirstTimeLock )
+	{
+	    // initiate retry
+	    *pLockStatus = NEVER_LOCK;
+	    break;
+	}
+
+	if( CPAMPValue < CPAMPMin ) break;
+
+	*pLockStatus = DEMOD_LOCK;
+
+	if( m_FECTimeOut == 0 && m_bFirstTimeLock )
+	{
+	    // Release FEC and Read Solomon Reset
+	    u8 tmp1;
+	    u8 tmp2;
+	    readreg(state, R367_OFDM_SFDLYSETH,&tmp1);
+	    readreg(state, R367_TSGENERAL,&tmp2);
+	    writereg(state, R367_OFDM_SFDLYSETH,tmp1 & ~0x08);
+	    writereg(state, R367_TSGENERAL,tmp2 & ~0x01);
+
+	    m_FECTimeOut = Time + FECTimeOut;
+	}
+
+	// Wait for TSP_LOCK, LK, PRF
+	if( (OFDM_Status & 0x98) != 0x98 )
+	{
+	    if( Time > m_FECTimeOut ) *pLockStatus = NEVER_LOCK;
+	    break;
+	}
+
+	if( m_bFirstTimeLock && m_TSTimeOut == 0)
+	{
+	    u8 Guard = (SYR_STAT & 0x03);
+	    if(Guard < 2)
+	    {
+		u8 tmp;
+		readreg(state, R367_OFDM_SYR_CTL,&tmp);
+		writereg(state, R367_OFDM_SYR_CTL,tmp & ~0x04); // Clear AUTO_LE_EN
+		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
+		writereg(state, R367_OFDM_SYR_UPDATE,tmp & ~0x10); // Clear SYR_FILTER
+	    } else {
+		u8 tmp;
+		readreg(state, R367_OFDM_SYR_CTL,&tmp);
+		writereg(state, R367_OFDM_SYR_CTL,tmp | 0x04); // Set AUTO_LE_EN
+		readreg(state, R367_OFDM_SYR_UPDATE,&tmp);
+		writereg(state, R367_OFDM_SYR_UPDATE,tmp | 0x10); // Set SYR_FILTER
+	    }
+
+	    // apply Sfec workaround if 8K 64QAM CR!=1/2
+	    if( FFTMode == 1)
+	    {
+		u8 tmp[2];
+		readreg(state, R367_OFDM_TPS_RCVD2,tmp,2);
+		if( ((tmp[0] & 0x03) == 0x02) && (( tmp[1] & 0x07 ) != 0) )
+		{
+		    writereg(state, R367_OFDM_SFDLYSETH,0xc0);
+		    writereg(state, R367_OFDM_SFDLYSETM,0x60);
+		    writereg(state, R367_OFDM_SFDLYSETL,0x00);
+		}
+		else
+		{
+		    writereg(state, R367_OFDM_SFDLYSETH,0x00);
+		}
+	    }
+
+	    m_TSTimeOut = Time + TSTimeOut;
+	}
+	readreg(state, R367_OFDM_TSSTATUS,&TSStatus);
+	if( (TSStatus & 0x80) != 0x80 )
+	{
+		if( Time > m_TSTimeOut ) *pLockStatus = NEVER_LOCK;
+	    break;
+	}
+	*pLockStatus = MPEG_LOCK;
+	m_bFirstTimeLock = false;
+	return status;
+}
+
+#endif
+
+static int read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	*status=0;
+
+	switch(state->demod_state) {
+	case QAMStarted:
+	{
+		u8 FEC_Lock;
+		u8 QAM_Lock;
+
+		readreg(state, R367_QAM_FSM_STS, &QAM_Lock);
+		QAM_Lock &= 0x0F;
+		if (QAM_Lock >10)
+			*status|=0x07;
+		readreg(state, R367_QAM_FEC_STATUS,&FEC_Lock);
+		if (FEC_Lock&2)
+			*status|=0x1f;
+		if (state->m_bFirstTimeLock) {
+			state->m_bFirstTimeLock = false;
+			// QAM_AGC_ACCUMRSTSEL to Tracking;
+			writereg(state, R367_QAM_AGC_CTL, state->m_Save_QAM_AGC_CTL);
+		}
+		break;
+	}
+	case OFDMStarted:
+	{
+		u8 OFDM_Status;
+		u8 TSStatus;
+
+		readreg(state, R367_OFDM_TSSTATUS, &TSStatus);
+
+		readreg(state, R367_OFDM_STATUS, &OFDM_Status);
+		if (OFDM_Status & 0x40)
+			*status |= FE_HAS_SIGNAL;
+
+		if ((OFDM_Status & 0x98) == 0x98)
+			*status|=0x0f;
+
+		if (TSStatus & 0x80)
+			*status |= 0x1f;
+		break;
+	}
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	//struct stv_state *state = fe->demodulator_priv;
+	*ber=0;
+	return 0;
+}
+
+static int read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	if (fe->ops.tuner_ops.get_rf_strength)
+		fe->ops.tuner_ops.get_rf_strength(fe, strength);
+	else
+		*strength = 0;
+	return 0;
+}
+
+static int read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	s32 snr2 = 0;
+
+	switch(state->demod_state) {
+	case QAMStarted:
+		QAM_GetSignalToNoise(state, &snr2);
+		break;
+	case OFDMStarted:
+		OFDM_GetSignalToNoise(state, &snr2);
+		break;
+	default:
+		break;
+	}
+	*snr = snr2&0xffff;
+	return 0;
+}
+
+static int read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct stv_state *state = fe->demodulator_priv;
+	u8 errl, errm, errh;
+	u8 val;
+
+	switch(state->demod_state) {
+	case QAMStarted:
+		readreg(state, R367_QAM_RS_COUNTER_4, &errl);
+		readreg(state, R367_QAM_RS_COUNTER_5, &errm);
+		*ucblocks = (errm << 8) | errl;
+		break;
+	case OFDMStarted:
+		readreg(state, R367_OFDM_SFERRCNTH, &val);
+		if ((val & 0x80) == 0) {
+			readreg(state, R367_OFDM_ERRCNT1H, &errh);
+			readreg(state, R367_OFDM_ERRCNT1M, &errl);
+			readreg(state, R367_OFDM_ERRCNT1L, &errm);
+			state->ucblocks = (errh <<16) | (errm << 8) | errl;
+		}
+		*ucblocks = state->ucblocks;
+		break;
+	default:
+		*ucblocks = 0;
+		break;
+	}
+	return 0;
+}
+
+static int c_get_tune_settings(struct dvb_frontend *fe,
+				    struct dvb_frontend_tune_settings *sets)
+{
+	sets->min_delay_ms=3000;
+	sets->max_drift=0;
+	sets->step_size=0;
+	return 0;
+}
+
+#ifndef USE_API3
+static int get_tune_settings(struct dvb_frontend *fe,
+			     struct dvb_frontend_tune_settings *sets)
+{
+	switch (fe->dtv_property_cache.delivery_system) {
+	case SYS_DVBC_ANNEX_A:
+	case SYS_DVBC_ANNEX_C:
+		return c_get_tune_settings(fe, sets);
+	default:
+		/* DVB-T: Use info.frequency_stepsize. */
+		return -EINVAL;
+	}
+}
+#endif
+
+#ifdef USE_API3
+static void t_release(struct dvb_frontend* fe)
+{
+	//struct stv_state *state=fe->demodulator_priv;
+	//printk("%s\n", __FUNCTION__);
+	//kfree(state);
+}
+
+static int t_init (struct dvb_frontend *fe)
+{
+	struct stv_state *state=fe->demodulator_priv;
+	if (mutex_trylock(&state->ctlock)==0)
+		return -EBUSY;
+	state->omode = OM_DVBT;
+	return 0;
+}
+
+static int t_sleep(struct dvb_frontend* fe)
+{
+	struct stv_state *state=fe->demodulator_priv;
+	mutex_unlock(&state->ctlock);
+	return 0;
+}
+#endif
+
+#if 0
+static int t_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	//struct stv_state *state = fe->demodulator_priv;
+	//printk("%s\n", __FUNCTION__);
+	return 0;
+}
+
+static enum dvbfe_algo algo(struct dvb_frontend *fe)
+{
+	return DVBFE_ALGO_CUSTOM;
+}
+#endif
+
+#ifdef USE_API3
+static struct dvb_frontend_ops c_ops = {
+	.info = {
+		.name = "STV0367 DVB-C",
+		.type = FE_QAM,
+		.frequency_stepsize = 62500,
+		.frequency_min = 47000000,
+		.frequency_max = 862000000,
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO
+	},
+	.release = c_release,
+	.init = c_init,
+	.sleep = c_sleep,
+	.i2c_gate_ctrl = gate_ctrl,
+
+	.get_tune_settings = c_get_tune_settings,
+
+	.read_status = read_status,
+	.read_ber = read_ber,
+	.read_signal_strength = read_signal_strength,
+	.read_snr = read_snr,
+	.read_ucblocks = read_ucblocks,
+
+#if 1
+	.set_frontend = set_parameters,
+#else
+	.get_frontend_algo = algo,
+	.search = search,
+#endif
+};
+
+static struct dvb_frontend_ops t_ops = {
+	.info = {
+		.name			= "STV0367 DVB-T",
+		.type			= FE_OFDM,
+		.frequency_min		= 47125000,
+		.frequency_max		= 865000000,
+		.frequency_stepsize	= 166667,
+		.frequency_tolerance	= 0,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+		FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+		FE_CAN_FEC_AUTO |
+		FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+		FE_CAN_QAM_AUTO |
+		FE_CAN_TRANSMISSION_MODE_AUTO |
+		FE_CAN_GUARD_INTERVAL_AUTO |
+		FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
+		FE_CAN_MUTE_TS
+	},
+	.release = t_release,
+	.init = t_init,
+	.sleep = t_sleep,
+	.i2c_gate_ctrl = gate_ctrl,
+
+	.set_frontend = set_parameters,
+
+	.read_status = read_status,
+	.read_ber = read_ber,
+	.read_signal_strength = read_signal_strength,
+	.read_snr = read_snr,
+	.read_ucblocks = read_ucblocks,
+};
+
+#else
+
+static struct dvb_frontend_ops common_ops = {
+	.delsys = { SYS_DVBC_ANNEX_A, SYS_DVBT },
+	.info = {
+		.name = "STV0367 DVB-C DVB-T",
+		.frequency_stepsize = 166667,	/* DVB-T only */
+		.frequency_min = 47000000,	/* DVB-T: 47125000 */
+		.frequency_max = 865000000,	/* DVB-C: 862000000 */
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		.caps = /* DVB-C */
+			FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 |
+			FE_CAN_FEC_AUTO |
+			/* DVB-T */
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO |
+			FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
+			FE_CAN_RECOVER | FE_CAN_MUTE_TS
+	},
+	.release = release,
+	.i2c_gate_ctrl = gate_ctrl,
+
+	.get_tune_settings = get_tune_settings,
+
+	.set_frontend = set_parameters,
+
+	.read_status = read_status,
+	.read_ber = read_ber,
+	.read_signal_strength = read_signal_strength,
+	.read_snr = read_snr,
+	.read_ucblocks = read_ucblocks,
+};
+#endif
+
+
+static void init_state(struct stv_state *state, struct stv0367_cfg *cfg)
+{
+	u32 ulENARPTLEVEL = 5;
+	u32 ulQAMInversion = 2;
+	state->omode = OM_NONE;
+	state->adr = cfg->adr;
+
+	mutex_init(&state->mutex);
+	mutex_init(&state->ctlock);
+
+#ifdef USE_API3
+	memcpy(&state->c_frontend.ops, &c_ops, sizeof(struct dvb_frontend_ops));
+	memcpy(&state->t_frontend.ops, &t_ops, sizeof(struct dvb_frontend_ops));
+	state->c_frontend.demodulator_priv = state;
+	state->t_frontend.demodulator_priv = state;
+#else
+	memcpy(&state->frontend.ops, &common_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+#endif
+
+	state->master_clock = 58000000;
+	state->adc_clock = 58000000;
+	state->I2CRPT = 0x08 | ((ulENARPTLEVEL & 0x07) << 4);
+	state->qam_inversion = ((ulQAMInversion & 3) << 6 );
+	state->demod_state   = Off;
+}
+
+
+struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c, struct stv0367_cfg *cfg,
+				    struct dvb_frontend **fe_t)
+{
+	struct stv_state *state = NULL;
+
+	state = kzalloc(sizeof(struct stv_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+
+	state->i2c = i2c;
+	init_state(state, cfg);
+
+	if (attach_init(state)<0)
+		goto error;
+#ifdef USE_API3
+	*fe_t = &state->t_frontend;
+	return &state->c_frontend;
+#else
+	return &state->frontend;
+#endif
+
+error:
+	printk("stv0367: not found\n");
+	kfree(state);
+	return NULL;
+}
+
+
+MODULE_DESCRIPTION("STV0367DD driver");
+MODULE_AUTHOR("Ralph Metzler, Manfred Voelkel");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(stv0367_attach);
+
+
+
diff -Naur linux-3.6.8/drivers/media/dvb/frontends/stv0367dd.h linux-3.6.8.patch/drivers/media/dvb/frontends/stv0367dd.h
--- linux-3.6.8/drivers/media/dvb/frontends/stv0367dd.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/frontends/stv0367dd.h	2012-12-03 08:41:17.000000000 +0100
@@ -0,0 +1,17 @@
+#ifndef _STV0367DD_H_
+#define _STV0367DD_H_
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+struct stv0367_cfg {
+	u8  adr;
+	u32 xtal;
+	u32 ts_mode;
+};
+
+
+extern struct dvb_frontend *stv0367_attach(struct i2c_adapter *i2c,
+					   struct stv0367_cfg *cfg,
+					   struct dvb_frontend **fe_t);
+#endif
diff -Naur linux-3.6.8/drivers/media/dvb/frontends/stv0367dd_regs.h linux-3.6.8.patch/drivers/media/dvb/frontends/stv0367dd_regs.h
--- linux-3.6.8/drivers/media/dvb/frontends/stv0367dd_regs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/frontends/stv0367dd_regs.h	2012-12-03 08:41:17.000000000 +0100
@@ -0,0 +1,3431 @@
+// @DVB-C/DVB-T STMicroelectronics STV0367 register defintions
+// Author Manfred Völkel, Februar 2011
+// (c) 2010 DigitalDevices GmbH Germany.  All rights reserved
+
+// $Id: DD_STV0367Register.h 357 2011-04-27 02:39:13Z manfred $
+
+/*	=======================================================================
+    -- Registers Declaration
+    -- -------------------------
+    -- Each register (R367_XXXXX) is defined by its address (2 bytes).
+    --
+    -- Each field (F367_XXXXX)is defined as follow:
+    -- [register address -- 2bytes][field sign -- 1byte][field mask -- 1byte]
+	    =======================================================================  */
+
+/* ID */
+#define	R367_ID		0xF000
+#define	F367_IDENTIFICATIONREG		0xF00000FF
+
+/* I2CRPT */
+#define	R367_I2CRPT		0xF001
+#define	F367_I2CT_ON		0xF0010080
+#define	F367_ENARPT_LEVEL		0xF0010070
+#define	F367_SCLT_DELAY		0xF0010008
+#define	F367_SCLT_NOD		0xF0010004
+#define	F367_STOP_ENABLE		0xF0010002
+#define	F367_SDAT_NOD		0xF0010001
+
+/* TOPCTRL */
+#define	R367_TOPCTRL		0xF002
+#define	F367_STDBY		0xF0020080
+#define	F367_STDBY_FEC		0xF0020040
+#define	F367_STDBY_CORE		0xF0020020
+#define	F367_QAM_COFDM		0xF0020010
+#define	F367_TS_DIS		0xF0020008
+#define	F367_DIR_CLK_216		0xF0020004
+#define	F367_TUNER_BB		0xF0020002
+#define	F367_DVBT_H		0xF0020001
+
+/* IOCFG0 */
+#define	R367_IOCFG0		0xF003
+#define	F367_OP0_SD		0xF0030080
+#define	F367_OP0_VAL		0xF0030040
+#define	F367_OP0_OD		0xF0030020
+#define	F367_OP0_INV		0xF0030010
+#define	F367_OP0_DACVALUE_HI		0xF003000F
+
+/* DAC0R */
+#define	R367_DAC0R		0xF004
+#define	F367_OP0_DACVALUE_LO		0xF00400FF
+
+/* IOCFG1 */
+#define	R367_IOCFG1		0xF005
+#define	F367_IP0		0xF0050040
+#define	F367_OP1_OD		0xF0050020
+#define	F367_OP1_INV		0xF0050010
+#define	F367_OP1_DACVALUE_HI		0xF005000F
+
+/* DAC1R */
+#define	R367_DAC1R		0xF006
+#define	F367_OP1_DACVALUE_LO		0xF00600FF
+
+/* IOCFG2 */
+#define	R367_IOCFG2		0xF007
+#define	F367_OP2_LOCK_CONF		0xF00700E0
+#define	F367_OP2_OD		0xF0070010
+#define	F367_OP2_VAL		0xF0070008
+#define	F367_OP1_LOCK_CONF		0xF0070007
+
+/* SDFR */
+#define	R367_SDFR		0xF008
+#define	F367_OP0_FREQ		0xF00800F0
+#define	F367_OP1_FREQ		0xF008000F
+
+/* STATUS */
+#define	R367_OFDM_STATUS		0xF009
+#define	F367_TPS_LOCK		0xF0090080
+#define	F367_SYR_LOCK		0xF0090040
+#define	F367_AGC_LOCK		0xF0090020
+#define	F367_PRF		0xF0090010
+#define	F367_LK		0xF0090008
+#define	F367_PR		0xF0090007
+
+/* AUX_CLK */
+#define	R367_AUX_CLK		0xF00A
+#define	F367_AUXFEC_CTL		0xF00A00C0
+#define	F367_DIS_CKX4		0xF00A0020
+#define	F367_CKSEL		0xF00A0018
+#define	F367_CKDIV_PROG		0xF00A0006
+#define	F367_AUXCLK_ENA		0xF00A0001
+
+/* FREESYS1 */
+#define	R367_FREESYS1		0xF00B
+#define	F367_FREE_SYS1		0xF00B00FF
+
+/* FREESYS2 */
+#define	R367_FREESYS2		0xF00C
+#define	F367_FREE_SYS2		0xF00C00FF
+
+/* FREESYS3 */
+#define	R367_FREESYS3		0xF00D
+#define	F367_FREE_SYS3		0xF00D00FF
+
+/* GPIO_CFG */
+#define	R367_GPIO_CFG		0xF00E
+#define	F367_GPIO7_NOD		0xF00E0080
+#define	F367_GPIO7_CFG		0xF00E0040
+#define	F367_GPIO6_NOD		0xF00E0020
+#define	F367_GPIO6_CFG		0xF00E0010
+#define	F367_GPIO5_NOD		0xF00E0008
+#define	F367_GPIO5_CFG		0xF00E0004
+#define	F367_GPIO4_NOD		0xF00E0002
+#define	F367_GPIO4_CFG		0xF00E0001
+
+/* GPIO_CMD */
+#define	R367_GPIO_CMD		0xF00F
+#define	F367_GPIO7_VAL		0xF00F0008
+#define	F367_GPIO6_VAL		0xF00F0004
+#define	F367_GPIO5_VAL		0xF00F0002
+#define	F367_GPIO4_VAL		0xF00F0001
+
+/* AGC2MAX */
+#define	R367_OFDM_AGC2MAX		0xF010
+#define	F367_OFDM_AGC2_MAX		0xF01000FF
+
+/* AGC2MIN */
+#define	R367_OFDM_AGC2MIN		0xF011
+#define	F367_OFDM_AGC2_MIN		0xF01100FF
+
+/* AGC1MAX */
+#define	R367_OFDM_AGC1MAX		0xF012
+#define	F367_OFDM_AGC1_MAX		0xF01200FF
+
+/* AGC1MIN */
+#define	R367_OFDM_AGC1MIN		0xF013
+#define	F367_OFDM_AGC1_MIN		0xF01300FF
+
+/* AGCR */
+#define	R367_OFDM_AGCR		0xF014
+#define	F367_OFDM_RATIO_A		0xF01400E0
+#define	F367_OFDM_RATIO_B		0xF0140018
+#define	F367_OFDM_RATIO_C		0xF0140007
+
+/* AGC2TH */
+#define	R367_OFDM_AGC2TH		0xF015
+#define	F367_OFDM_AGC2_THRES		0xF01500FF
+
+/* AGC12C */
+#define	R367_OFDM_AGC12C		0xF016
+#define	F367_OFDM_AGC1_IV		0xF0160080
+#define	F367_OFDM_AGC1_OD		0xF0160040
+#define	F367_OFDM_AGC1_LOAD		0xF0160020
+#define	F367_OFDM_AGC2_IV		0xF0160010
+#define	F367_OFDM_AGC2_OD		0xF0160008
+#define	F367_OFDM_AGC2_LOAD		0xF0160004
+#define	F367_OFDM_AGC12_MODE		0xF0160003
+
+/* AGCCTRL1 */
+#define	R367_OFDM_AGCCTRL1		0xF017
+#define	F367_OFDM_DAGC_ON		0xF0170080
+#define	F367_OFDM_INVERT_AGC12		0xF0170040
+#define	F367_OFDM_AGC1_MODE		0xF0170008
+#define	F367_OFDM_AGC2_MODE		0xF0170007
+
+/* AGCCTRL2 */
+#define	R367_OFDM_AGCCTRL2		0xF018
+#define	F367_OFDM_FRZ2_CTRL		0xF0180060
+#define	F367_OFDM_FRZ1_CTRL		0xF0180018
+#define	F367_OFDM_TIME_CST		0xF0180007
+
+/* AGC1VAL1 */
+#define	R367_OFDM_AGC1VAL1		0xF019
+#define	F367_OFDM_AGC1_VAL_LO		0xF01900FF
+
+/* AGC1VAL2 */
+#define	R367_OFDM_AGC1VAL2		0xF01A
+#define	F367_OFDM_AGC1_VAL_HI		0xF01A000F
+
+/* AGC2VAL1 */
+#define	R367_OFDM_AGC2VAL1		0xF01B
+#define	F367_OFDM_AGC2_VAL_LO		0xF01B00FF
+
+/* AGC2VAL2 */
+#define	R367_OFDM_AGC2VAL2		0xF01C
+#define	F367_OFDM_AGC2_VAL_HI		0xF01C000F
+
+/* AGC2PGA */
+#define	R367_OFDM_AGC2PGA		0xF01D
+#define	F367_OFDM_AGC2_PGA		0xF01D00FF
+
+/* OVF_RATE1 */
+#define	R367_OFDM_OVF_RATE1		0xF01E
+#define	F367_OFDM_OVF_RATE_HI		0xF01E000F
+
+/* OVF_RATE2 */
+#define	R367_OFDM_OVF_RATE2		0xF01F
+#define	F367_OFDM_OVF_RATE_LO		0xF01F00FF
+
+/* GAIN_SRC1 */
+#define	R367_OFDM_GAIN_SRC1		0xF020
+#define	F367_OFDM_INV_SPECTR		0xF0200080
+#define	F367_OFDM_IQ_INVERT		0xF0200040
+#define	F367_OFDM_INR_BYPASS		0xF0200020
+#define	F367_OFDM_STATUS_INV_SPECRUM		0xF0200010
+#define	F367_OFDM_GAIN_SRC_HI		0xF020000F
+
+/* GAIN_SRC2 */
+#define	R367_OFDM_GAIN_SRC2		0xF021
+#define	F367_OFDM_GAIN_SRC_LO		0xF02100FF
+
+/* INC_DEROT1 */
+#define	R367_OFDM_INC_DEROT1		0xF022
+#define	F367_OFDM_INC_DEROT_HI		0xF02200FF
+
+/* INC_DEROT2 */
+#define	R367_OFDM_INC_DEROT2		0xF023
+#define	F367_OFDM_INC_DEROT_LO		0xF02300FF
+
+/* PPM_CPAMP_DIR */
+#define	R367_OFDM_PPM_CPAMP_DIR		0xF024
+#define	F367_OFDM_PPM_CPAMP_DIRECT		0xF02400FF
+
+/* PPM_CPAMP_INV */
+#define	R367_OFDM_PPM_CPAMP_INV		0xF025
+#define	F367_OFDM_PPM_CPAMP_INVER		0xF02500FF
+
+/* FREESTFE_1 */
+#define	R367_OFDM_FREESTFE_1		0xF026
+#define	F367_OFDM_SYMBOL_NUMBER_INC		0xF02600C0
+#define	F367_OFDM_SEL_LSB		0xF0260004
+#define	F367_OFDM_AVERAGE_ON		0xF0260002
+#define	F367_OFDM_DC_ADJ		0xF0260001
+
+/* FREESTFE_2 */
+#define	R367_OFDM_FREESTFE_2		0xF027
+#define	F367_OFDM_SEL_SRCOUT		0xF02700C0
+#define	F367_OFDM_SEL_SYRTHR		0xF027001F
+
+/* DCOFFSET */
+#define	R367_OFDM_DCOFFSET		0xF028
+#define	F367_OFDM_SELECT_I_Q		0xF0280080
+#define	F367_OFDM_DC_OFFSET		0xF028007F
+
+/* EN_PROCESS */
+#define	R367_OFDM_EN_PROCESS		0xF029
+#define	F367_OFDM_FREE		0xF02900F0
+#define	F367_OFDM_ENAB_MANUAL		0xF0290001
+
+/* SDI_SMOOTHER */
+#define	R367_OFDM_SDI_SMOOTHER		0xF02A
+#define	F367_OFDM_DIS_SMOOTH		0xF02A0080
+#define	F367_OFDM_SDI_INC_SMOOTHER		0xF02A007F
+
+/* FE_LOOP_OPEN */
+#define	R367_OFDM_FE_LOOP_OPEN		0xF02B
+#define	F367_OFDM_TRL_LOOP_OP		0xF02B0002
+#define	F367_OFDM_CRL_LOOP_OP		0xF02B0001
+
+/* FREQOFF1 */
+#define	R367_OFDM_FREQOFF1		0xF02C
+#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_VHI		0xF02C00FF
+
+/* FREQOFF2 */
+#define	R367_OFDM_FREQOFF2		0xF02D
+#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_HI		0xF02D00FF
+
+/* FREQOFF3 */
+#define	R367_OFDM_FREQOFF3		0xF02E
+#define	F367_OFDM_FREQ_OFFSET_LOOP_OPEN_LO		0xF02E00FF
+
+/* TIMOFF1 */
+#define	R367_OFDM_TIMOFF1		0xF02F
+#define	F367_OFDM_TIM_OFFSET_LOOP_OPEN_HI		0xF02F00FF
+
+/* TIMOFF2 */
+#define	R367_OFDM_TIMOFF2		0xF030
+#define	F367_OFDM_TIM_OFFSET_LOOP_OPEN_LO		0xF03000FF
+
+/* EPQ */
+#define	R367_OFDM_EPQ		0xF031
+#define	F367_OFDM_EPQ1		0xF03100FF
+
+/* EPQAUTO */
+#define	R367_OFDM_EPQAUTO		0xF032
+#define	F367_OFDM_EPQ2		0xF03200FF
+
+/* SYR_UPDATE */
+#define	R367_OFDM_SYR_UPDATE		0xF033
+#define	F367_OFDM_SYR_PROTV		0xF0330080
+#define	F367_OFDM_SYR_PROTV_GAIN		0xF0330060
+#define	F367_OFDM_SYR_FILTER		0xF0330010
+#define	F367_OFDM_SYR_TRACK_THRES		0xF033000C
+
+/* CHPFREE */
+#define	R367_OFDM_CHPFREE		0xF034
+#define	F367_OFDM_CHP_FREE		0xF03400FF
+
+/* PPM_STATE_MAC */
+#define	R367_OFDM_PPM_STATE_MAC		0xF035
+#define	F367_OFDM_PPM_STATE_MACHINE_DECODER		0xF035003F
+
+/* INR_THRESHOLD */
+#define	R367_OFDM_INR_THRESHOLD		0xF036
+#define	F367_OFDM_INR_THRESH		0xF03600FF
+
+/* EPQ_TPS_ID_CELL */
+#define	R367_OFDM_EPQ_TPS_ID_CELL		0xF037
+#define	F367_OFDM_ENABLE_LGTH_TO_CF		0xF0370080
+#define	F367_OFDM_DIS_TPS_RSVD		0xF0370040
+#define	F367_OFDM_DIS_BCH		0xF0370020
+#define	F367_OFDM_DIS_ID_CEL		0xF0370010
+#define	F367_OFDM_TPS_ADJUST_SYM		0xF037000F
+
+/* EPQ_CFG */
+#define	R367_OFDM_EPQ_CFG		0xF038
+#define	F367_OFDM_EPQ_RANGE		0xF0380002
+#define	F367_OFDM_EPQ_SOFT		0xF0380001
+
+/* EPQ_STATUS */
+#define	R367_OFDM_EPQ_STATUS		0xF039
+#define	F367_OFDM_SLOPE_INC		0xF03900FC
+#define	F367_OFDM_TPS_FIELD		0xF0390003
+
+/* AUTORELOCK */
+#define	R367_OFDM_AUTORELOCK		0xF03A
+#define	F367_OFDM_BYPASS_BER_TEMPO		0xF03A0080
+#define	F367_OFDM_BER_TEMPO		0xF03A0070
+#define	F367_OFDM_BYPASS_COFDM_TEMPO		0xF03A0008
+#define	F367_OFDM_COFDM_TEMPO		0xF03A0007
+
+/* BER_THR_VMSB */
+#define	R367_OFDM_BER_THR_VMSB		0xF03B
+#define	F367_OFDM_BER_THRESHOLD_HI		0xF03B00FF
+
+/* BER_THR_MSB */
+#define	R367_OFDM_BER_THR_MSB		0xF03C
+#define	F367_OFDM_BER_THRESHOLD_MID		0xF03C00FF
+
+/* BER_THR_LSB */
+#define	R367_OFDM_BER_THR_LSB		0xF03D
+#define	F367_OFDM_BER_THRESHOLD_LO		0xF03D00FF
+
+/* CCD */
+#define	R367_OFDM_CCD		0xF03E
+#define	F367_OFDM_CCD_DETECTED		0xF03E0080
+#define	F367_OFDM_CCD_RESET		0xF03E0040
+#define	F367_OFDM_CCD_THRESHOLD		0xF03E000F
+
+/* SPECTR_CFG */
+#define	R367_OFDM_SPECTR_CFG		0xF03F
+#define	F367_OFDM_SPECT_CFG		0xF03F0003
+
+/* CONSTMU_MSB */
+#define	R367_OFDM_CONSTMU_MSB		0xF040
+#define	F367_OFDM_CONSTMU_FREEZE		0xF0400080
+#define	F367_OFDM_CONSTNU_FORCE_EN		0xF0400040
+#define	F367_OFDM_CONST_MU_MSB		0xF040003F
+
+/* CONSTMU_LSB */
+#define	R367_OFDM_CONSTMU_LSB		0xF041
+#define	F367_OFDM_CONST_MU_LSB		0xF04100FF
+
+/* CONSTMU_MAX_MSB */
+#define	R367_OFDM_CONSTMU_MAX_MSB		0xF042
+#define	F367_OFDM_CONST_MU_MAX_MSB		0xF042003F
+
+/* CONSTMU_MAX_LSB */
+#define	R367_OFDM_CONSTMU_MAX_LSB		0xF043
+#define	F367_OFDM_CONST_MU_MAX_LSB		0xF04300FF
+
+/* ALPHANOISE */
+#define	R367_OFDM_ALPHANOISE		0xF044
+#define	F367_OFDM_USE_ALLFILTER		0xF0440080
+#define	F367_OFDM_INTER_ON		0xF0440040
+#define	F367_OFDM_ALPHA_NOISE		0xF044001F
+
+/* MAXGP_MSB */
+#define	R367_OFDM_MAXGP_MSB		0xF045
+#define	F367_OFDM_MUFILTER_LENGTH		0xF04500F0
+#define	F367_OFDM_MAX_GP_MSB		0xF045000F
+
+/* MAXGP_LSB */
+#define	R367_OFDM_MAXGP_LSB		0xF046
+#define	F367_OFDM_MAX_GP_LSB		0xF04600FF
+
+/* ALPHAMSB */
+#define	R367_OFDM_ALPHAMSB		0xF047
+#define	F367_OFDM_CHC_DATARATE		0xF04700C0
+#define	F367_OFDM_ALPHA_MSB		0xF047003F
+
+/* ALPHALSB */
+#define	R367_OFDM_ALPHALSB		0xF048
+#define	F367_OFDM_ALPHA_LSB		0xF04800FF
+
+/* PILOT_ACCU */
+#define	R367_OFDM_PILOT_ACCU		0xF049
+#define	F367_OFDM_USE_SCAT4ADDAPT		0xF0490080
+#define	F367_OFDM_PILOT_ACC		0xF049001F
+
+/* PILOTMU_ACCU */
+#define	R367_OFDM_PILOTMU_ACCU		0xF04A
+#define	F367_OFDM_DISCARD_BAD_SP		0xF04A0080
+#define	F367_OFDM_DISCARD_BAD_CP		0xF04A0040
+#define	F367_OFDM_PILOT_MU_ACCU		0xF04A001F
+
+/* FILT_CHANNEL_EST */
+#define	R367_OFDM_FILT_CHANNEL_EST		0xF04B
+#define	F367_OFDM_USE_FILT_PILOT		0xF04B0080
+#define	F367_OFDM_FILT_CHANNEL		0xF04B007F
+
+/* ALPHA_NOPISE_FREQ */
+#define	R367_OFDM_ALPHA_NOPISE_FREQ		0xF04C
+#define	F367_OFDM_NOISE_FREQ_FILT		0xF04C0040
+#define	F367_OFDM_ALPHA_NOISE_FREQ		0xF04C003F
+
+/* RATIO_PILOT */
+#define	R367_OFDM_RATIO_PILOT		0xF04D
+#define	F367_OFDM_RATIO_MEAN_SP		0xF04D00F0
+#define	F367_OFDM_RATIO_MEAN_CP		0xF04D000F
+
+/* CHC_CTL */
+#define	R367_OFDM_CHC_CTL		0xF04E
+#define	F367_OFDM_TRACK_EN		0xF04E0080
+#define	F367_OFDM_NOISE_NORM_EN		0xF04E0040
+#define	F367_OFDM_FORCE_CHC_RESET		0xF04E0020
+#define	F367_OFDM_SHORT_TIME		0xF04E0010
+#define	F367_OFDM_FORCE_STATE_EN		0xF04E0008
+#define	F367_OFDM_FORCE_STATE		0xF04E0007
+
+/* EPQ_ADJUST */
+#define	R367_OFDM_EPQ_ADJUST		0xF04F
+#define	F367_OFDM_ADJUST_SCAT_IND		0xF04F00C0
+#define	F367_OFDM_ONE_SYMBOL		0xF04F0010
+#define	F367_OFDM_EPQ_DECAY		0xF04F000E
+#define	F367_OFDM_HOLD_SLOPE		0xF04F0001
+
+/* EPQ_THRES */
+#define	R367_OFDM_EPQ_THRES		0xF050
+#define	F367_OFDM_EPQ_THR		0xF05000FF
+
+/* OMEGA_CTL */
+#define	R367_OFDM_OMEGA_CTL		0xF051
+#define	F367_OFDM_OMEGA_RST		0xF0510080
+#define	F367_OFDM_FREEZE_OMEGA		0xF0510040
+#define	F367_OFDM_OMEGA_SEL		0xF051003F
+
+/* GP_CTL */
+#define	R367_OFDM_GP_CTL		0xF052
+#define	F367_OFDM_CHC_STATE		0xF05200E0
+#define	F367_OFDM_FREEZE_GP		0xF0520010
+#define	F367_OFDM_GP_SEL		0xF052000F
+
+/* MUMSB */
+#define	R367_OFDM_MUMSB		0xF053
+#define	F367_OFDM_MU_MSB		0xF053007F
+
+/* MULSB */
+#define	R367_OFDM_MULSB		0xF054
+#define	F367_OFDM_MU_LSB		0xF05400FF
+
+/* GPMSB */
+#define	R367_OFDM_GPMSB		0xF055
+#define	F367_OFDM_CSI_THRESHOLD		0xF05500E0
+#define	F367_OFDM_GP_MSB		0xF055000F
+
+/* GPLSB */
+#define	R367_OFDM_GPLSB		0xF056
+#define	F367_OFDM_GP_LSB		0xF05600FF
+
+/* OMEGAMSB */
+#define	R367_OFDM_OMEGAMSB		0xF057
+#define	F367_OFDM_OMEGA_MSB		0xF057007F
+
+/* OMEGALSB */
+#define	R367_OFDM_OMEGALSB		0xF058
+#define	F367_OFDM_OMEGA_LSB		0xF05800FF
+
+/* SCAT_NB */
+#define	R367_OFDM_SCAT_NB		0xF059
+#define	F367_OFDM_CHC_TEST		0xF05900F8
+#define	F367_OFDM_SCAT_NUMB		0xF0590003
+
+/* CHC_DUMMY */
+#define	R367_OFDM_CHC_DUMMY		0xF05A
+#define	F367_OFDM_CHC_DUM		0xF05A00FF
+
+/* INC_CTL */
+#define	R367_OFDM_INC_CTL		0xF05B
+#define	F367_OFDM_INC_BYPASS		0xF05B0080
+#define	F367_OFDM_INC_NDEPTH		0xF05B000C
+#define	F367_OFDM_INC_MADEPTH		0xF05B0003
+
+/* INCTHRES_COR1 */
+#define	R367_OFDM_INCTHRES_COR1		0xF05C
+#define	F367_OFDM_INC_THRES_COR1		0xF05C00FF
+
+/* INCTHRES_COR2 */
+#define	R367_OFDM_INCTHRES_COR2		0xF05D
+#define	F367_OFDM_INC_THRES_COR2		0xF05D00FF
+
+/* INCTHRES_DET1 */
+#define	R367_OFDM_INCTHRES_DET1		0xF05E
+#define	F367_OFDM_INC_THRES_DET1		0xF05E003F
+
+/* INCTHRES_DET2 */
+#define	R367_OFDM_INCTHRES_DET2		0xF05F
+#define	F367_OFDM_INC_THRES_DET2		0xF05F003F
+
+/* IIR_CELLNB */
+#define	R367_OFDM_IIR_CELLNB		0xF060
+#define	F367_OFDM_NRST_IIR		0xF0600080
+#define	F367_OFDM_IIR_CELL_NB		0xF0600007
+
+/* IIRCX_COEFF1_MSB */
+#define	R367_OFDM_IIRCX_COEFF1_MSB		0xF061
+#define	F367_OFDM_IIR_CX_COEFF1_MSB		0xF06100FF
+
+/* IIRCX_COEFF1_LSB */
+#define	R367_OFDM_IIRCX_COEFF1_LSB		0xF062
+#define	F367_OFDM_IIR_CX_COEFF1_LSB		0xF06200FF
+
+/* IIRCX_COEFF2_MSB */
+#define	R367_OFDM_IIRCX_COEFF2_MSB		0xF063
+#define	F367_OFDM_IIR_CX_COEFF2_MSB		0xF06300FF
+
+/* IIRCX_COEFF2_LSB */
+#define	R367_OFDM_IIRCX_COEFF2_LSB		0xF064
+#define	F367_OFDM_IIR_CX_COEFF2_LSB		0xF06400FF
+
+/* IIRCX_COEFF3_MSB */
+#define	R367_OFDM_IIRCX_COEFF3_MSB		0xF065
+#define	F367_OFDM_IIR_CX_COEFF3_MSB		0xF06500FF
+
+/* IIRCX_COEFF3_LSB */
+#define	R367_OFDM_IIRCX_COEFF3_LSB		0xF066
+#define	F367_OFDM_IIR_CX_COEFF3_LSB		0xF06600FF
+
+/* IIRCX_COEFF4_MSB */
+#define	R367_OFDM_IIRCX_COEFF4_MSB		0xF067
+#define	F367_OFDM_IIR_CX_COEFF4_MSB		0xF06700FF
+
+/* IIRCX_COEFF4_LSB */
+#define	R367_OFDM_IIRCX_COEFF4_LSB		0xF068
+#define	F367_OFDM_IIR_CX_COEFF4_LSB		0xF06800FF
+
+/* IIRCX_COEFF5_MSB */
+#define	R367_OFDM_IIRCX_COEFF5_MSB		0xF069
+#define	F367_OFDM_IIR_CX_COEFF5_MSB		0xF06900FF
+
+/* IIRCX_COEFF5_LSB */
+#define	R367_OFDM_IIRCX_COEFF5_LSB		0xF06A
+#define	F367_OFDM_IIR_CX_COEFF5_LSB		0xF06A00FF
+
+/* FEPATH_CFG */
+#define	R367_OFDM_FEPATH_CFG		0xF06B
+#define	F367_OFDM_DEMUX_SWAP		0xF06B0004
+#define	F367_OFDM_DIGAGC_SWAP		0xF06B0002
+#define	F367_OFDM_LONGPATH_IF		0xF06B0001
+
+/* PMC1_FUNC */
+#define	R367_OFDM_PMC1_FUNC		0xF06C
+#define	F367_OFDM_SOFT_RSTN		0xF06C0080
+#define	F367_OFDM_PMC1_AVERAGE_TIME		0xF06C0078
+#define	F367_OFDM_PMC1_WAIT_TIME		0xF06C0006
+#define	F367_OFDM_PMC1_2N_SEL		0xF06C0001
+
+/* PMC1_FOR */
+#define	R367_OFDM_PMC1_FOR		0xF06D
+#define	F367_OFDM_PMC1_FORCE		0xF06D0080
+#define	F367_OFDM_PMC1_FORCE_VALUE		0xF06D007C
+
+/* PMC2_FUNC */
+#define	R367_OFDM_PMC2_FUNC		0xF06E
+#define	F367_OFDM_PMC2_SOFT_STN		0xF06E0080
+#define	F367_OFDM_PMC2_ACCU_TIME		0xF06E0070
+#define	F367_OFDM_PMC2_CMDP_MN		0xF06E0008
+#define	F367_OFDM_PMC2_SWAP		0xF06E0004
+
+/* STATUS_ERR_DA */
+#define	R367_OFDM_STATUS_ERR_DA		0xF06F
+#define	F367_OFDM_COM_USEGAINTRK		0xF06F0080
+#define	F367_OFDM_COM_AGCLOCK		0xF06F0040
+#define	F367_OFDM_AUT_AGCLOCK		0xF06F0020
+#define	F367_OFDM_MIN_ERR_X_LSB		0xF06F000F
+
+/* DIG_AGC_R */
+#define	R367_OFDM_DIG_AGC_R		0xF070
+#define	F367_OFDM_COM_SOFT_RSTN		0xF0700080
+#define	F367_OFDM_COM_AGC_ON		0xF0700040
+#define	F367_OFDM_COM_EARLY		0xF0700020
+#define	F367_OFDM_AUT_SOFT_RESETN		0xF0700010
+#define	F367_OFDM_AUT_AGC_ON		0xF0700008
+#define	F367_OFDM_AUT_EARLY		0xF0700004
+#define	F367_OFDM_AUT_ROT_EN		0xF0700002
+#define	F367_OFDM_LOCK_SOFT_RESETN		0xF0700001
+
+/* COMAGC_TARMSB */
+#define	R367_OFDM_COMAGC_TARMSB		0xF071
+#define	F367_OFDM_COM_AGC_TARGET_MSB		0xF07100FF
+
+/* COM_AGC_TAR_ENMODE */
+#define	R367_OFDM_COM_AGC_TAR_ENMODE		0xF072
+#define	F367_OFDM_COM_AGC_TARGET_LSB		0xF07200F0
+#define	F367_OFDM_COM_ENMODE		0xF072000F
+
+/* COM_AGC_CFG */
+#define	R367_OFDM_COM_AGC_CFG		0xF073
+#define	F367_OFDM_COM_N		0xF07300F8
+#define	F367_OFDM_COM_STABMODE		0xF0730006
+#define	F367_OFDM_ERR_SEL		0xF0730001
+
+/* COM_AGC_GAIN1 */
+#define	R367_OFDM_COM_AGC_GAIN1		0xF074
+#define	F367_OFDM_COM_GAIN1ACK		0xF07400F0
+#define	F367_OFDM_COM_GAIN1TRK		0xF074000F
+
+/* AUT_AGC_TARGETMSB */
+#define	R367_OFDM_AUT_AGC_TARGETMSB		0xF075
+#define	F367_OFDM_AUT_AGC_TARGET_MSB		0xF07500FF
+
+/* LOCK_DET_MSB */
+#define	R367_OFDM_LOCK_DET_MSB		0xF076
+#define	F367_OFDM_LOCK_DETECT_MSB		0xF07600FF
+
+/* AGCTAR_LOCK_LSBS */
+#define	R367_OFDM_AGCTAR_LOCK_LSBS		0xF077
+#define	F367_OFDM_AUT_AGC_TARGET_LSB		0xF07700F0
+#define	F367_OFDM_LOCK_DETECT_LSB		0xF077000F
+
+/* AUT_GAIN_EN */
+#define	R367_OFDM_AUT_GAIN_EN		0xF078
+#define	F367_OFDM_AUT_ENMODE		0xF07800F0
+#define	F367_OFDM_AUT_GAIN2		0xF078000F
+
+/* AUT_CFG */
+#define	R367_OFDM_AUT_CFG		0xF079
+#define	F367_OFDM_AUT_N		0xF07900F8
+#define	F367_OFDM_INT_CHOICE		0xF0790006
+#define	F367_OFDM_INT_LOAD		0xF0790001
+
+/* LOCKN */
+#define	R367_OFDM_LOCKN		0xF07A
+#define	F367_OFDM_LOCK_N		0xF07A00F8
+#define	F367_OFDM_SEL_IQNTAR		0xF07A0004
+#define	F367_OFDM_LOCK_DETECT_CHOICE		0xF07A0003
+
+/* INT_X_3 */
+#define	R367_OFDM_INT_X_3		0xF07B
+#define	F367_OFDM_INT_X3		0xF07B00FF
+
+/* INT_X_2 */
+#define	R367_OFDM_INT_X_2		0xF07C
+#define	F367_OFDM_INT_X2		0xF07C00FF
+
+/* INT_X_1 */
+#define	R367_OFDM_INT_X_1		0xF07D
+#define	F367_OFDM_INT_X1		0xF07D00FF
+
+/* INT_X_0 */
+#define	R367_OFDM_INT_X_0		0xF07E
+#define	F367_OFDM_INT_X0		0xF07E00FF
+
+/* MIN_ERRX_MSB */
+#define	R367_OFDM_MIN_ERRX_MSB		0xF07F
+#define	F367_OFDM_MIN_ERR_X_MSB		0xF07F00FF
+
+/* COR_CTL */
+#define	R367_OFDM_COR_CTL		0xF080
+#define	F367_OFDM_CORE_ACTIVE		0xF0800020
+#define	F367_OFDM_HOLD		0xF0800010
+#define	F367_OFDM_CORE_STATE_CTL		0xF080000F
+
+/* COR_STAT */
+#define	R367_OFDM_COR_STAT		0xF081
+#define	F367_OFDM_SCATT_LOCKED		0xF0810080
+#define	F367_OFDM_TPS_LOCKED		0xF0810040
+#define	F367_OFDM_SYR_LOCKED_COR		0xF0810020
+#define	F367_OFDM_AGC_LOCKED_STAT		0xF0810010
+#define	F367_OFDM_CORE_STATE_STAT		0xF081000F
+
+/* COR_INTEN */
+#define	R367_OFDM_COR_INTEN		0xF082
+#define	F367_OFDM_INTEN		0xF0820080
+#define	F367_OFDM_INTEN_SYR		0xF0820020
+#define	F367_OFDM_INTEN_FFT		0xF0820010
+#define	F367_OFDM_INTEN_AGC		0xF0820008
+#define	F367_OFDM_INTEN_TPS1		0xF0820004
+#define	F367_OFDM_INTEN_TPS2		0xF0820002
+#define	F367_OFDM_INTEN_TPS3		0xF0820001
+
+/* COR_INTSTAT */
+#define	R367_OFDM_COR_INTSTAT		0xF083
+#define	F367_OFDM_INTSTAT_SYR		0xF0830020
+#define	F367_OFDM_INTSTAT_FFT		0xF0830010
+#define	F367_OFDM_INTSAT_AGC		0xF0830008
+#define	F367_OFDM_INTSTAT_TPS1		0xF0830004
+#define	F367_OFDM_INTSTAT_TPS2		0xF0830002
+#define	F367_OFDM_INTSTAT_TPS3		0xF0830001
+
+/* COR_MODEGUARD */
+#define	R367_OFDM_COR_MODEGUARD		0xF084
+#define	F367_OFDM_FORCE		0xF0840010
+#define	F367_OFDM_MODE		0xF084000C
+#define	F367_OFDM_GUARD		0xF0840003
+
+/* AGC_CTL */
+#define	R367_OFDM_AGC_CTL		0xF085
+#define	F367_OFDM_AGC_TIMING_FACTOR		0xF08500E0
+#define	F367_OFDM_AGC_LAST		0xF0850010
+#define	F367_OFDM_AGC_GAIN		0xF085000C
+#define	F367_OFDM_AGC_NEG		0xF0850002
+#define	F367_OFDM_AGC_SET		0xF0850001
+
+/* AGC_MANUAL1 */
+#define	R367_OFDM_AGC_MANUAL1		0xF086
+#define	F367_OFDM_AGC_VAL_LO		0xF08600FF
+
+/* AGC_MANUAL2 */
+#define	R367_OFDM_AGC_MANUAL2		0xF087
+#define	F367_OFDM_AGC_VAL_HI		0xF087000F
+
+/* AGC_TARG */
+#define	R367_OFDM_AGC_TARG		0xF088
+#define	F367_OFDM_AGC_TARGET		0xF08800FF
+
+/* AGC_GAIN1 */
+#define	R367_OFDM_AGC_GAIN1		0xF089
+#define	F367_OFDM_AGC_GAIN_LO		0xF08900FF
+
+/* AGC_GAIN2 */
+#define	R367_OFDM_AGC_GAIN2		0xF08A
+#define	F367_OFDM_AGC_LOCKED_GAIN2		0xF08A0010
+#define	F367_OFDM_AGC_GAIN_HI		0xF08A000F
+
+/* RESERVED_1 */
+#define	R367_OFDM_RESERVED_1		0xF08B
+#define	F367_OFDM_RESERVED1		0xF08B00FF
+
+/* RESERVED_2 */
+#define	R367_OFDM_RESERVED_2		0xF08C
+#define	F367_OFDM_RESERVED2		0xF08C00FF
+
+/* RESERVED_3 */
+#define	R367_OFDM_RESERVED_3		0xF08D
+#define	F367_OFDM_RESERVED3		0xF08D00FF
+
+/* CAS_CTL */
+#define	R367_OFDM_CAS_CTL		0xF08E
+#define	F367_OFDM_CCS_ENABLE		0xF08E0080
+#define	F367_OFDM_ACS_DISABLE		0xF08E0040
+#define	F367_OFDM_DAGC_DIS		0xF08E0020
+#define	F367_OFDM_DAGC_GAIN		0xF08E0018
+#define	F367_OFDM_CCSMU		0xF08E0007
+
+/* CAS_FREQ */
+#define	R367_OFDM_CAS_FREQ		0xF08F
+#define	F367_OFDM_CCS_FREQ		0xF08F00FF
+
+/* CAS_DAGCGAIN */
+#define	R367_OFDM_CAS_DAGCGAIN		0xF090
+#define	F367_OFDM_CAS_DAGC_GAIN		0xF09000FF
+
+/* SYR_CTL */
+#define	R367_OFDM_SYR_CTL		0xF091
+#define	F367_OFDM_SICTH_ENABLE		0xF0910080
+#define	F367_OFDM_LONG_ECHO		0xF0910078
+#define	F367_OFDM_AUTO_LE_EN		0xF0910004
+#define	F367_OFDM_SYR_BYPASS		0xF0910002
+#define	F367_OFDM_SYR_TR_DIS		0xF0910001
+
+/* SYR_STAT */
+#define	R367_OFDM_SYR_STAT		0xF092
+#define	F367_OFDM_SYR_LOCKED_STAT		0xF0920010
+#define	F367_OFDM_SYR_MODE		0xF092000C
+#define	F367_OFDM_SYR_GUARD		0xF0920003
+
+/* SYR_NCO1 */
+#define	R367_OFDM_SYR_NCO1		0xF093
+#define	F367_OFDM_SYR_NCO_LO		0xF09300FF
+
+/* SYR_NCO2 */
+#define	R367_OFDM_SYR_NCO2		0xF094
+#define	F367_OFDM_SYR_NCO_HI		0xF094003F
+
+/* SYR_OFFSET1 */
+#define	R367_OFDM_SYR_OFFSET1		0xF095
+#define	F367_OFDM_SYR_OFFSET_LO		0xF09500FF
+
+/* SYR_OFFSET2 */
+#define	R367_OFDM_SYR_OFFSET2		0xF096
+#define	F367_OFDM_SYR_OFFSET_HI		0xF096003F
+
+/* FFT_CTL */
+#define	R367_OFDM_FFT_CTL		0xF097
+#define	F367_OFDM_SHIFT_FFT_TRIG		0xF0970018
+#define	F367_OFDM_FFT_TRIGGER		0xF0970004
+#define	F367_OFDM_FFT_MANUAL		0xF0970002
+#define	F367_OFDM_IFFT_MODE		0xF0970001
+
+/* SCR_CTL */
+#define	R367_OFDM_SCR_CTL		0xF098
+#define	F367_OFDM_SYRADJDECAY		0xF0980070
+#define	F367_OFDM_SCR_CPEDIS		0xF0980002
+#define	F367_OFDM_SCR_DIS		0xF0980001
+
+/* PPM_CTL1 */
+#define	R367_OFDM_PPM_CTL1		0xF099
+#define	F367_OFDM_PPM_MAXFREQ		0xF0990030
+#define	F367_OFDM_PPM_MAXTIM		0xF0990008
+#define	F367_OFDM_PPM_INVSEL		0xF0990004
+#define	F367_OFDM_PPM_SCATDIS		0xF0990002
+#define	F367_OFDM_PPM_BYP		0xF0990001
+
+/* TRL_CTL */
+#define	R367_OFDM_TRL_CTL		0xF09A
+#define	F367_OFDM_TRL_NOMRATE_LSB		0xF09A0080
+#define	F367_OFDM_TRL_GAIN_FACTOR		0xF09A0078
+#define	F367_OFDM_TRL_LOOPGAIN		0xF09A0007
+
+/* TRL_NOMRATE1 */
+#define	R367_OFDM_TRL_NOMRATE1		0xF09B
+#define	F367_OFDM_TRL_NOMRATE_LO		0xF09B00FF
+
+/* TRL_NOMRATE2 */
+#define	R367_OFDM_TRL_NOMRATE2		0xF09C
+#define	F367_OFDM_TRL_NOMRATE_HI		0xF09C00FF
+
+/* TRL_TIME1 */
+#define	R367_OFDM_TRL_TIME1		0xF09D
+#define	F367_OFDM_TRL_TOFFSET_LO		0xF09D00FF
+
+/* TRL_TIME2 */
+#define	R367_OFDM_TRL_TIME2		0xF09E
+#define	F367_OFDM_TRL_TOFFSET_HI		0xF09E00FF
+
+/* CRL_CTL */
+#define	R367_OFDM_CRL_CTL		0xF09F
+#define	F367_OFDM_CRL_DIS		0xF09F0080
+#define	F367_OFDM_CRL_GAIN_FACTOR		0xF09F0078
+#define	F367_OFDM_CRL_LOOPGAIN		0xF09F0007
+
+/* CRL_FREQ1 */
+#define	R367_OFDM_CRL_FREQ1		0xF0A0
+#define	F367_OFDM_CRL_FOFFSET_LO		0xF0A000FF
+
+/* CRL_FREQ2 */
+#define	R367_OFDM_CRL_FREQ2		0xF0A1
+#define	F367_OFDM_CRL_FOFFSET_HI		0xF0A100FF
+
+/* CRL_FREQ3 */
+#define	R367_OFDM_CRL_FREQ3		0xF0A2
+#define	F367_OFDM_CRL_FOFFSET_VHI		0xF0A200FF
+
+/* TPS_SFRAME_CTL */
+#define	R367_OFDM_TPS_SFRAME_CTL		0xF0A3
+#define	F367_OFDM_TPS_SFRAME_SYNC		0xF0A30001
+
+/* CHC_SNR */
+#define	R367_OFDM_CHC_SNR		0xF0A4
+#define	F367_OFDM_CHCSNR		0xF0A400FF
+
+/* BDI_CTL */
+#define	R367_OFDM_BDI_CTL		0xF0A5
+#define	F367_OFDM_BDI_LPSEL		0xF0A50002
+#define	F367_OFDM_BDI_SERIAL		0xF0A50001
+
+/* DMP_CTL */
+#define	R367_OFDM_DMP_CTL		0xF0A6
+#define	F367_OFDM_DMP_SCALING_FACTOR		0xF0A6001E
+#define	F367_OFDM_DMP_SDDIS		0xF0A60001
+
+/* TPS_RCVD1 */
+#define	R367_OFDM_TPS_RCVD1		0xF0A7
+#define	F367_OFDM_TPS_CHANGE		0xF0A70040
+#define	F367_OFDM_BCH_OK		0xF0A70020
+#define	F367_OFDM_TPS_SYNC		0xF0A70010
+#define	F367_OFDM_TPS_FRAME		0xF0A70003
+
+/* TPS_RCVD2 */
+#define	R367_OFDM_TPS_RCVD2		0xF0A8
+#define	F367_OFDM_TPS_HIERMODE		0xF0A80070
+#define	F367_OFDM_TPS_CONST		0xF0A80003
+
+/* TPS_RCVD3 */
+#define	R367_OFDM_TPS_RCVD3		0xF0A9
+#define	F367_OFDM_TPS_LPCODE		0xF0A90070
+#define	F367_OFDM_TPS_HPCODE		0xF0A90007
+
+/* TPS_RCVD4 */
+#define	R367_OFDM_TPS_RCVD4		0xF0AA
+#define	F367_OFDM_TPS_GUARD		0xF0AA0030
+#define	F367_OFDM_TPS_MODE		0xF0AA0003
+
+/* TPS_ID_CELL1 */
+#define	R367_OFDM_TPS_ID_CELL1		0xF0AB
+#define	F367_OFDM_TPS_ID_CELL_LO		0xF0AB00FF
+
+/* TPS_ID_CELL2 */
+#define	R367_OFDM_TPS_ID_CELL2		0xF0AC
+#define	F367_OFDM_TPS_ID_CELL_HI		0xF0AC00FF
+
+/* TPS_RCVD5_SET1 */
+#define	R367_OFDM_TPS_RCVD5_SET1		0xF0AD
+#define	F367_OFDM_TPS_NA		0xF0AD00FC
+#define	F367_OFDM_TPS_SETFRAME		0xF0AD0003
+
+/* TPS_SET2 */
+#define	R367_OFDM_TPS_SET2		0xF0AE
+#define	F367_OFDM_TPS_SETHIERMODE		0xF0AE0070
+#define	F367_OFDM_TPS_SETCONST		0xF0AE0003
+
+/* TPS_SET3 */
+#define	R367_OFDM_TPS_SET3		0xF0AF
+#define	F367_OFDM_TPS_SETLPCODE		0xF0AF0070
+#define	F367_OFDM_TPS_SETHPCODE		0xF0AF0007
+
+/* TPS_CTL */
+#define	R367_OFDM_TPS_CTL		0xF0B0
+#define	F367_OFDM_TPS_IMM		0xF0B00004
+#define	F367_OFDM_TPS_BCHDIS		0xF0B00002
+#define	F367_OFDM_TPS_UPDDIS		0xF0B00001
+
+/* CTL_FFTOSNUM */
+#define	R367_OFDM_CTL_FFTOSNUM		0xF0B1
+#define	F367_OFDM_SYMBOL_NUMBER		0xF0B1007F
+
+/* TESTSELECT */
+#define	R367_OFDM_TESTSELECT		0xF0B2
+#define	F367_OFDM_TEST_SELECT		0xF0B2001F
+
+/* MSC_REV */
+#define	R367_OFDM_MSC_REV		0xF0B3
+#define	F367_OFDM_REV_NUMBER		0xF0B300FF
+
+/* PIR_CTL */
+#define	R367_OFDM_PIR_CTL		0xF0B4
+#define	F367_OFDM_FREEZE		0xF0B40001
+
+/* SNR_CARRIER1 */
+#define	R367_OFDM_SNR_CARRIER1		0xF0B5
+#define	F367_OFDM_SNR_CARRIER_LO		0xF0B500FF
+
+/* SNR_CARRIER2 */
+#define	R367_OFDM_SNR_CARRIER2		0xF0B6
+#define	F367_OFDM_MEAN		0xF0B600C0
+#define	F367_OFDM_SNR_CARRIER_HI		0xF0B6001F
+
+/* PPM_CPAMP */
+#define	R367_OFDM_PPM_CPAMP		0xF0B7
+#define	F367_OFDM_PPM_CPC		0xF0B700FF
+
+/* TSM_AP0 */
+#define	R367_OFDM_TSM_AP0		0xF0B8
+#define	F367_OFDM_ADDRESS_BYTE_0		0xF0B800FF
+
+/* TSM_AP1 */
+#define	R367_OFDM_TSM_AP1		0xF0B9
+#define	F367_OFDM_ADDRESS_BYTE_1		0xF0B900FF
+
+/* TSM_AP2 */
+#define	R367_OFDM_TSM_AP2		0xF0BA
+#define	F367_OFDM_DATA_BYTE_0		0xF0BA00FF
+
+/* TSM_AP3 */
+#define	R367_OFDM_TSM_AP3		0xF0BB
+#define	F367_OFDM_DATA_BYTE_1		0xF0BB00FF
+
+/* TSM_AP4 */
+#define	R367_OFDM_TSM_AP4		0xF0BC
+#define	F367_OFDM_DATA_BYTE_2		0xF0BC00FF
+
+/* TSM_AP5 */
+#define	R367_OFDM_TSM_AP5		0xF0BD
+#define	F367_OFDM_DATA_BYTE_3		0xF0BD00FF
+
+/* TSM_AP6 */
+#define	R367_OFDM_TSM_AP6		0xF0BE
+#define	F367_OFDM_TSM_AP_6		0xF0BE00FF
+
+/* TSM_AP7 */
+#define	R367_OFDM_TSM_AP7		0xF0BF
+#define	F367_OFDM_MEM_SELECT_BYTE		0xF0BF00FF
+
+/* TSTRES */
+#define	R367_TSTRES		0xF0C0
+#define	F367_FRES_DISPLAY		0xF0C00080
+#define	F367_FRES_FIFO_AD		0xF0C00020
+#define	F367_FRESRS		0xF0C00010
+#define	F367_FRESACS		0xF0C00008
+#define	F367_FRESFEC		0xF0C00004
+#define	F367_FRES_PRIF		0xF0C00002
+#define	F367_FRESCORE		0xF0C00001
+
+/* ANACTRL */
+#define	R367_ANACTRL		0xF0C1
+#define	F367_BYPASS_XTAL		0xF0C10040
+#define	F367_BYPASS_PLLXN		0xF0C1000C
+#define	F367_DIS_PAD_OSC		0xF0C10002
+#define	F367_STDBY_PLLXN		0xF0C10001
+
+/* TSTBUS */
+#define	R367_TSTBUS		0xF0C2
+#define	F367_TS_BYTE_CLK_INV		0xF0C20080
+#define	F367_CFG_IP		0xF0C20070
+#define	F367_CFG_TST		0xF0C2000F
+
+/* TSTRATE */
+#define	R367_TSTRATE		0xF0C6
+#define	F367_FORCEPHA		0xF0C60080
+#define	F367_FNEWPHA		0xF0C60010
+#define	F367_FROT90		0xF0C60008
+#define	F367_FR		0xF0C60007
+
+/* CONSTMODE */
+#define	R367_OFDM_CONSTMODE		0xF0CB
+#define	F367_OFDM_TST_PRIF		0xF0CB00E0
+#define	F367_OFDM_CAR_TYPE		0xF0CB0018
+#define	F367_OFDM_CONST_MODE		0xF0CB0003
+
+/* CONSTCARR1 */
+#define	R367_OFDM_CONSTCARR1		0xF0CC
+#define	F367_OFDM_CONST_CARR_LO		0xF0CC00FF
+
+/* CONSTCARR2 */
+#define	R367_OFDM_CONSTCARR2		0xF0CD
+#define	F367_OFDM_CONST_CARR_HI		0xF0CD001F
+
+/* ICONSTEL */
+#define	R367_OFDM_ICONSTEL		0xF0CE
+#define	F367_OFDM_PICONSTEL		0xF0CE00FF
+
+/* QCONSTEL */
+#define	R367_OFDM_QCONSTEL		0xF0CF
+#define	F367_OFDM_PQCONSTEL		0xF0CF00FF
+
+/* TSTBISTRES0 */
+#define	R367_OFDM_TSTBISTRES0		0xF0D0
+#define	F367_OFDM_BEND_PPM		0xF0D00080
+#define	F367_OFDM_BBAD_PPM		0xF0D00040
+#define	F367_OFDM_BEND_FFTW		0xF0D00020
+#define	F367_OFDM_BBAD_FFTW		0xF0D00010
+#define	F367_OFDM_BEND_FFT_BUF		0xF0D00008
+#define	F367_OFDM_BBAD_FFT_BUF		0xF0D00004
+#define	F367_OFDM_BEND_SYR		0xF0D00002
+#define	F367_OFDM_BBAD_SYR		0xF0D00001
+
+/* TSTBISTRES1 */
+#define	R367_OFDM_TSTBISTRES1		0xF0D1
+#define	F367_OFDM_BEND_CHC_CP		0xF0D10080
+#define	F367_OFDM_BBAD_CHC_CP		0xF0D10040
+#define	F367_OFDM_BEND_CHCI		0xF0D10020
+#define	F367_OFDM_BBAD_CHCI		0xF0D10010
+#define	F367_OFDM_BEND_BDI		0xF0D10008
+#define	F367_OFDM_BBAD_BDI		0xF0D10004
+#define	F367_OFDM_BEND_SDI		0xF0D10002
+#define	F367_OFDM_BBAD_SDI		0xF0D10001
+
+/* TSTBISTRES2 */
+#define	R367_OFDM_TSTBISTRES2		0xF0D2
+#define	F367_OFDM_BEND_CHC_INC		0xF0D20080
+#define	F367_OFDM_BBAD_CHC_INC		0xF0D20040
+#define	F367_OFDM_BEND_CHC_SPP		0xF0D20020
+#define	F367_OFDM_BBAD_CHC_SPP		0xF0D20010
+#define	F367_OFDM_BEND_CHC_CPP		0xF0D20008
+#define	F367_OFDM_BBAD_CHC_CPP		0xF0D20004
+#define	F367_OFDM_BEND_CHC_SP		0xF0D20002
+#define	F367_OFDM_BBAD_CHC_SP		0xF0D20001
+
+/* TSTBISTRES3 */
+#define	R367_OFDM_TSTBISTRES3		0xF0D3
+#define	F367_OFDM_BEND_QAM		0xF0D30080
+#define	F367_OFDM_BBAD_QAM		0xF0D30040
+#define	F367_OFDM_BEND_SFEC_VIT		0xF0D30020
+#define	F367_OFDM_BBAD_SFEC_VIT		0xF0D30010
+#define	F367_OFDM_BEND_SFEC_DLINE		0xF0D30008
+#define	F367_OFDM_BBAD_SFEC_DLINE		0xF0D30004
+#define	F367_OFDM_BEND_SFEC_HW		0xF0D30002
+#define	F367_OFDM_BBAD_SFEC_HW		0xF0D30001
+
+/* RF_AGC1 */
+#define	R367_RF_AGC1		0xF0D4
+#define	F367_RF_AGC1_LEVEL_HI		0xF0D400FF
+
+/* RF_AGC2 */
+#define	R367_RF_AGC2		0xF0D5
+#define	F367_REF_ADGP		0xF0D50080
+#define	F367_STDBY_ADCGP		0xF0D50020
+#define	F367_CHANNEL_SEL		0xF0D5001C
+#define	F367_RF_AGC1_LEVEL_LO		0xF0D50003
+
+/* ANADIGCTRL */
+#define	R367_ANADIGCTRL		0xF0D7
+#define	F367_SEL_CLKDEM		0xF0D70020
+#define	F367_EN_BUFFER_Q		0xF0D70010
+#define	F367_EN_BUFFER_I		0xF0D70008
+#define	F367_ADC_RIS_EGDE		0xF0D70004
+#define	F367_SGN_ADC		0xF0D70002
+#define	F367_SEL_AD12_SYNC		0xF0D70001
+
+/* PLLMDIV */
+#define	R367_PLLMDIV		0xF0D8
+#define	F367_PLL_MDIV		0xF0D800FF
+
+/* PLLNDIV */
+#define	R367_PLLNDIV		0xF0D9
+#define	F367_PLL_NDIV		0xF0D900FF
+
+/* PLLSETUP */
+#define	R367_PLLSETUP		0xF0DA
+#define	F367_PLL_PDIV		0xF0DA0070
+#define	F367_PLL_KDIV		0xF0DA000F
+
+/* DUAL_AD12 */
+#define	R367_DUAL_AD12		0xF0DB
+#define	F367_FS20M		0xF0DB0020
+#define	F367_FS50M		0xF0DB0010
+#define	F367_INMODE0		0xF0DB0008
+#define	F367_POFFQ		0xF0DB0004
+#define	F367_POFFI		0xF0DB0002
+#define	F367_INMODE1		0xF0DB0001
+
+/* TSTBIST */
+#define	R367_TSTBIST		0xF0DC
+#define	F367_TST_BYP_CLK		0xF0DC0080
+#define	F367_TST_GCLKENA_STD		0xF0DC0040
+#define	F367_TST_GCLKENA		0xF0DC0020
+#define	F367_TST_MEMBIST		0xF0DC001F
+
+/* PAD_COMP_CTRL */
+#define	R367_PAD_COMP_CTRL		0xF0DD
+#define	F367_COMPTQ		0xF0DD0010
+#define	F367_COMPEN		0xF0DD0008
+#define	F367_FREEZE2		0xF0DD0004
+#define	F367_SLEEP_INHBT		0xF0DD0002
+#define	F367_CHIP_SLEEP		0xF0DD0001
+
+/* PAD_COMP_WR */
+#define	R367_PAD_COMP_WR		0xF0DE
+#define	F367_WR_ASRC		0xF0DE007F
+
+/* PAD_COMP_RD */
+#define	R367_PAD_COMP_RD		0xF0DF
+#define	F367_COMPOK		0xF0DF0080
+#define	F367_RD_ASRC		0xF0DF007F
+
+/* SYR_TARGET_FFTADJT_MSB */
+#define	R367_OFDM_SYR_TARGET_FFTADJT_MSB		0xF100
+#define	F367_OFDM_SYR_START		0xF1000080
+#define	F367_OFDM_SYR_TARGET_FFTADJ_HI		0xF100000F
+
+/* SYR_TARGET_FFTADJT_LSB */
+#define	R367_OFDM_SYR_TARGET_FFTADJT_LSB		0xF101
+#define	F367_OFDM_SYR_TARGET_FFTADJ_LO		0xF10100FF
+
+/* SYR_TARGET_CHCADJT_MSB */
+#define	R367_OFDM_SYR_TARGET_CHCADJT_MSB		0xF102
+#define	F367_OFDM_SYR_TARGET_CHCADJ_HI		0xF102000F
+
+/* SYR_TARGET_CHCADJT_LSB */
+#define	R367_OFDM_SYR_TARGET_CHCADJT_LSB		0xF103
+#define	F367_OFDM_SYR_TARGET_CHCADJ_LO		0xF10300FF
+
+/* SYR_FLAG */
+#define	R367_OFDM_SYR_FLAG		0xF104
+#define	F367_OFDM_TRIG_FLG1		0xF1040080
+#define	F367_OFDM_TRIG_FLG0		0xF1040040
+#define	F367_OFDM_FFT_FLG1		0xF1040008
+#define	F367_OFDM_FFT_FLG0		0xF1040004
+#define	F367_OFDM_CHC_FLG1		0xF1040002
+#define	F367_OFDM_CHC_FLG0		0xF1040001
+
+/* CRL_TARGET1 */
+#define	R367_OFDM_CRL_TARGET1		0xF105
+#define	F367_OFDM_CRL_START		0xF1050080
+#define	F367_OFDM_CRL_TARGET_VHI		0xF105000F
+
+/* CRL_TARGET2 */
+#define	R367_OFDM_CRL_TARGET2		0xF106
+#define	F367_OFDM_CRL_TARGET_HI		0xF10600FF
+
+/* CRL_TARGET3 */
+#define	R367_OFDM_CRL_TARGET3		0xF107
+#define	F367_OFDM_CRL_TARGET_LO		0xF10700FF
+
+/* CRL_TARGET4 */
+#define	R367_OFDM_CRL_TARGET4		0xF108
+#define	F367_OFDM_CRL_TARGET_VLO		0xF10800FF
+
+/* CRL_FLAG */
+#define	R367_OFDM_CRL_FLAG		0xF109
+#define	F367_OFDM_CRL_FLAG1		0xF1090002
+#define	F367_OFDM_CRL_FLAG0		0xF1090001
+
+/* TRL_TARGET1 */
+#define	R367_OFDM_TRL_TARGET1		0xF10A
+#define	F367_OFDM_TRL_TARGET_HI		0xF10A00FF
+
+/* TRL_TARGET2 */
+#define	R367_OFDM_TRL_TARGET2		0xF10B
+#define	F367_OFDM_TRL_TARGET_LO		0xF10B00FF
+
+/* TRL_CHC */
+#define	R367_OFDM_TRL_CHC		0xF10C
+#define	F367_OFDM_TRL_START		0xF10C0080
+#define	F367_OFDM_CHC_START		0xF10C0040
+#define	F367_OFDM_TRL_FLAG1		0xF10C0002
+#define	F367_OFDM_TRL_FLAG0		0xF10C0001
+
+/* CHC_SNR_TARG */
+#define	R367_OFDM_CHC_SNR_TARG		0xF10D
+#define	F367_OFDM_CHC_SNR_TARGET		0xF10D00FF
+
+/* TOP_TRACK */
+#define	R367_OFDM_TOP_TRACK		0xF10E
+#define	F367_OFDM_TOP_START		0xF10E0080
+#define	F367_OFDM_FIRST_FLAG		0xF10E0070
+#define	F367_OFDM_TOP_FLAG1		0xF10E0008
+#define	F367_OFDM_TOP_FLAG0		0xF10E0004
+#define	F367_OFDM_CHC_FLAG1		0xF10E0002
+#define	F367_OFDM_CHC_FLAG0		0xF10E0001
+
+/* TRACKER_FREE1 */
+#define	R367_OFDM_TRACKER_FREE1		0xF10F
+#define	F367_OFDM_TRACKER_FREE_1		0xF10F00FF
+
+/* ERROR_CRL1 */
+#define	R367_OFDM_ERROR_CRL1		0xF110
+#define	F367_OFDM_ERROR_CRL_VHI		0xF11000FF
+
+/* ERROR_CRL2 */
+#define	R367_OFDM_ERROR_CRL2		0xF111
+#define	F367_OFDM_ERROR_CRL_HI		0xF11100FF
+
+/* ERROR_CRL3 */
+#define	R367_OFDM_ERROR_CRL3		0xF112
+#define	F367_OFDM_ERROR_CRL_LOI		0xF11200FF
+
+/* ERROR_CRL4 */
+#define	R367_OFDM_ERROR_CRL4		0xF113
+#define	F367_OFDM_ERROR_CRL_VLO		0xF11300FF
+
+/* DEC_NCO1 */
+#define	R367_OFDM_DEC_NCO1		0xF114
+#define	F367_OFDM_DEC_NCO_VHI		0xF11400FF
+
+/* DEC_NCO2 */
+#define	R367_OFDM_DEC_NCO2		0xF115
+#define	F367_OFDM_DEC_NCO_HI		0xF11500FF
+
+/* DEC_NCO3 */
+#define	R367_OFDM_DEC_NCO3		0xF116
+#define	F367_OFDM_DEC_NCO_LO		0xF11600FF
+
+/* SNR */
+#define	R367_OFDM_SNR		0xF117
+#define	F367_OFDM_SNRATIO		0xF11700FF
+
+/* SYR_FFTADJ1 */
+#define	R367_OFDM_SYR_FFTADJ1		0xF118
+#define	F367_OFDM_SYR_FFTADJ_HI		0xF11800FF
+
+/* SYR_FFTADJ2 */
+#define	R367_OFDM_SYR_FFTADJ2		0xF119
+#define	F367_OFDM_SYR_FFTADJ_LO		0xF11900FF
+
+/* SYR_CHCADJ1 */
+#define	R367_OFDM_SYR_CHCADJ1		0xF11A
+#define	F367_OFDM_SYR_CHCADJ_HI		0xF11A00FF
+
+/* SYR_CHCADJ2 */
+#define	R367_OFDM_SYR_CHCADJ2		0xF11B
+#define	F367_OFDM_SYR_CHCADJ_LO		0xF11B00FF
+
+/* SYR_OFF */
+#define	R367_OFDM_SYR_OFF		0xF11C
+#define	F367_OFDM_SYR_OFFSET		0xF11C00FF
+
+/* PPM_OFFSET1 */
+#define	R367_OFDM_PPM_OFFSET1		0xF11D
+#define	F367_OFDM_PPM_OFFSET_HI		0xF11D00FF
+
+/* PPM_OFFSET2 */
+#define	R367_OFDM_PPM_OFFSET2		0xF11E
+#define	F367_OFDM_PPM_OFFSET_LO		0xF11E00FF
+
+/* TRACKER_FREE2 */
+#define	R367_OFDM_TRACKER_FREE2		0xF11F
+#define	F367_OFDM_TRACKER_FREE_2		0xF11F00FF
+
+/* DEBG_LT10 */
+#define	R367_OFDM_DEBG_LT10		0xF120
+#define	F367_OFDM_DEBUG_LT10		0xF12000FF
+
+/* DEBG_LT11 */
+#define	R367_OFDM_DEBG_LT11		0xF121
+#define	F367_OFDM_DEBUG_LT11		0xF12100FF
+
+/* DEBG_LT12 */
+#define	R367_OFDM_DEBG_LT12		0xF122
+#define	F367_OFDM_DEBUG_LT12		0xF12200FF
+
+/* DEBG_LT13 */
+#define	R367_OFDM_DEBG_LT13		0xF123
+#define	F367_OFDM_DEBUG_LT13		0xF12300FF
+
+/* DEBG_LT14 */
+#define	R367_OFDM_DEBG_LT14		0xF124
+#define	F367_OFDM_DEBUG_LT14		0xF12400FF
+
+/* DEBG_LT15 */
+#define	R367_OFDM_DEBG_LT15		0xF125
+#define	F367_OFDM_DEBUG_LT15		0xF12500FF
+
+/* DEBG_LT16 */
+#define	R367_OFDM_DEBG_LT16		0xF126
+#define	F367_OFDM_DEBUG_LT16		0xF12600FF
+
+/* DEBG_LT17 */
+#define	R367_OFDM_DEBG_LT17		0xF127
+#define	F367_OFDM_DEBUG_LT17		0xF12700FF
+
+/* DEBG_LT18 */
+#define	R367_OFDM_DEBG_LT18		0xF128
+#define	F367_OFDM_DEBUG_LT18		0xF12800FF
+
+/* DEBG_LT19 */
+#define	R367_OFDM_DEBG_LT19		0xF129
+#define	F367_OFDM_DEBUG_LT19		0xF12900FF
+
+/* DEBG_LT1A */
+#define	R367_OFDM_DEBG_LT1A		0xF12A
+#define	F367_OFDM_DEBUG_LT1A		0xF12A00FF
+
+/* DEBG_LT1B */
+#define	R367_OFDM_DEBG_LT1B		0xF12B
+#define	F367_OFDM_DEBUG_LT1B		0xF12B00FF
+
+/* DEBG_LT1C */
+#define	R367_OFDM_DEBG_LT1C		0xF12C
+#define	F367_OFDM_DEBUG_LT1C		0xF12C00FF
+
+/* DEBG_LT1D */
+#define	R367_OFDM_DEBG_LT1D		0xF12D
+#define	F367_OFDM_DEBUG_LT1D		0xF12D00FF
+
+/* DEBG_LT1E */
+#define	R367_OFDM_DEBG_LT1E		0xF12E
+#define	F367_OFDM_DEBUG_LT1E		0xF12E00FF
+
+/* DEBG_LT1F */
+#define	R367_OFDM_DEBG_LT1F		0xF12F
+#define	F367_OFDM_DEBUG_LT1F		0xF12F00FF
+
+/* RCCFGH */
+#define	R367_OFDM_RCCFGH		0xF200
+#define	F367_OFDM_TSRCFIFO_DVBCI		0xF2000080
+#define	F367_OFDM_TSRCFIFO_SERIAL		0xF2000040
+#define	F367_OFDM_TSRCFIFO_DISABLE		0xF2000020
+#define	F367_OFDM_TSFIFO_2TORC		0xF2000010
+#define	F367_OFDM_TSRCFIFO_HSGNLOUT		0xF2000008
+#define	F367_OFDM_TSRCFIFO_ERRMODE		0xF2000006
+#define	F367_OFDM_RCCFGH_0		0xF2000001
+
+/* RCCFGM */
+#define	R367_OFDM_RCCFGM		0xF201
+#define	F367_OFDM_TSRCFIFO_MANSPEED		0xF20100C0
+#define	F367_OFDM_TSRCFIFO_PERMDATA		0xF2010020
+#define	F367_OFDM_TSRCFIFO_NONEWSGNL		0xF2010010
+#define	F367_OFDM_RCBYTE_OVERSAMPLING		0xF201000E
+#define	F367_OFDM_TSRCFIFO_INVDATA		0xF2010001
+
+/* RCCFGL */
+#define	R367_OFDM_RCCFGL		0xF202
+#define	F367_OFDM_TSRCFIFO_BCLKDEL1CK		0xF20200C0
+#define	F367_OFDM_RCCFGL_5		0xF2020020
+#define	F367_OFDM_TSRCFIFO_DUTY50		0xF2020010
+#define	F367_OFDM_TSRCFIFO_NSGNL2DATA		0xF2020008
+#define	F367_OFDM_TSRCFIFO_DISSERMUX		0xF2020004
+#define	F367_OFDM_RCCFGL_1		0xF2020002
+#define	F367_OFDM_TSRCFIFO_STOPCKDIS		0xF2020001
+
+/* RCINSDELH */
+#define	R367_OFDM_RCINSDELH		0xF203
+#define	F367_OFDM_TSRCDEL_SYNCBYTE		0xF2030080
+#define	F367_OFDM_TSRCDEL_XXHEADER		0xF2030040
+#define	F367_OFDM_TSRCDEL_BBHEADER		0xF2030020
+#define	F367_OFDM_TSRCDEL_DATAFIELD		0xF2030010
+#define	F367_OFDM_TSRCINSDEL_ISCR		0xF2030008
+#define	F367_OFDM_TSRCINSDEL_NPD		0xF2030004
+#define	F367_OFDM_TSRCINSDEL_RSPARITY		0xF2030002
+#define	F367_OFDM_TSRCINSDEL_CRC8		0xF2030001
+
+/* RCINSDELM */
+#define	R367_OFDM_RCINSDELM		0xF204
+#define	F367_OFDM_TSRCINS_BBPADDING		0xF2040080
+#define	F367_OFDM_TSRCINS_BCHFEC		0xF2040040
+#define	F367_OFDM_TSRCINS_LDPCFEC		0xF2040020
+#define	F367_OFDM_TSRCINS_EMODCOD		0xF2040010
+#define	F367_OFDM_TSRCINS_TOKEN		0xF2040008
+#define	F367_OFDM_TSRCINS_XXXERR		0xF2040004
+#define	F367_OFDM_TSRCINS_MATYPE		0xF2040002
+#define	F367_OFDM_TSRCINS_UPL		0xF2040001
+
+/* RCINSDELL */
+#define	R367_OFDM_RCINSDELL		0xF205
+#define	F367_OFDM_TSRCINS_DFL		0xF2050080
+#define	F367_OFDM_TSRCINS_SYNCD		0xF2050040
+#define	F367_OFDM_TSRCINS_BLOCLEN		0xF2050020
+#define	F367_OFDM_TSRCINS_SIGPCOUNT		0xF2050010
+#define	F367_OFDM_TSRCINS_FIFO		0xF2050008
+#define	F367_OFDM_TSRCINS_REALPACK		0xF2050004
+#define	F367_OFDM_TSRCINS_TSCONFIG		0xF2050002
+#define	F367_OFDM_TSRCINS_LATENCY		0xF2050001
+
+/* RCSTATUS */
+#define	R367_OFDM_RCSTATUS		0xF206
+#define	F367_OFDM_TSRCFIFO_LINEOK		0xF2060080
+#define	F367_OFDM_TSRCFIFO_ERROR		0xF2060040
+#define	F367_OFDM_TSRCFIFO_DATA7		0xF2060020
+#define	F367_OFDM_RCSTATUS_4		0xF2060010
+#define	F367_OFDM_TSRCFIFO_DEMODSEL		0xF2060008
+#define	F367_OFDM_TSRC1FIFOSPEED_STORE		0xF2060004
+#define	F367_OFDM_RCSTATUS_1		0xF2060002
+#define	F367_OFDM_TSRCSERIAL_IMPOSSIBLE		0xF2060001
+
+/* RCSPEED */
+#define	R367_OFDM_RCSPEED		0xF207
+#define	F367_OFDM_TSRCFIFO_OUTSPEED		0xF20700FF
+
+/* RCDEBUGM */
+#define	R367_OFDM_RCDEBUGM		0xF208
+#define	F367_OFDM_SD_UNSYNC		0xF2080080
+#define	F367_OFDM_ULFLOCK_DETECTM		0xF2080040
+#define	F367_OFDM_SUL_SELECTOS		0xF2080020
+#define	F367_OFDM_DILUL_NOSCRBLE		0xF2080010
+#define	F367_OFDM_NUL_SCRB		0xF2080008
+#define	F367_OFDM_UL_SCRB		0xF2080004
+#define	F367_OFDM_SCRAULBAD		0xF2080002
+#define	F367_OFDM_SCRAUL_UNSYNC		0xF2080001
+
+/* RCDEBUGL */
+#define	R367_OFDM_RCDEBUGL		0xF209
+#define	F367_OFDM_RS_ERR		0xF2090080
+#define	F367_OFDM_LLFLOCK_DETECTM		0xF2090040
+#define	F367_OFDM_NOT_SUL_SELECTOS		0xF2090020
+#define	F367_OFDM_DILLL_NOSCRBLE		0xF2090010
+#define	F367_OFDM_NLL_SCRB		0xF2090008
+#define	F367_OFDM_LL_SCRB		0xF2090004
+#define	F367_OFDM_SCRALLBAD		0xF2090002
+#define	F367_OFDM_SCRALL_UNSYNC		0xF2090001
+
+/* RCOBSCFG */
+#define	R367_OFDM_RCOBSCFG		0xF20A
+#define	F367_OFDM_TSRCFIFO_OBSCFG		0xF20A00FF
+
+/* RCOBSM */
+#define	R367_OFDM_RCOBSM		0xF20B
+#define	F367_OFDM_TSRCFIFO_OBSDATA_HI		0xF20B00FF
+
+/* RCOBSL */
+#define	R367_OFDM_RCOBSL		0xF20C
+#define	F367_OFDM_TSRCFIFO_OBSDATA_LO		0xF20C00FF
+
+/* RCFECSPY */
+#define	R367_OFDM_RCFECSPY		0xF210
+#define	F367_OFDM_SPYRC_ENABLE		0xF2100080
+#define	F367_OFDM_RCNO_SYNCBYTE		0xF2100040
+#define	F367_OFDM_RCSERIAL_MODE		0xF2100020
+#define	F367_OFDM_RCUNUSUAL_PACKET		0xF2100010
+#define	F367_OFDM_BERRCMETER_DATAMODE		0xF210000C
+#define	F367_OFDM_BERRCMETER_LMODE		0xF2100002
+#define	F367_OFDM_BERRCMETER_RESET		0xF2100001
+
+/* RCFSPYCFG */
+#define	R367_OFDM_RCFSPYCFG		0xF211
+#define	F367_OFDM_FECSPYRC_INPUT		0xF21100C0
+#define	F367_OFDM_RCRST_ON_ERROR		0xF2110020
+#define	F367_OFDM_RCONE_SHOT		0xF2110010
+#define	F367_OFDM_RCI2C_MODE		0xF211000C
+#define	F367_OFDM_SPYRC_HSTERESIS		0xF2110003
+
+/* RCFSPYDATA */
+#define	R367_OFDM_RCFSPYDATA		0xF212
+#define	F367_OFDM_SPYRC_STUFFING		0xF2120080
+#define	F367_OFDM_RCNOERR_PKTJITTER		0xF2120040
+#define	F367_OFDM_SPYRC_CNULLPKT		0xF2120020
+#define	F367_OFDM_SPYRC_OUTDATA_MODE		0xF212001F
+
+/* RCFSPYOUT */
+#define	R367_OFDM_RCFSPYOUT		0xF213
+#define	F367_OFDM_FSPYRC_DIRECT		0xF2130080
+#define	F367_OFDM_RCFSPYOUT_6		0xF2130040
+#define	F367_OFDM_SPYRC_OUTDATA_BUS		0xF2130038
+#define	F367_OFDM_RCSTUFF_MODE		0xF2130007
+
+/* RCFSTATUS */
+#define	R367_OFDM_RCFSTATUS		0xF214
+#define	F367_OFDM_SPYRC_ENDSIM		0xF2140080
+#define	F367_OFDM_RCVALID_SIM		0xF2140040
+#define	F367_OFDM_RCFOUND_SIGNAL		0xF2140020
+#define	F367_OFDM_RCDSS_SYNCBYTE		0xF2140010
+#define	F367_OFDM_RCRESULT_STATE		0xF214000F
+
+/* RCFGOODPACK */
+#define	R367_OFDM_RCFGOODPACK		0xF215
+#define	F367_OFDM_RCGOOD_PACKET		0xF21500FF
+
+/* RCFPACKCNT */
+#define	R367_OFDM_RCFPACKCNT		0xF216
+#define	F367_OFDM_RCPACKET_COUNTER		0xF21600FF
+
+/* RCFSPYMISC */
+#define	R367_OFDM_RCFSPYMISC		0xF217
+#define	F367_OFDM_RCLABEL_COUNTER		0xF21700FF
+
+/* RCFBERCPT4 */
+#define	R367_OFDM_RCFBERCPT4		0xF218
+#define	F367_OFDM_FBERRCMETER_CPT_MMMMSB		0xF21800FF
+
+/* RCFBERCPT3 */
+#define	R367_OFDM_RCFBERCPT3		0xF219
+#define	F367_OFDM_FBERRCMETER_CPT_MMMSB		0xF21900FF
+
+/* RCFBERCPT2 */
+#define	R367_OFDM_RCFBERCPT2		0xF21A
+#define	F367_OFDM_FBERRCMETER_CPT_MMSB		0xF21A00FF
+
+/* RCFBERCPT1 */
+#define	R367_OFDM_RCFBERCPT1		0xF21B
+#define	F367_OFDM_FBERRCMETER_CPT_MSB		0xF21B00FF
+
+/* RCFBERCPT0 */
+#define	R367_OFDM_RCFBERCPT0		0xF21C
+#define	F367_OFDM_FBERRCMETER_CPT_LSB		0xF21C00FF
+
+/* RCFBERERR2 */
+#define	R367_OFDM_RCFBERERR2		0xF21D
+#define	F367_OFDM_FBERRCMETER_ERR_HI		0xF21D00FF
+
+/* RCFBERERR1 */
+#define	R367_OFDM_RCFBERERR1		0xF21E
+#define	F367_OFDM_FBERRCMETER_ERR		0xF21E00FF
+
+/* RCFBERERR0 */
+#define	R367_OFDM_RCFBERERR0		0xF21F
+#define	F367_OFDM_FBERRCMETER_ERR_LO		0xF21F00FF
+
+/* RCFSTATESM */
+#define	R367_OFDM_RCFSTATESM		0xF220
+#define	F367_OFDM_RCRSTATE_F		0xF2200080
+#define	F367_OFDM_RCRSTATE_E		0xF2200040
+#define	F367_OFDM_RCRSTATE_D		0xF2200020
+#define	F367_OFDM_RCRSTATE_C		0xF2200010
+#define	F367_OFDM_RCRSTATE_B		0xF2200008
+#define	F367_OFDM_RCRSTATE_A		0xF2200004
+#define	F367_OFDM_RCRSTATE_9		0xF2200002
+#define	F367_OFDM_RCRSTATE_8		0xF2200001
+
+/* RCFSTATESL */
+#define	R367_OFDM_RCFSTATESL		0xF221
+#define	F367_OFDM_RCRSTATE_7		0xF2210080
+#define	F367_OFDM_RCRSTATE_6		0xF2210040
+#define	F367_OFDM_RCRSTATE_5		0xF2210020
+#define	F367_OFDM_RCRSTATE_4		0xF2210010
+#define	F367_OFDM_RCRSTATE_3		0xF2210008
+#define	F367_OFDM_RCRSTATE_2		0xF2210004
+#define	F367_OFDM_RCRSTATE_1		0xF2210002
+#define	F367_OFDM_RCRSTATE_0		0xF2210001
+
+/* RCFSPYBER */
+#define	R367_OFDM_RCFSPYBER		0xF222
+#define	F367_OFDM_RCFSPYBER_7		0xF2220080
+#define	F367_OFDM_SPYRCOBS_XORREAD		0xF2220040
+#define	F367_OFDM_FSPYRCBER_OBSMODE		0xF2220020
+#define	F367_OFDM_FSPYRCBER_SYNCBYT		0xF2220010
+#define	F367_OFDM_FSPYRCBER_UNSYNC		0xF2220008
+#define	F367_OFDM_FSPYRCBER_CTIME		0xF2220007
+
+/* RCFSPYDISTM */
+#define	R367_OFDM_RCFSPYDISTM		0xF223
+#define	F367_OFDM_RCPKTTIME_DISTANCE_HI		0xF22300FF
+
+/* RCFSPYDISTL */
+#define	R367_OFDM_RCFSPYDISTL		0xF224
+#define	F367_OFDM_RCPKTTIME_DISTANCE_LO		0xF22400FF
+
+/* RCFSPYOBS7 */
+#define	R367_OFDM_RCFSPYOBS7		0xF228
+#define	F367_OFDM_RCSPYOBS_SPYFAIL		0xF2280080
+#define	F367_OFDM_RCSPYOBS_SPYFAIL1		0xF2280040
+#define	F367_OFDM_RCSPYOBS_ERROR		0xF2280020
+#define	F367_OFDM_RCSPYOBS_STROUT		0xF2280010
+#define	F367_OFDM_RCSPYOBS_RESULTSTATE1		0xF228000F
+
+/* RCFSPYOBS6 */
+#define	R367_OFDM_RCFSPYOBS6		0xF229
+#define	F367_OFDM_RCSPYOBS_RESULTSTATE0		0xF22900F0
+#define	F367_OFDM_RCSPYOBS_RESULTSTATEM1		0xF229000F
+
+/* RCFSPYOBS5 */
+#define	R367_OFDM_RCFSPYOBS5		0xF22A
+#define	F367_OFDM_RCSPYOBS_BYTEOFPACKET1		0xF22A00FF
+
+/* RCFSPYOBS4 */
+#define	R367_OFDM_RCFSPYOBS4		0xF22B
+#define	F367_OFDM_RCSPYOBS_BYTEVALUE1		0xF22B00FF
+
+/* RCFSPYOBS3 */
+#define	R367_OFDM_RCFSPYOBS3		0xF22C
+#define	F367_OFDM_RCSPYOBS_DATA1		0xF22C00FF
+
+/* RCFSPYOBS2 */
+#define	R367_OFDM_RCFSPYOBS2		0xF22D
+#define	F367_OFDM_RCSPYOBS_DATA0		0xF22D00FF
+
+/* RCFSPYOBS1 */
+#define	R367_OFDM_RCFSPYOBS1		0xF22E
+#define	F367_OFDM_RCSPYOBS_DATAM1		0xF22E00FF
+
+/* RCFSPYOBS0 */
+#define	R367_OFDM_RCFSPYOBS0		0xF22F
+#define	F367_OFDM_RCSPYOBS_DATAM2		0xF22F00FF
+
+/* TSGENERAL */
+#define	R367_TSGENERAL		0xF230
+#define	F367_TSGENERAL_7		0xF2300080
+#define	F367_TSGENERAL_6		0xF2300040
+#define	F367_TSFIFO_BCLK1ALL		0xF2300020
+#define	F367_TSGENERAL_4		0xF2300010
+#define	F367_MUXSTREAM_OUTMODE		0xF2300008
+#define	F367_TSFIFO_PERMPARAL		0xF2300006
+#define	F367_RST_REEDSOLO		0xF2300001
+
+/* RC1SPEED */
+#define	R367_RC1SPEED		0xF231
+#define	F367_TSRCFIFO1_OUTSPEED		0xF23100FF
+
+/* TSGSTATUS */
+#define	R367_TSGSTATUS		0xF232
+#define	F367_TSGSTATUS_7		0xF2320080
+#define	F367_TSGSTATUS_6		0xF2320040
+#define	F367_RSMEM_FULL		0xF2320020
+#define	F367_RS_MULTCALC		0xF2320010
+#define	F367_RSIN_OVERTIME		0xF2320008
+#define	F367_TSFIFO3_DEMODSEL		0xF2320004
+#define	F367_TSFIFO2_DEMODSEL		0xF2320002
+#define	F367_TSFIFO1_DEMODSEL		0xF2320001
+
+
+/* FECM */
+#define	R367_OFDM_FECM		0xF233
+#define	F367_OFDM_DSS_DVB		0xF2330080
+#define	F367_OFDM_DEMOD_BYPASS		0xF2330040
+#define	F367_OFDM_CMP_SLOWMODE		0xF2330020
+#define	F367_OFDM_DSS_SRCH		0xF2330010
+#define	F367_OFDM_FECM_3		0xF2330008
+#define	F367_OFDM_DIFF_MODEVIT		0xF2330004
+#define	F367_OFDM_SYNCVIT		0xF2330002
+#define	F367_OFDM_I2CSYM		0xF2330001
+
+/* VTH12 */
+#define	R367_OFDM_VTH12		0xF234
+#define	F367_OFDM_VTH_12		0xF23400FF
+
+/* VTH23 */
+#define	R367_OFDM_VTH23		0xF235
+#define	F367_OFDM_VTH_23		0xF23500FF
+
+/* VTH34 */
+#define	R367_OFDM_VTH34		0xF236
+#define	F367_OFDM_VTH_34		0xF23600FF
+
+/* VTH56 */
+#define	R367_OFDM_VTH56		0xF237
+#define	F367_OFDM_VTH_56		0xF23700FF
+
+/* VTH67 */
+#define	R367_OFDM_VTH67		0xF238
+#define	F367_OFDM_VTH_67		0xF23800FF
+
+/* VTH78 */
+#define	R367_OFDM_VTH78		0xF239
+#define	F367_OFDM_VTH_78		0xF23900FF
+
+/* VITCURPUN */
+#define	R367_OFDM_VITCURPUN		0xF23A
+#define	F367_OFDM_VIT_MAPPING		0xF23A00E0
+#define	F367_OFDM_VIT_CURPUN		0xF23A001F
+
+/* VERROR */
+#define	R367_OFDM_VERROR		0xF23B
+#define	F367_OFDM_REGERR_VIT		0xF23B00FF
+
+/* PRVIT */
+#define	R367_OFDM_PRVIT		0xF23C
+#define	F367_OFDM_PRVIT_7		0xF23C0080
+#define	F367_OFDM_DIS_VTHLOCK		0xF23C0040
+#define	F367_OFDM_E7_8VIT		0xF23C0020
+#define	F367_OFDM_E6_7VIT		0xF23C0010
+#define	F367_OFDM_E5_6VIT		0xF23C0008
+#define	F367_OFDM_E3_4VIT		0xF23C0004
+#define	F367_OFDM_E2_3VIT		0xF23C0002
+#define	F367_OFDM_E1_2VIT		0xF23C0001
+
+/* VAVSRVIT */
+#define	R367_OFDM_VAVSRVIT		0xF23D
+#define	F367_OFDM_AMVIT		0xF23D0080
+#define	F367_OFDM_FROZENVIT		0xF23D0040
+#define	F367_OFDM_SNVIT		0xF23D0030
+#define	F367_OFDM_TOVVIT		0xF23D000C
+#define	F367_OFDM_HYPVIT		0xF23D0003
+
+/* VSTATUSVIT */
+#define	R367_OFDM_VSTATUSVIT		0xF23E
+#define	F367_OFDM_VITERBI_ON		0xF23E0080
+#define	F367_OFDM_END_LOOPVIT		0xF23E0040
+#define	F367_OFDM_VITERBI_DEPRF		0xF23E0020
+#define	F367_OFDM_PRFVIT		0xF23E0010
+#define	F367_OFDM_LOCKEDVIT		0xF23E0008
+#define	F367_OFDM_VITERBI_DELOCK		0xF23E0004
+#define	F367_OFDM_VIT_DEMODSEL		0xF23E0002
+#define	F367_OFDM_VITERBI_COMPOUT		0xF23E0001
+
+/* VTHINUSE */
+#define	R367_OFDM_VTHINUSE		0xF23F
+#define	F367_OFDM_VIT_INUSE		0xF23F00FF
+
+/* KDIV12 */
+#define	R367_OFDM_KDIV12		0xF240
+#define	F367_OFDM_KDIV12_MANUAL		0xF2400080
+#define	F367_OFDM_K_DIVIDER_12		0xF240007F
+
+/* KDIV23 */
+#define	R367_OFDM_KDIV23		0xF241
+#define	F367_OFDM_KDIV23_MANUAL		0xF2410080
+#define	F367_OFDM_K_DIVIDER_23		0xF241007F
+
+/* KDIV34 */
+#define	R367_OFDM_KDIV34		0xF242
+#define	F367_OFDM_KDIV34_MANUAL		0xF2420080
+#define	F367_OFDM_K_DIVIDER_34		0xF242007F
+
+/* KDIV56 */
+#define	R367_OFDM_KDIV56		0xF243
+#define	F367_OFDM_KDIV56_MANUAL		0xF2430080
+#define	F367_OFDM_K_DIVIDER_56		0xF243007F
+
+/* KDIV67 */
+#define	R367_OFDM_KDIV67		0xF244
+#define	F367_OFDM_KDIV67_MANUAL		0xF2440080
+#define	F367_OFDM_K_DIVIDER_67		0xF244007F
+
+/* KDIV78 */
+#define	R367_OFDM_KDIV78		0xF245
+#define	F367_OFDM_KDIV78_MANUAL		0xF2450080
+#define	F367_OFDM_K_DIVIDER_78		0xF245007F
+
+/* SIGPOWER */
+#define	R367_OFDM_SIGPOWER		0xF246
+#define	F367_OFDM_SIGPOWER_MANUAL		0xF2460080
+#define	F367_OFDM_SIG_POWER		0xF246007F
+
+/* DEMAPVIT */
+#define	R367_OFDM_DEMAPVIT		0xF247
+#define	F367_OFDM_DEMAPVIT_7		0xF2470080
+#define	F367_OFDM_K_DIVIDER_VIT		0xF247007F
+
+/* VITSCALE */
+#define	R367_OFDM_VITSCALE		0xF248
+#define	F367_OFDM_NVTH_NOSRANGE		0xF2480080
+#define	F367_OFDM_VERROR_MAXMODE		0xF2480040
+#define	F367_OFDM_KDIV_MODE		0xF2480030
+#define	F367_OFDM_NSLOWSN_LOCKED		0xF2480008
+#define	F367_OFDM_DELOCK_PRFLOSS		0xF2480004
+#define	F367_OFDM_DIS_RSFLOCK		0xF2480002
+#define	F367_OFDM_VITSCALE_0		0xF2480001
+
+/* FFEC1PRG */
+#define	R367_OFDM_FFEC1PRG		0xF249
+#define	F367_OFDM_FDSS_DVB		0xF2490080
+#define	F367_OFDM_FDSS_SRCH		0xF2490040
+#define	F367_OFDM_FFECPROG_5		0xF2490020
+#define	F367_OFDM_FFECPROG_4		0xF2490010
+#define	F367_OFDM_FFECPROG_3		0xF2490008
+#define	F367_OFDM_FFECPROG_2		0xF2490004
+#define	F367_OFDM_FTS1_DISABLE		0xF2490002
+#define	F367_OFDM_FTS2_DISABLE		0xF2490001
+
+/* FVITCURPUN */
+#define	R367_OFDM_FVITCURPUN		0xF24A
+#define	F367_OFDM_FVIT_MAPPING		0xF24A00E0
+#define	F367_OFDM_FVIT_CURPUN		0xF24A001F
+
+/* FVERROR */
+#define	R367_OFDM_FVERROR		0xF24B
+#define	F367_OFDM_FREGERR_VIT		0xF24B00FF
+
+/* FVSTATUSVIT */
+#define	R367_OFDM_FVSTATUSVIT		0xF24C
+#define	F367_OFDM_FVITERBI_ON		0xF24C0080
+#define	F367_OFDM_F1END_LOOPVIT		0xF24C0040
+#define	F367_OFDM_FVITERBI_DEPRF		0xF24C0020
+#define	F367_OFDM_FPRFVIT		0xF24C0010
+#define	F367_OFDM_FLOCKEDVIT		0xF24C0008
+#define	F367_OFDM_FVITERBI_DELOCK		0xF24C0004
+#define	F367_OFDM_FVIT_DEMODSEL		0xF24C0002
+#define	F367_OFDM_FVITERBI_COMPOUT		0xF24C0001
+
+/* DEBUG_LT1 */
+#define	R367_OFDM_DEBUG_LT1		0xF24D
+#define	F367_OFDM_DBG_LT1		0xF24D00FF
+
+/* DEBUG_LT2 */
+#define	R367_OFDM_DEBUG_LT2		0xF24E
+#define	F367_OFDM_DBG_LT2		0xF24E00FF
+
+/* DEBUG_LT3 */
+#define	R367_OFDM_DEBUG_LT3		0xF24F
+#define	F367_OFDM_DBG_LT3		0xF24F00FF
+
+	/*	TSTSFMET */
+#define	R367_OFDM_TSTSFMET			0xF250
+#define F367_OFDM_TSTSFEC_METRIQUES	0xF25000FF
+
+	/*	SELOUT */
+#define	R367_OFDM_SELOUT				0xF252
+#define	F367_OFDM_EN_SYNC			0xF2520080
+#define	F367_OFDM_EN_TBUSDEMAP       0xF2520040
+#define	F367_OFDM_SELOUT_5			0xF2520020
+#define	F367_OFDM_SELOUT_4			0xF2520010
+#define	F367_OFDM_TSTSYNCHRO_MODE    0xF2520002
+
+	/*	TSYNC */
+#define R367_OFDM_TSYNC				0xF253
+#define F367_OFDM_CURPUN_INCMODE		0xF2530080
+#define F367_OFDM_CERR_TSTMODE		0xF2530040
+#define F367_OFDM_SHIFTSOF_MODE		0xF2530030
+#define F367_OFDM_SLOWPHA_MODE		0xF2530008
+#define F367_OFDM_PXX_BYPALL			0xF2530004
+#define F367_OFDM_FROTA45_FIRST		0xF2530002
+#define F367_OFDM_TST_BCHERROR		0xF2530001
+
+	/*	TSTERR */
+#define R367_OFDM_TSTERR				0xF254
+#define F367_OFDM_TST_LONGPKT		0xF2540080
+#define F367_OFDM_TST_ISSYION		0xF2540040
+#define F367_OFDM_TST_NPDON			0xF2540020
+#define F367_OFDM_TSTERR_4			0xF2540010
+#define F367_OFDM_TRACEBACK_MODE		0xF2540008
+#define F367_OFDM_TST_RSPARITY		0xF2540004
+#define F367_OFDM_METRIQUE_MODE		0xF2540003
+
+	/*	TSFSYNC */
+#define R367_OFDM_TSFSYNC			0xF255
+#define F367_OFDM_EN_SFECSYNC		0xF2550080
+#define F367_OFDM_EN_SFECDEMAP		0xF2550040
+#define F367_OFDM_SFCERR_TSTMODE		0xF2550020
+#define F367_OFDM_SFECPXX_BYPALL		0xF2550010
+#define F367_OFDM_SFECTSTSYNCHRO_MODE 0xF255000F
+
+	/*	TSTSFERR */
+#define R367_OFDM_TSTSFERR			0xF256
+#define F367_OFDM_TSTSTERR_7			0xF2560080
+#define F367_OFDM_TSTSTERR_6			0xF2560040
+#define F367_OFDM_TSTSTERR_5 		0xF2560020
+#define F367_OFDM_TSTSTERR_4			0xF2560010
+#define F367_OFDM_SFECTRACEBACK_MODE	0xF2560008
+#define F367_OFDM_SFEC_NCONVPROG		0xF2560004
+#define F367_OFDM_SFECMETRIQUE_MODE	0xF2560003
+
+	/*	TSTTSSF1 */
+#define R367_OFDM_TSTTSSF1			0xF258
+#define F367_OFDM_TSTERSSF			0xF2580080
+#define F367_OFDM_TSTTSSFEN			0xF2580040
+#define F367_OFDM_SFEC_OUTMODE		0xF2580030
+#define F367_OFDM_XLSF_NOFTHRESHOLD  0xF2580008
+#define F367_OFDM_TSTTSSF_STACKSEL	0xF2580007
+
+	/*	TSTTSSF2 */
+#define R367_OFDM_TSTTSSF2			0xF259
+#define F367_OFDM_DILSF_DBBHEADER	0xF2590080
+#define F367_OFDM_TSTTSSF_DISBUG		0xF2590040
+#define F367_OFDM_TSTTSSF_NOBADSTART	0xF2590020
+#define F367_OFDM_TSTTSSF_SELECT 	0xF259001F
+
+	/*	TSTTSSF3 */
+#define R367_OFDM_TSTTSSF3			0xF25A
+#define F367_OFDM_TSTTSSF3_7			0xF25A0080
+#define F367_OFDM_TSTTSSF3_6			0xF25A0040
+#define F367_OFDM_TSTTSSF3_5			0xF25A0020
+#define F367_OFDM_TSTTSSF3_4			0xF25A0010
+#define F367_OFDM_TSTTSSF3_3			0xF25A0008
+#define F367_OFDM_TSTTSSF3_2			0xF25A0004
+#define F367_OFDM_TSTTSSF3_1			0xF25A0002
+#define F367_OFDM_DISSF_CLKENABLE    0xF25A0001
+
+	/*	TSTTS1 */
+#define R367_OFDM_TSTTS1				0xF25C
+#define F367_OFDM_TSTERS				0xF25C0080
+#define F367_OFDM_TSFIFO_DSSSYNCB	0xF25C0040
+#define F367_OFDM_TSTTS_FSPYBEFRS	0xF25C0020
+#define F367_OFDM_NFORCE_SYNCBYTE	0xF25C0010
+#define F367_OFDM_XL_NOFTHRESHOLD	0xF25C0008
+#define F367_OFDM_TSTTS_FRFORCEPKT	0xF25C0004
+#define F367_OFDM_DESCR_NOTAUTO		0xF25C0002
+#define F367_OFDM_TSTTSEN			0xF25C0001
+
+	/*	TSTTS2 */
+#define R367_OFDM_TSTTS2				0xF25D
+#define F367_OFDM_DIL_DBBHEADER		0xF25D0080
+#define F367_OFDM_TSTTS_NOBADXXX		0xF25D0040
+#define F367_OFDM_TSFIFO_DELSPEEDUP	0xF25D0020
+#define F367_OFDM_TSTTS_SELECT		0xF25D001F
+
+	/*	TSTTS3 */
+#define R367_OFDM_TSTTS3				0xF25E
+#define F367_OFDM_TSTTS_NOPKTGAIN	0xF25E0080
+#define F367_OFDM_TSTTS_NOPKTENE		0xF25E0040
+#define F367_OFDM_TSTTS_ISOLATION	0xF25E0020
+#define F367_OFDM_TSTTS_DISBUG		0xF25E0010
+#define F367_OFDM_TSTTS_NOBADSTART	0xF25E0008
+#define F367_OFDM_TSTTS_STACKSEL		0xF25E0007
+
+	/*	TSTTS4 */
+#define R367_OFDM_TSTTS4				0xF25F
+#define F367_OFDM_TSTTS4_7			0xF25F0080
+#define F367_OFDM_TSTTS4_6			0xF25F0040
+#define F367_OFDM_TSTTS4_5			0xF25F0020
+#define F367_OFDM_TSTTS_DISDSTATE	0xF25F0010
+#define F367_OFDM_TSTTS_FASTNOSYNC	0xF25F0008
+#define F367_OFDM_EXT_FECSPYIN		0xF25F0004
+#define F367_OFDM_TSTTS_NODPZERO		0xF25F0002
+#define F367_OFDM_TSTTS_NODIV3		0xF25F0001
+
+	/*	TSTTSRC */
+#define R367_OFDM_TSTTSRC				0xF26C
+#define F367_OFDM_TSTTSRC_7				0xF26C0080
+#define F367_OFDM_TSRCFIFO_DSSSYNCB		0xF26C0040
+#define F367_OFDM_TSRCFIFO_DPUNACTIVE	0xF26C0020
+#define F367_OFDM_TSRCFIFO_DELSPEEDUP	0xF26C0010
+#define F367_OFDM_TSTTSRC_NODIV3			0xF26C0008
+#define F367_OFDM_TSTTSRC_FRFORCEPKT		0xF26C0004
+#define F367_OFDM_SAT25_SDDORIGINE		0xF26C0002
+#define F367_OFDM_TSTTSRC_INACTIVE		0xF26C0001
+
+	/*	TSTTSRS */
+#define R367_OFDM_TSTTSRS				0xF26D
+#define F367_OFDM_TSTTSRS_7				0xF26D0080
+#define F367_OFDM_TSTTSRS_6				0xF26D0040
+#define F367_OFDM_TSTTSRS_5				0xF26D0020
+#define F367_OFDM_TSTTSRS_4				0xF26D0010
+#define F367_OFDM_TSTTSRS_3				0xF26D0008
+#define F367_OFDM_TSTTSRS_2				0xF26D0004
+#define F367_OFDM_TSTRS_DISRS2			0xF26D0002
+#define F367_OFDM_TSTRS_DISRS1			0xF26D0001
+
+/* TSSTATEM */
+#define	R367_OFDM_TSSTATEM		0xF270
+#define	F367_OFDM_TSDIL_ON		0xF2700080
+#define	F367_OFDM_TSSKIPRS_ON		0xF2700040
+#define	F367_OFDM_TSRS_ON		0xF2700020
+#define	F367_OFDM_TSDESCRAMB_ON		0xF2700010
+#define	F367_OFDM_TSFRAME_MODE		0xF2700008
+#define	F367_OFDM_TS_DISABLE		0xF2700004
+#define	F367_OFDM_TSACM_MODE		0xF2700002
+#define	F367_OFDM_TSOUT_NOSYNC		0xF2700001
+
+/* TSSTATEL */
+#define	R367_OFDM_TSSTATEL		0xF271
+#define	F367_OFDM_TSNOSYNCBYTE		0xF2710080
+#define	F367_OFDM_TSPARITY_ON		0xF2710040
+#define	F367_OFDM_TSSYNCOUTRS_ON		0xF2710020
+#define	F367_OFDM_TSDVBS2_MODE		0xF2710010
+#define	F367_OFDM_TSISSYI_ON		0xF2710008
+#define	F367_OFDM_TSNPD_ON		0xF2710004
+#define	F367_OFDM_TSCRC8_ON		0xF2710002
+#define	F367_OFDM_TSDSS_PACKET		0xF2710001
+
+/* TSCFGH */
+#define	R367_OFDM_TSCFGH		0xF272
+#define	F367_OFDM_TSFIFO_DVBCI		0xF2720080
+#define	F367_OFDM_TSFIFO_SERIAL		0xF2720040
+#define	F367_OFDM_TSFIFO_TEIUPDATE		0xF2720020
+#define	F367_OFDM_TSFIFO_DUTY50		0xF2720010
+#define	F367_OFDM_TSFIFO_HSGNLOUT		0xF2720008
+#define	F367_OFDM_TSFIFO_ERRMODE		0xF2720006
+#define	F367_OFDM_RST_HWARE		0xF2720001
+
+/* TSCFGM */
+#define	R367_OFDM_TSCFGM		0xF273
+#define	F367_OFDM_TSFIFO_MANSPEED		0xF27300C0
+#define	F367_OFDM_TSFIFO_PERMDATA		0xF2730020
+#define	F367_OFDM_TSFIFO_NONEWSGNL		0xF2730010
+#define	F367_OFDM_TSFIFO_BITSPEED		0xF2730008
+#define	F367_OFDM_NPD_SPECDVBS2		0xF2730004
+#define	F367_OFDM_TSFIFO_STOPCKDIS		0xF2730002
+#define	F367_OFDM_TSFIFO_INVDATA		0xF2730001
+
+/* TSCFGL */
+#define	R367_OFDM_TSCFGL		0xF274
+#define	F367_OFDM_TSFIFO_BCLKDEL1CK		0xF27400C0
+#define	F367_OFDM_BCHERROR_MODE		0xF2740030
+#define	F367_OFDM_TSFIFO_NSGNL2DATA		0xF2740008
+#define	F367_OFDM_TSFIFO_EMBINDVB		0xF2740004
+#define	F367_OFDM_TSFIFO_DPUNACT		0xF2740002
+#define	F367_OFDM_TSFIFO_NPDOFF		0xF2740001
+
+/* TSSYNC */
+#define	R367_OFDM_TSSYNC		0xF275
+#define	F367_OFDM_TSFIFO_PERMUTE		0xF2750080
+#define	F367_OFDM_TSFIFO_FISCR3B		0xF2750060
+#define	F367_OFDM_TSFIFO_SYNCMODE		0xF2750018
+#define	F367_OFDM_TSFIFO_SYNCSEL		0xF2750007
+
+/* TSINSDELH */
+#define	R367_OFDM_TSINSDELH		0xF276
+#define	F367_OFDM_TSDEL_SYNCBYTE		0xF2760080
+#define	F367_OFDM_TSDEL_XXHEADER		0xF2760040
+#define	F367_OFDM_TSDEL_BBHEADER		0xF2760020
+#define	F367_OFDM_TSDEL_DATAFIELD		0xF2760010
+#define	F367_OFDM_TSINSDEL_ISCR		0xF2760008
+#define	F367_OFDM_TSINSDEL_NPD		0xF2760004
+#define	F367_OFDM_TSINSDEL_RSPARITY		0xF2760002
+#define	F367_OFDM_TSINSDEL_CRC8		0xF2760001
+
+/* TSINSDELM */
+#define	R367_OFDM_TSINSDELM		0xF277
+#define	F367_OFDM_TSINS_BBPADDING		0xF2770080
+#define	F367_OFDM_TSINS_BCHFEC		0xF2770040
+#define	F367_OFDM_TSINS_LDPCFEC		0xF2770020
+#define	F367_OFDM_TSINS_EMODCOD		0xF2770010
+#define	F367_OFDM_TSINS_TOKEN		0xF2770008
+#define	F367_OFDM_TSINS_XXXERR		0xF2770004
+#define	F367_OFDM_TSINS_MATYPE		0xF2770002
+#define	F367_OFDM_TSINS_UPL		0xF2770001
+
+/* TSINSDELL */
+#define	R367_OFDM_TSINSDELL		0xF278
+#define	F367_OFDM_TSINS_DFL		0xF2780080
+#define	F367_OFDM_TSINS_SYNCD		0xF2780040
+#define	F367_OFDM_TSINS_BLOCLEN		0xF2780020
+#define	F367_OFDM_TSINS_SIGPCOUNT		0xF2780010
+#define	F367_OFDM_TSINS_FIFO		0xF2780008
+#define	F367_OFDM_TSINS_REALPACK		0xF2780004
+#define	F367_OFDM_TSINS_TSCONFIG		0xF2780002
+#define	F367_OFDM_TSINS_LATENCY		0xF2780001
+
+/* TSDIVN */
+#define	R367_OFDM_TSDIVN		0xF279
+#define	F367_OFDM_TSFIFO_LOWSPEED		0xF2790080
+#define	F367_OFDM_BYTE_OVERSAMPLING		0xF2790070
+#define	F367_OFDM_TSMANUAL_PACKETNBR		0xF279000F
+
+/* TSDIVPM */
+#define	R367_OFDM_TSDIVPM		0xF27A
+#define	F367_OFDM_TSMANUAL_P_HI		0xF27A00FF
+
+/* TSDIVPL */
+#define	R367_OFDM_TSDIVPL		0xF27B
+#define	F367_OFDM_TSMANUAL_P_LO		0xF27B00FF
+
+/* TSDIVQM */
+#define	R367_OFDM_TSDIVQM		0xF27C
+#define	F367_OFDM_TSMANUAL_Q_HI		0xF27C00FF
+
+/* TSDIVQL */
+#define	R367_OFDM_TSDIVQL		0xF27D
+#define	F367_OFDM_TSMANUAL_Q_LO		0xF27D00FF
+
+/* TSDILSTKM */
+#define	R367_OFDM_TSDILSTKM		0xF27E
+#define	F367_OFDM_TSFIFO_DILSTK_HI		0xF27E00FF
+
+/* TSDILSTKL */
+#define	R367_OFDM_TSDILSTKL		0xF27F
+#define	F367_OFDM_TSFIFO_DILSTK_LO		0xF27F00FF
+
+/* TSSPEED */
+#define	R367_OFDM_TSSPEED		0xF280
+#define	F367_OFDM_TSFIFO_OUTSPEED		0xF28000FF
+
+/* TSSTATUS */
+#define	R367_OFDM_TSSTATUS		0xF281
+#define	F367_OFDM_TSFIFO_LINEOK		0xF2810080
+#define	F367_OFDM_TSFIFO_ERROR		0xF2810040
+#define	F367_OFDM_TSFIFO_DATA7		0xF2810020
+#define	F367_OFDM_TSFIFO_NOSYNC		0xF2810010
+#define	F367_OFDM_ISCR_INITIALIZED		0xF2810008
+#define	F367_OFDM_ISCR_UPDATED		0xF2810004
+#define	F367_OFDM_SOFFIFO_UNREGUL		0xF2810002
+#define	F367_OFDM_DIL_READY		0xF2810001
+
+/* TSSTATUS2 */
+#define	R367_OFDM_TSSTATUS2		0xF282
+#define	F367_OFDM_TSFIFO_DEMODSEL		0xF2820080
+#define	F367_OFDM_TSFIFOSPEED_STORE		0xF2820040
+#define	F367_OFDM_DILXX_RESET		0xF2820020
+#define	F367_OFDM_TSSERIAL_IMPOSSIBLE		0xF2820010
+#define	F367_OFDM_TSFIFO_UNDERSPEED		0xF2820008
+#define	F367_OFDM_BITSPEED_EVENT		0xF2820004
+#define	F367_OFDM_UL_SCRAMBDETECT		0xF2820002
+#define	F367_OFDM_ULDTV67_FALSELOCK		0xF2820001
+
+/* TSBITRATEM */
+#define	R367_OFDM_TSBITRATEM		0xF283
+#define	F367_OFDM_TSFIFO_BITRATE_HI		0xF28300FF
+
+/* TSBITRATEL */
+#define	R367_OFDM_TSBITRATEL		0xF284
+#define	F367_OFDM_TSFIFO_BITRATE_LO		0xF28400FF
+
+/* TSPACKLENM */
+#define	R367_OFDM_TSPACKLENM		0xF285
+#define	F367_OFDM_TSFIFO_PACKCPT		0xF28500E0
+#define	F367_OFDM_DIL_RPLEN_HI		0xF285001F
+
+/* TSPACKLENL */
+#define	R367_OFDM_TSPACKLENL		0xF286
+#define	F367_OFDM_DIL_RPLEN_LO		0xF28600FF
+
+/* TSBLOCLENM */
+#define	R367_OFDM_TSBLOCLENM		0xF287
+#define	F367_OFDM_TSFIFO_PFLEN_HI		0xF28700FF
+
+/* TSBLOCLENL */
+#define	R367_OFDM_TSBLOCLENL		0xF288
+#define	F367_OFDM_TSFIFO_PFLEN_LO		0xF28800FF
+
+/* TSDLYH */
+#define	R367_OFDM_TSDLYH		0xF289
+#define	F367_OFDM_SOFFIFO_TSTIMEVALID		0xF2890080
+#define	F367_OFDM_SOFFIFO_SPEEDUP		0xF2890040
+#define	F367_OFDM_SOFFIFO_STOP		0xF2890020
+#define	F367_OFDM_SOFFIFO_REGULATED		0xF2890010
+#define	F367_OFDM_SOFFIFO_REALSBOFF_HI		0xF289000F
+
+/* TSDLYM */
+#define	R367_OFDM_TSDLYM		0xF28A
+#define	F367_OFDM_SOFFIFO_REALSBOFF_MED		0xF28A00FF
+
+/* TSDLYL */
+#define	R367_OFDM_TSDLYL		0xF28B
+#define	F367_OFDM_SOFFIFO_REALSBOFF_LO		0xF28B00FF
+
+/* TSNPDAV */
+#define	R367_OFDM_TSNPDAV		0xF28C
+#define	F367_OFDM_TSNPD_AVERAGE		0xF28C00FF
+
+/* TSBUFSTATH */
+#define	R367_OFDM_TSBUFSTATH		0xF28D
+#define	F367_OFDM_TSISCR_3BYTES		0xF28D0080
+#define	F367_OFDM_TSISCR_NEWDATA		0xF28D0040
+#define	F367_OFDM_TSISCR_BUFSTAT_HI		0xF28D003F
+
+/* TSBUFSTATM */
+#define	R367_OFDM_TSBUFSTATM		0xF28E
+#define	F367_OFDM_TSISCR_BUFSTAT_MED		0xF28E00FF
+
+/* TSBUFSTATL */
+#define	R367_OFDM_TSBUFSTATL		0xF28F
+#define	F367_OFDM_TSISCR_BUFSTAT_LO		0xF28F00FF
+
+/* TSDEBUGM */
+#define	R367_OFDM_TSDEBUGM		0xF290
+#define	F367_OFDM_TSFIFO_ILLPACKET		0xF2900080
+#define	F367_OFDM_DIL_NOSYNC		0xF2900040
+#define	F367_OFDM_DIL_ISCR		0xF2900020
+#define	F367_OFDM_DILOUT_BSYNCB		0xF2900010
+#define	F367_OFDM_TSFIFO_EMPTYPKT		0xF2900008
+#define	F367_OFDM_TSFIFO_EMPTYRD		0xF2900004
+#define	F367_OFDM_SOFFIFO_STOPM		0xF2900002
+#define	F367_OFDM_SOFFIFO_SPEEDUPM		0xF2900001
+
+/* TSDEBUGL */
+#define	R367_OFDM_TSDEBUGL		0xF291
+#define	F367_OFDM_TSFIFO_PACKLENFAIL		0xF2910080
+#define	F367_OFDM_TSFIFO_SYNCBFAIL		0xF2910040
+#define	F367_OFDM_TSFIFO_VITLIBRE		0xF2910020
+#define	F367_OFDM_TSFIFO_BOOSTSPEEDM		0xF2910010
+#define	F367_OFDM_TSFIFO_UNDERSPEEDM		0xF2910008
+#define	F367_OFDM_TSFIFO_ERROR_EVNT		0xF2910004
+#define	F367_OFDM_TSFIFO_FULL		0xF2910002
+#define	F367_OFDM_TSFIFO_OVERFLOWM		0xF2910001
+
+/* TSDLYSETH */
+#define	R367_OFDM_TSDLYSETH		0xF292
+#define	F367_OFDM_SOFFIFO_OFFSET		0xF29200E0
+#define	F367_OFDM_SOFFIFO_SYMBOFFSET_HI		0xF292001F
+
+/* TSDLYSETM */
+#define	R367_OFDM_TSDLYSETM		0xF293
+#define	F367_OFDM_SOFFIFO_SYMBOFFSET_MED		0xF29300FF
+
+/* TSDLYSETL */
+#define	R367_OFDM_TSDLYSETL		0xF294
+#define	F367_OFDM_SOFFIFO_SYMBOFFSET_LO		0xF29400FF
+
+/* TSOBSCFG */
+#define	R367_OFDM_TSOBSCFG		0xF295
+#define	F367_OFDM_TSFIFO_OBSCFG		0xF29500FF
+
+/* TSOBSM */
+#define	R367_OFDM_TSOBSM		0xF296
+#define	F367_OFDM_TSFIFO_OBSDATA_HI		0xF29600FF
+
+/* TSOBSL */
+#define	R367_OFDM_TSOBSL		0xF297
+#define	F367_OFDM_TSFIFO_OBSDATA_LO		0xF29700FF
+
+/* ERRCTRL1 */
+#define	R367_OFDM_ERRCTRL1		0xF298
+#define	F367_OFDM_ERR_SRC1		0xF29800F0
+#define	F367_OFDM_ERRCTRL1_3		0xF2980008
+#define	F367_OFDM_NUM_EVT1		0xF2980007
+
+/* ERRCNT1H */
+#define	R367_OFDM_ERRCNT1H		0xF299
+#define	F367_OFDM_ERRCNT1_OLDVALUE		0xF2990080
+#define	F367_OFDM_ERR_CNT1		0xF299007F
+
+/* ERRCNT1M */
+#define	R367_OFDM_ERRCNT1M		0xF29A
+#define	F367_OFDM_ERR_CNT1_HI		0xF29A00FF
+
+/* ERRCNT1L */
+#define	R367_OFDM_ERRCNT1L		0xF29B
+#define	F367_OFDM_ERR_CNT1_LO		0xF29B00FF
+
+/* ERRCTRL2 */
+#define	R367_OFDM_ERRCTRL2		0xF29C
+#define	F367_OFDM_ERR_SRC2		0xF29C00F0
+#define	F367_OFDM_ERRCTRL2_3		0xF29C0008
+#define	F367_OFDM_NUM_EVT2		0xF29C0007
+
+/* ERRCNT2H */
+#define	R367_OFDM_ERRCNT2H		0xF29D
+#define	F367_OFDM_ERRCNT2_OLDVALUE		0xF29D0080
+#define	F367_OFDM_ERR_CNT2_HI		0xF29D007F
+
+/* ERRCNT2M */
+#define	R367_OFDM_ERRCNT2M		0xF29E
+#define	F367_OFDM_ERR_CNT2_MED		0xF29E00FF
+
+/* ERRCNT2L */
+#define	R367_OFDM_ERRCNT2L		0xF29F
+#define	F367_OFDM_ERR_CNT2_LO		0xF29F00FF
+
+/* FECSPY */
+#define	R367_OFDM_FECSPY		0xF2A0
+#define	F367_OFDM_SPY_ENABLE		0xF2A00080
+#define	F367_OFDM_NO_SYNCBYTE		0xF2A00040
+#define	F367_OFDM_SERIAL_MODE		0xF2A00020
+#define	F367_OFDM_UNUSUAL_PACKET		0xF2A00010
+#define	F367_OFDM_BERMETER_DATAMODE		0xF2A0000C
+#define	F367_OFDM_BERMETER_LMODE		0xF2A00002
+#define	F367_OFDM_BERMETER_RESET		0xF2A00001
+
+/* FSPYCFG */
+#define	R367_OFDM_FSPYCFG		0xF2A1
+#define	F367_OFDM_FECSPY_INPUT		0xF2A100C0
+#define	F367_OFDM_RST_ON_ERROR		0xF2A10020
+#define	F367_OFDM_ONE_SHOT		0xF2A10010
+#define	F367_OFDM_I2C_MOD		0xF2A1000C
+#define	F367_OFDM_SPY_HYSTERESIS		0xF2A10003
+
+/* FSPYDATA */
+#define	R367_OFDM_FSPYDATA		0xF2A2
+#define	F367_OFDM_SPY_STUFFING		0xF2A20080
+#define	F367_OFDM_NOERROR_PKTJITTER		0xF2A20040
+#define	F367_OFDM_SPY_CNULLPKT		0xF2A20020
+#define	F367_OFDM_SPY_OUTDATA_MODE		0xF2A2001F
+
+/* FSPYOUT */
+#define	R367_OFDM_FSPYOUT		0xF2A3
+#define	F367_OFDM_FSPY_DIRECT		0xF2A30080
+#define	F367_OFDM_FSPYOUT_6		0xF2A30040
+#define	F367_OFDM_SPY_OUTDATA_BUS		0xF2A30038
+#define	F367_OFDM_STUFF_MODE		0xF2A30007
+
+/* FSTATUS */
+#define	R367_OFDM_FSTATUS		0xF2A4
+#define	F367_OFDM_SPY_ENDSIM		0xF2A40080
+#define	F367_OFDM_VALID_SIM		0xF2A40040
+#define	F367_OFDM_FOUND_SIGNAL		0xF2A40020
+#define	F367_OFDM_DSS_SYNCBYTE		0xF2A40010
+#define	F367_OFDM_RESULT_STATE		0xF2A4000F
+
+/* FGOODPACK */
+#define	R367_OFDM_FGOODPACK		0xF2A5
+#define	F367_OFDM_FGOOD_PACKET		0xF2A500FF
+
+/* FPACKCNT */
+#define	R367_OFDM_FPACKCNT		0xF2A6
+#define	F367_OFDM_FPACKET_COUNTER		0xF2A600FF
+
+/* FSPYMISC */
+#define	R367_OFDM_FSPYMISC		0xF2A7
+#define	F367_OFDM_FLABEL_COUNTER		0xF2A700FF
+
+/* FBERCPT4 */
+#define	R367_OFDM_FBERCPT4		0xF2A8
+#define	F367_OFDM_FBERMETER_CPT5		0xF2A800FF
+
+/* FBERCPT3 */
+#define	R367_OFDM_FBERCPT3		0xF2A9
+#define	F367_OFDM_FBERMETER_CPT4		0xF2A900FF
+
+/* FBERCPT2 */
+#define	R367_OFDM_FBERCPT2		0xF2AA
+#define	F367_OFDM_FBERMETER_CPT3		0xF2AA00FF
+
+/* FBERCPT1 */
+#define	R367_OFDM_FBERCPT1		0xF2AB
+#define	F367_OFDM_FBERMETER_CPT2		0xF2AB00FF
+
+/* FBERCPT0 */
+#define	R367_OFDM_FBERCPT0		0xF2AC
+#define	F367_OFDM_FBERMETER_CPT1		0xF2AC00FF
+
+/* FBERERR2 */
+#define	R367_OFDM_FBERERR2		0xF2AD
+#define	F367_OFDM_FBERMETER_ERR_HI		0xF2AD00FF
+
+/* FBERERR1 */
+#define	R367_OFDM_FBERERR1		0xF2AE
+#define	F367_OFDM_FBERMETER_ERR_MED		0xF2AE00FF
+
+/* FBERERR0 */
+#define	R367_OFDM_FBERERR0		0xF2AF
+#define	F367_OFDM_FBERMETER_ERR_LO		0xF2AF00FF
+
+/* FSTATESM */
+#define	R367_OFDM_FSTATESM		0xF2B0
+#define	F367_OFDM_RSTATE_F		0xF2B00080
+#define	F367_OFDM_RSTATE_E		0xF2B00040
+#define	F367_OFDM_RSTATE_D		0xF2B00020
+#define	F367_OFDM_RSTATE_C		0xF2B00010
+#define	F367_OFDM_RSTATE_B		0xF2B00008
+#define	F367_OFDM_RSTATE_A		0xF2B00004
+#define	F367_OFDM_RSTATE_9		0xF2B00002
+#define	F367_OFDM_RSTATE_8		0xF2B00001
+
+/* FSTATESL */
+#define	R367_OFDM_FSTATESL		0xF2B1
+#define	F367_OFDM_RSTATE_7		0xF2B10080
+#define	F367_OFDM_RSTATE_6		0xF2B10040
+#define	F367_OFDM_RSTATE_5		0xF2B10020
+#define	F367_OFDM_RSTATE_4		0xF2B10010
+#define	F367_OFDM_RSTATE_3		0xF2B10008
+#define	F367_OFDM_RSTATE_2		0xF2B10004
+#define	F367_OFDM_RSTATE_1		0xF2B10002
+#define	F367_OFDM_RSTATE_0		0xF2B10001
+
+/* FSPYBER */
+#define	R367_OFDM_FSPYBER		0xF2B2
+#define	F367_OFDM_FSPYBER_7		0xF2B20080
+#define	F367_OFDM_FSPYOBS_XORREAD		0xF2B20040
+#define	F367_OFDM_FSPYBER_OBSMODE		0xF2B20020
+#define	F367_OFDM_FSPYBER_SYNCBYTE		0xF2B20010
+#define	F367_OFDM_FSPYBER_UNSYNC		0xF2B20008
+#define	F367_OFDM_FSPYBER_CTIME		0xF2B20007
+
+/* FSPYDISTM */
+#define	R367_OFDM_FSPYDISTM		0xF2B3
+#define	F367_OFDM_PKTTIME_DISTANCE_HI		0xF2B300FF
+
+/* FSPYDISTL */
+#define	R367_OFDM_FSPYDISTL		0xF2B4
+#define	F367_OFDM_PKTTIME_DISTANCE_LO		0xF2B400FF
+
+/* FSPYOBS7 */
+#define	R367_OFDM_FSPYOBS7		0xF2B8
+#define	F367_OFDM_FSPYOBS_SPYFAIL		0xF2B80080
+#define	F367_OFDM_FSPYOBS_SPYFAIL1		0xF2B80040
+#define	F367_OFDM_FSPYOBS_ERROR		0xF2B80020
+#define	F367_OFDM_FSPYOBS_STROUT		0xF2B80010
+#define	F367_OFDM_FSPYOBS_RESULTSTATE1		0xF2B8000F
+
+/* FSPYOBS6 */
+#define	R367_OFDM_FSPYOBS6		0xF2B9
+#define	F367_OFDM_FSPYOBS_RESULTSTATE0		0xF2B900F0
+#define	F367_OFDM_FSPYOBS_RESULTSTATEM1		0xF2B9000F
+
+/* FSPYOBS5 */
+#define	R367_OFDM_FSPYOBS5		0xF2BA
+#define	F367_OFDM_FSPYOBS_BYTEOFPACKET1		0xF2BA00FF
+
+/* FSPYOBS4 */
+#define	R367_OFDM_FSPYOBS4		0xF2BB
+#define	F367_OFDM_FSPYOBS_BYTEVALUE1		0xF2BB00FF
+
+/* FSPYOBS3 */
+#define	R367_OFDM_FSPYOBS3		0xF2BC
+#define	F367_OFDM_FSPYOBS_DATA1		0xF2BC00FF
+
+/* FSPYOBS2 */
+#define	R367_OFDM_FSPYOBS2		0xF2BD
+#define	F367_OFDM_FSPYOBS_DATA0		0xF2BD00FF
+
+/* FSPYOBS1 */
+#define	R367_OFDM_FSPYOBS1		0xF2BE
+#define	F367_OFDM_FSPYOBS_DATAM1		0xF2BE00FF
+
+/* FSPYOBS0 */
+#define	R367_OFDM_FSPYOBS0		0xF2BF
+#define	F367_OFDM_FSPYOBS_DATAM2		0xF2BF00FF
+
+/* SFDEMAP */
+#define	R367_OFDM_SFDEMAP		0xF2C0
+#define	F367_OFDM_SFDEMAP_7		0xF2C00080
+#define	F367_OFDM_SFEC_K_DIVIDER_VIT		0xF2C0007F
+
+/* SFERROR */
+#define	R367_OFDM_SFERROR		0xF2C1
+#define	F367_OFDM_SFEC_REGERR_VIT		0xF2C100FF
+
+/* SFAVSR */
+#define	R367_OFDM_SFAVSR		0xF2C2
+#define	F367_OFDM_SFEC_SUMERRORS		0xF2C20080
+#define	F367_OFDM_SERROR_MAXMODE		0xF2C20040
+#define	F367_OFDM_SN_SFEC		0xF2C20030
+#define	F367_OFDM_KDIV_MODE_SFEC		0xF2C2000C
+#define	F367_OFDM_SFAVSR_1		0xF2C20002
+#define	F367_OFDM_SFAVSR_0		0xF2C20001
+
+/* SFECSTATUS */
+#define	R367_OFDM_SFECSTATUS		0xF2C3
+#define	F367_OFDM_SFEC_ON		0xF2C30080
+#define	F367_OFDM_SFSTATUS_6		0xF2C30040
+#define	F367_OFDM_SFSTATUS_5		0xF2C30020
+#define	F367_OFDM_SFSTATUS_4		0xF2C30010
+#define	F367_OFDM_LOCKEDSFEC		0xF2C30008
+#define	F367_OFDM_SFEC_DELOCK		0xF2C30004
+#define	F367_OFDM_SFEC_DEMODSEL1		0xF2C30002
+#define	F367_OFDM_SFEC_OVFON		0xF2C30001
+
+/* SFKDIV12 */
+#define	R367_OFDM_SFKDIV12		0xF2C4
+#define	F367_OFDM_SFECKDIV12_MAN		0xF2C40080
+#define	F367_OFDM_SFEC_K_DIVIDER_12		0xF2C4007F
+
+/* SFKDIV23 */
+#define	R367_OFDM_SFKDIV23		0xF2C5
+#define	F367_OFDM_SFECKDIV23_MAN		0xF2C50080
+#define	F367_OFDM_SFEC_K_DIVIDER_23		0xF2C5007F
+
+/* SFKDIV34 */
+#define	R367_OFDM_SFKDIV34		0xF2C6
+#define	F367_OFDM_SFECKDIV34_MAN		0xF2C60080
+#define	F367_OFDM_SFEC_K_DIVIDER_34		0xF2C6007F
+
+/* SFKDIV56 */
+#define	R367_OFDM_SFKDIV56		0xF2C7
+#define	F367_OFDM_SFECKDIV56_MAN		0xF2C70080
+#define	F367_OFDM_SFEC_K_DIVIDER_56		0xF2C7007F
+
+/* SFKDIV67 */
+#define	R367_OFDM_SFKDIV67		0xF2C8
+#define	F367_OFDM_SFECKDIV67_MAN		0xF2C80080
+#define	F367_OFDM_SFEC_K_DIVIDER_67		0xF2C8007F
+
+/* SFKDIV78 */
+#define	R367_OFDM_SFKDIV78		0xF2C9
+#define	F367_OFDM_SFECKDIV78_MAN		0xF2C90080
+#define	F367_OFDM_SFEC_K_DIVIDER_78		0xF2C9007F
+
+/* SFDILSTKM */
+#define	R367_OFDM_SFDILSTKM		0xF2CA
+#define	F367_OFDM_SFEC_PACKCPT		0xF2CA00E0
+#define	F367_OFDM_SFEC_DILSTK_HI		0xF2CA001F
+
+/* SFDILSTKL */
+#define	R367_OFDM_SFDILSTKL		0xF2CB
+#define	F367_OFDM_SFEC_DILSTK_LO		0xF2CB00FF
+
+/* SFSTATUS */
+#define	R367_OFDM_SFSTATUS		0xF2CC
+#define	F367_OFDM_SFEC_LINEOK		0xF2CC0080
+#define	F367_OFDM_SFEC_ERROR		0xF2CC0040
+#define	F367_OFDM_SFEC_DATA7		0xF2CC0020
+#define	F367_OFDM_SFEC_OVERFLOW		0xF2CC0010
+#define	F367_OFDM_SFEC_DEMODSEL2		0xF2CC0008
+#define	F367_OFDM_SFEC_NOSYNC		0xF2CC0004
+#define	F367_OFDM_SFEC_UNREGULA		0xF2CC0002
+#define	F367_OFDM_SFEC_READY		0xF2CC0001
+
+/* SFDLYH */
+#define	R367_OFDM_SFDLYH		0xF2CD
+#define	F367_OFDM_SFEC_TSTIMEVALID		0xF2CD0080
+#define	F367_OFDM_SFEC_SPEEDUP		0xF2CD0040
+#define	F367_OFDM_SFEC_STOP		0xF2CD0020
+#define	F367_OFDM_SFEC_REGULATED		0xF2CD0010
+#define	F367_OFDM_SFEC_REALSYMBOFFSET		0xF2CD000F
+
+/* SFDLYM */
+#define	R367_OFDM_SFDLYM		0xF2CE
+#define	F367_OFDM_SFEC_REALSYMBOFFSET_HI		0xF2CE00FF
+
+/* SFDLYL */
+#define	R367_OFDM_SFDLYL		0xF2CF
+#define	F367_OFDM_SFEC_REALSYMBOFFSET_LO		0xF2CF00FF
+
+/* SFDLYSETH */
+#define	R367_OFDM_SFDLYSETH		0xF2D0
+#define	F367_OFDM_SFEC_OFFSET		0xF2D000E0
+#define	F367_OFDM_SFECDLYSETH_4		0xF2D00010
+#define	F367_OFDM_RST_SFEC		0xF2D00008
+#define	F367_OFDM_SFECDLYSETH_2		0xF2D00004
+#define	F367_OFDM_SFEC_DISABLE		0xF2D00002
+#define	F367_OFDM_SFEC_UNREGUL		0xF2D00001
+
+/* SFDLYSETM */
+#define	R367_OFDM_SFDLYSETM		0xF2D1
+#define	F367_OFDM_SFECDLYSETM_7		0xF2D10080
+#define	F367_OFDM_SFEC_SYMBOFFSET_HI		0xF2D1007F
+
+/* SFDLYSETL */
+#define	R367_OFDM_SFDLYSETL		0xF2D2
+#define	F367_OFDM_SFEC_SYMBOFFSET_LO		0xF2D200FF
+
+/* SFOBSCFG */
+#define	R367_OFDM_SFOBSCFG		0xF2D3
+#define	F367_OFDM_SFEC_OBSCFG		0xF2D300FF
+
+/* SFOBSM */
+#define	R367_OFDM_SFOBSM		0xF2D4
+#define	F367_OFDM_SFEC_OBSDATA_HI		0xF2D400FF
+
+/* SFOBSL */
+#define	R367_OFDM_SFOBSL		0xF2D5
+#define	F367_OFDM_SFEC_OBSDATA_LO		0xF2D500FF
+
+/* SFECINFO */
+#define	R367_OFDM_SFECINFO		0xF2D6
+#define	F367_OFDM_SFECINFO_7		0xF2D60080
+#define	F367_OFDM_SFEC_SYNCDLSB		0xF2D60070
+#define	F367_OFDM_SFCE_S1CPHASE		0xF2D6000F
+
+/* SFERRCTRL */
+#define	R367_OFDM_SFERRCTRL		0xF2D8
+#define	F367_OFDM_SFEC_ERR_SOURCE		0xF2D800F0
+#define	F367_OFDM_SFERRCTRL_3		0xF2D80008
+#define	F367_OFDM_SFEC_NUM_EVENT		0xF2D80007
+
+/* SFERRCNTH */
+#define	R367_OFDM_SFERRCNTH		0xF2D9
+#define	F367_OFDM_SFERRC_OLDVALUE		0xF2D90080
+#define	F367_OFDM_SFEC_ERR_CNT		0xF2D9007F
+
+/* SFERRCNTM */
+#define	R367_OFDM_SFERRCNTM		0xF2DA
+#define	F367_OFDM_SFEC_ERR_CNT_HI		0xF2DA00FF
+
+/* SFERRCNTL */
+#define	R367_OFDM_SFERRCNTL		0xF2DB
+#define	F367_OFDM_SFEC_ERR_CNT_LO		0xF2DB00FF
+
+/* SYMBRATEM */
+#define	R367_OFDM_SYMBRATEM		0xF2E0
+#define	F367_OFDM_DEFGEN_SYMBRATE_HI		0xF2E000FF
+
+/* SYMBRATEL */
+#define	R367_OFDM_SYMBRATEL		0xF2E1
+#define	F367_OFDM_DEFGEN_SYMBRATE_LO		0xF2E100FF
+
+/* SYMBSTATUS */
+#define	R367_OFDM_SYMBSTATUS		0xF2E2
+#define	F367_OFDM_SYMBDLINE2_OFF		0xF2E20080
+#define	F367_OFDM_SDDL_REINIT1		0xF2E20040
+#define	F367_OFDM_SDD_REINIT1		0xF2E20020
+#define	F367_OFDM_TOKENID_ERROR		0xF2E20010
+#define	F367_OFDM_SYMBRATE_OVERFLOW		0xF2E20008
+#define	F367_OFDM_SYMBRATE_UNDERFLOW		0xF2E20004
+#define	F367_OFDM_TOKENID_RSTEVENT		0xF2E20002
+#define	F367_OFDM_TOKENID_RESET1		0xF2E20001
+
+/* SYMBCFG */
+#define	R367_OFDM_SYMBCFG		0xF2E3
+#define	F367_OFDM_SYMBCFG_7		0xF2E30080
+#define	F367_OFDM_SYMBCFG_6		0xF2E30040
+#define	F367_OFDM_SYMBCFG_5		0xF2E30020
+#define	F367_OFDM_SYMBCFG_4		0xF2E30010
+#define	F367_OFDM_SYMRATE_FSPEED		0xF2E3000C
+#define	F367_OFDM_SYMRATE_SSPEED		0xF2E30003
+
+/* SYMBFIFOM */
+#define	R367_OFDM_SYMBFIFOM		0xF2E4
+#define	F367_OFDM_SYMBFIFOM_7		0xF2E40080
+#define	F367_OFDM_SYMBFIFOM_6		0xF2E40040
+#define	F367_OFDM_DEFGEN_SYMFIFO_HI		0xF2E4003F
+
+/* SYMBFIFOL */
+#define	R367_OFDM_SYMBFIFOL		0xF2E5
+#define	F367_OFDM_DEFGEN_SYMFIFO_LO		0xF2E500FF
+
+/* SYMBOFFSM */
+#define	R367_OFDM_SYMBOFFSM		0xF2E6
+#define	F367_OFDM_TOKENID_RESET2		0xF2E60080
+#define	F367_OFDM_SDDL_REINIT2		0xF2E60040
+#define	F367_OFDM_SDD_REINIT2		0xF2E60020
+#define	F367_OFDM_SYMBOFFSM_4		0xF2E60010
+#define	F367_OFDM_SYMBOFFSM_3		0xF2E60008
+#define	F367_OFDM_DEFGEN_SYMBOFFSET_HI		0xF2E60007
+
+/* SYMBOFFSL */
+#define	R367_OFDM_SYMBOFFSL		0xF2E7
+#define	F367_OFDM_DEFGEN_SYMBOFFSET_LO		0xF2E700FF
+
+/* DEBUG_LT4 */
+#define	R367_DEBUG_LT4		0xF400
+#define	F367_F_DEBUG_LT4		0xF40000FF
+
+/* DEBUG_LT5 */
+#define	R367_DEBUG_LT5		0xF401
+#define	F367_F_DEBUG_LT5		0xF40100FF
+
+/* DEBUG_LT6 */
+#define	R367_DEBUG_LT6		0xF402
+#define	F367_F_DEBUG_LT6		0xF40200FF
+
+/* DEBUG_LT7 */
+#define	R367_DEBUG_LT7		0xF403
+#define	F367_F_DEBUG_LT7		0xF40300FF
+
+/* DEBUG_LT8 */
+#define	R367_DEBUG_LT8		0xF404
+#define	F367_F_DEBUG_LT8		0xF40400FF
+
+/* DEBUG_LT9 */
+#define	R367_DEBUG_LT9		0xF405
+#define	F367_F_DEBUG_LT9		0xF40500FF
+
+/* CTRL_1 */
+#define	R367_QAM_CTRL_1		0xF402
+#define	F367_QAM_SOFT_RST		0xF4020080
+#define	F367_QAM_EQU_RST		0xF4020008
+#define	F367_QAM_CRL_RST		0xF4020004
+#define	F367_QAM_TRL_RST		0xF4020002
+#define	F367_QAM_AGC_RST		0xF4020001
+
+/* CTRL_2 */
+#define	R367_QAM_CTRL_2		0xF403
+#define	F367_QAM_DEINT_RST		0xF4030008
+#define	F367_QAM_RS_RST		0xF4030004
+
+/* IT_STATUS1 */
+#define	R367_QAM_IT_STATUS1		0xF408
+#define	F367_QAM_SWEEP_OUT		0xF4080080
+#define	F367_QAM_FSM_CRL		0xF4080040
+#define	F367_QAM_CRL_LOCK		0xF4080020
+#define	F367_QAM_MFSM		0xF4080010
+#define	F367_QAM_TRL_LOCK		0xF4080008
+#define	F367_QAM_TRL_AGC_LIMIT		0xF4080004
+#define	F367_QAM_ADJ_AGC_LOCK		0xF4080002
+#define	F367_QAM_AGC_QAM_LOCK		0xF4080001
+
+/* IT_STATUS2 */
+#define	R367_QAM_IT_STATUS2		0xF409
+#define	F367_QAM_TSMF_CNT		0xF4090080
+#define	F367_QAM_TSMF_EOF		0xF4090040
+#define	F367_QAM_TSMF_RDY		0xF4090020
+#define	F367_QAM_FEC_NOCORR		0xF4090010
+#define	F367_QAM_SYNCSTATE		0xF4090008
+#define	F367_QAM_DEINT_LOCK		0xF4090004
+#define	F367_QAM_FADDING_FRZ		0xF4090002
+#define	F367_QAM_TAPMON_ALARM		0xF4090001
+
+/* IT_EN1 */
+#define	R367_QAM_IT_EN1		0xF40A
+#define	F367_QAM_SWEEP_OUTE		0xF40A0080
+#define	F367_QAM_FSM_CRLE		0xF40A0040
+#define	F367_QAM_CRL_LOCKE		0xF40A0020
+#define	F367_QAM_MFSME		0xF40A0010
+#define	F367_QAM_TRL_LOCKE		0xF40A0008
+#define	F367_QAM_TRL_AGC_LIMITE		0xF40A0004
+#define	F367_QAM_ADJ_AGC_LOCKE		0xF40A0002
+#define	F367_QAM_AGC_LOCKE		0xF40A0001
+
+/* IT_EN2 */
+#define	R367_QAM_IT_EN2		0xF40B
+#define	F367_QAM_TSMF_CNTE		0xF40B0080
+#define	F367_QAM_TSMF_EOFE		0xF40B0040
+#define	F367_QAM_TSMF_RDYE		0xF40B0020
+#define	F367_QAM_FEC_NOCORRE		0xF40B0010
+#define	F367_QAM_SYNCSTATEE		0xF40B0008
+#define	F367_QAM_DEINT_LOCKE		0xF40B0004
+#define	F367_QAM_FADDING_FRZE		0xF40B0002
+#define	F367_QAM_TAPMON_ALARME		0xF40B0001
+
+/* CTRL_STATUS */
+#define	R367_QAM_CTRL_STATUS		0xF40C
+#define	F367_QAM_QAMFEC_LOCK		0xF40C0004
+#define	F367_QAM_TSMF_LOCK		0xF40C0002
+#define	F367_QAM_TSMF_ERROR		0xF40C0001
+
+/* TEST_CTL */
+#define	R367_QAM_TEST_CTL		0xF40F
+#define	F367_QAM_TST_BLK_SEL		0xF40F0060
+#define	F367_QAM_TST_BUS_SEL		0xF40F001F
+
+/* AGC_CTL */
+#define	R367_QAM_AGC_CTL		0xF410
+#define	F367_QAM_AGC_LCK_TH		0xF41000F0
+#define	F367_QAM_AGC_ACCUMRSTSEL		0xF4100007
+
+/* AGC_IF_CFG */
+#define	R367_QAM_AGC_IF_CFG		0xF411
+#define	F367_QAM_AGC_IF_BWSEL		0xF41100F0
+#define	F367_QAM_AGC_IF_FREEZE		0xF4110002
+
+/* AGC_RF_CFG */
+#define	R367_QAM_AGC_RF_CFG		0xF412
+#define	F367_QAM_AGC_RF_BWSEL		0xF4120070
+#define	F367_QAM_AGC_RF_FREEZE		0xF4120002
+
+/* AGC_PWM_CFG */
+#define	R367_QAM_AGC_PWM_CFG		0xF413
+#define	F367_QAM_AGC_RF_PWM_TST		0xF4130080
+#define	F367_QAM_AGC_RF_PWM_INV		0xF4130040
+#define	F367_QAM_AGC_IF_PWM_TST		0xF4130008
+#define	F367_QAM_AGC_IF_PWM_INV		0xF4130004
+#define	F367_QAM_AGC_PWM_CLKDIV		0xF4130003
+
+/* AGC_PWR_REF_L */
+#define	R367_QAM_AGC_PWR_REF_L		0xF414
+#define	F367_QAM_AGC_PWRREF_LO		0xF41400FF
+
+/* AGC_PWR_REF_H */
+#define	R367_QAM_AGC_PWR_REF_H		0xF415
+#define	F367_QAM_AGC_PWRREF_HI		0xF4150003
+
+/* AGC_RF_TH_L */
+#define	R367_QAM_AGC_RF_TH_L		0xF416
+#define	F367_QAM_AGC_RF_TH_LO		0xF41600FF
+
+/* AGC_RF_TH_H */
+#define	R367_QAM_AGC_RF_TH_H		0xF417
+#define	F367_QAM_AGC_RF_TH_HI		0xF417000F
+
+/* AGC_IF_LTH_L */
+#define	R367_QAM_AGC_IF_LTH_L		0xF418
+#define	F367_QAM_AGC_IF_THLO_LO		0xF41800FF
+
+/* AGC_IF_LTH_H */
+#define	R367_QAM_AGC_IF_LTH_H		0xF419
+#define	F367_QAM_AGC_IF_THLO_HI		0xF419000F
+
+/* AGC_IF_HTH_L */
+#define	R367_QAM_AGC_IF_HTH_L		0xF41A
+#define	F367_QAM_AGC_IF_THHI_LO		0xF41A00FF
+
+/* AGC_IF_HTH_H */
+#define	R367_QAM_AGC_IF_HTH_H		0xF41B
+#define	F367_QAM_AGC_IF_THHI_HI		0xF41B000F
+
+/* AGC_PWR_RD_L */
+#define	R367_QAM_AGC_PWR_RD_L		0xF41C
+#define	F367_QAM_AGC_PWR_WORD_LO		0xF41C00FF
+
+/* AGC_PWR_RD_M */
+#define	R367_QAM_AGC_PWR_RD_M		0xF41D
+#define	F367_QAM_AGC_PWR_WORD_ME		0xF41D00FF
+
+/* AGC_PWR_RD_H */
+#define	R367_QAM_AGC_PWR_RD_H		0xF41E
+#define	F367_QAM_AGC_PWR_WORD_HI		0xF41E0003
+
+/* AGC_PWM_IFCMD_L */
+#define	R367_QAM_AGC_PWM_IFCMD_L		0xF420
+#define	F367_QAM_AGC_IF_PWMCMD_LO		0xF42000FF
+
+/* AGC_PWM_IFCMD_H */
+#define	R367_QAM_AGC_PWM_IFCMD_H		0xF421
+#define	F367_QAM_AGC_IF_PWMCMD_HI		0xF421000F
+
+/* AGC_PWM_RFCMD_L */
+#define	R367_QAM_AGC_PWM_RFCMD_L		0xF422
+#define	F367_QAM_AGC_RF_PWMCMD_LO		0xF42200FF
+
+/* AGC_PWM_RFCMD_H */
+#define	R367_QAM_AGC_PWM_RFCMD_H		0xF423
+#define	F367_QAM_AGC_RF_PWMCMD_HI		0xF423000F
+
+/* IQDEM_CFG */
+#define	R367_QAM_IQDEM_CFG		0xF424
+#define	F367_QAM_IQDEM_CLK_SEL		0xF4240004
+#define	F367_QAM_IQDEM_INVIQ		0xF4240002
+#define	F367_QAM_IQDEM_A2DTYPE		0xF4240001
+
+/* MIX_NCO_LL */
+#define	R367_QAM_MIX_NCO_LL		0xF425
+#define	F367_QAM_MIX_NCO_INC_LL		0xF42500FF
+
+/* MIX_NCO_HL */
+#define	R367_QAM_MIX_NCO_HL		0xF426
+#define	F367_QAM_MIX_NCO_INC_HL		0xF42600FF
+
+/* MIX_NCO_HH */
+#define	R367_QAM_MIX_NCO_HH		0xF427
+#define	F367_QAM_MIX_NCO_INVCNST		0xF4270080
+#define	F367_QAM_MIX_NCO_INC_HH		0xF427007F
+
+/* SRC_NCO_LL */
+#define	R367_QAM_SRC_NCO_LL		0xF428
+#define	F367_QAM_SRC_NCO_INC_LL		0xF42800FF
+
+/* SRC_NCO_LH */
+#define	R367_QAM_SRC_NCO_LH		0xF429
+#define	F367_QAM_SRC_NCO_INC_LH		0xF42900FF
+
+/* SRC_NCO_HL */
+#define	R367_QAM_SRC_NCO_HL		0xF42A
+#define	F367_QAM_SRC_NCO_INC_HL		0xF42A00FF
+
+/* SRC_NCO_HH */
+#define	R367_QAM_SRC_NCO_HH		0xF42B
+#define	F367_QAM_SRC_NCO_INC_HH		0xF42B007F
+
+/* IQDEM_GAIN_SRC_L */
+#define	R367_QAM_IQDEM_GAIN_SRC_L		0xF42C
+#define	F367_QAM_GAIN_SRC_LO		0xF42C00FF
+
+/* IQDEM_GAIN_SRC_H */
+#define	R367_QAM_IQDEM_GAIN_SRC_H		0xF42D
+#define	F367_QAM_GAIN_SRC_HI		0xF42D0003
+
+/* IQDEM_DCRM_CFG_LL */
+#define	R367_QAM_IQDEM_DCRM_CFG_LL		0xF430
+#define	F367_QAM_DCRM0_DCIN_L		0xF43000FF
+
+/* IQDEM_DCRM_CFG_LH */
+#define	R367_QAM_IQDEM_DCRM_CFG_LH		0xF431
+#define	F367_QAM_DCRM1_I_DCIN_L		0xF43100FC
+#define	F367_QAM_DCRM0_DCIN_H		0xF4310003
+
+/* IQDEM_DCRM_CFG_HL */
+#define	R367_QAM_IQDEM_DCRM_CFG_HL		0xF432
+#define	F367_QAM_DCRM1_Q_DCIN_L		0xF43200F0
+#define	F367_QAM_DCRM1_I_DCIN_H		0xF432000F
+
+/* IQDEM_DCRM_CFG_HH */
+#define	R367_QAM_IQDEM_DCRM_CFG_HH		0xF433
+#define	F367_QAM_DCRM1_FRZ		0xF4330080
+#define	F367_QAM_DCRM0_FRZ		0xF4330040
+#define	F367_QAM_DCRM1_Q_DCIN_H		0xF433003F
+
+/* IQDEM_ADJ_COEFF0 */
+#define	R367_QAM_IQDEM_ADJ_COEFF0		0xF434
+#define	F367_QAM_ADJIIR_COEFF10_L		0xF43400FF
+
+/* IQDEM_ADJ_COEFF1 */
+#define	R367_QAM_IQDEM_ADJ_COEFF1		0xF435
+#define	F367_QAM_ADJIIR_COEFF11_L		0xF43500FC
+#define	F367_QAM_ADJIIR_COEFF10_H		0xF4350003
+
+/* IQDEM_ADJ_COEFF2 */
+#define	R367_QAM_IQDEM_ADJ_COEFF2		0xF436
+#define	F367_QAM_ADJIIR_COEFF12_L		0xF43600F0
+#define	F367_QAM_ADJIIR_COEFF11_H		0xF436000F
+
+/* IQDEM_ADJ_COEFF3 */
+#define	R367_QAM_IQDEM_ADJ_COEFF3		0xF437
+#define	F367_QAM_ADJIIR_COEFF20_L		0xF43700C0
+#define	F367_QAM_ADJIIR_COEFF12_H		0xF437003F
+
+/* IQDEM_ADJ_COEFF4 */
+#define	R367_QAM_IQDEM_ADJ_COEFF4		0xF438
+#define	F367_QAM_ADJIIR_COEFF20_H		0xF43800FF
+
+/* IQDEM_ADJ_COEFF5 */
+#define	R367_QAM_IQDEM_ADJ_COEFF5		0xF439
+#define	F367_QAM_ADJIIR_COEFF21_L		0xF43900FF
+
+/* IQDEM_ADJ_COEFF6 */
+#define	R367_QAM_IQDEM_ADJ_COEFF6		0xF43A
+#define	F367_QAM_ADJIIR_COEFF22_L		0xF43A00FC
+#define	F367_QAM_ADJIIR_COEFF21_H		0xF43A0003
+
+/* IQDEM_ADJ_COEFF7 */
+#define	R367_QAM_IQDEM_ADJ_COEFF7		0xF43B
+#define	F367_QAM_ADJIIR_COEFF22_H		0xF43B000F
+
+/* IQDEM_ADJ_EN */
+#define	R367_QAM_IQDEM_ADJ_EN		0xF43C
+#define	F367_QAM_ALLPASSFILT_EN		0xF43C0008
+#define	F367_QAM_ADJ_AGC_EN		0xF43C0004
+#define	F367_QAM_ADJ_COEFF_FRZ		0xF43C0002
+#define	F367_QAM_ADJ_EN		0xF43C0001
+
+/* IQDEM_ADJ_AGC_REF */
+#define	R367_QAM_IQDEM_ADJ_AGC_REF		0xF43D
+#define	F367_QAM_ADJ_AGC_REF		0xF43D00FF
+
+/* ALLPASSFILT1 */
+#define	R367_QAM_ALLPASSFILT1		0xF440
+#define	F367_QAM_ALLPASSFILT_COEFF1_LO		0xF44000FF
+
+/* ALLPASSFILT2 */
+#define	R367_QAM_ALLPASSFILT2		0xF441
+#define	F367_QAM_ALLPASSFILT_COEFF1_ME		0xF44100FF
+
+/* ALLPASSFILT3 */
+#define	R367_QAM_ALLPASSFILT3		0xF442
+#define	F367_QAM_ALLPASSFILT_COEFF2_LO		0xF44200C0
+#define	F367_QAM_ALLPASSFILT_COEFF1_HI		0xF442003F
+
+/* ALLPASSFILT4 */
+#define	R367_QAM_ALLPASSFILT4		0xF443
+#define	F367_QAM_ALLPASSFILT_COEFF2_MEL		0xF44300FF
+
+/* ALLPASSFILT5 */
+#define	R367_QAM_ALLPASSFILT5		0xF444
+#define	F367_QAM_ALLPASSFILT_COEFF2_MEH		0xF44400FF
+
+/* ALLPASSFILT6 */
+#define	R367_QAM_ALLPASSFILT6		0xF445
+#define	F367_QAM_ALLPASSFILT_COEFF3_LO		0xF44500F0
+#define	F367_QAM_ALLPASSFILT_COEFF2_HI		0xF445000F
+
+/* ALLPASSFILT7 */
+#define	R367_QAM_ALLPASSFILT7		0xF446
+#define	F367_QAM_ALLPASSFILT_COEFF3_MEL		0xF44600FF
+
+/* ALLPASSFILT8 */
+#define	R367_QAM_ALLPASSFILT8		0xF447
+#define	F367_QAM_ALLPASSFILT_COEFF3_MEH		0xF44700FF
+
+/* ALLPASSFILT9 */
+#define	R367_QAM_ALLPASSFILT9		0xF448
+#define	F367_QAM_ALLPASSFILT_COEFF4_LO		0xF44800FC
+#define	F367_QAM_ALLPASSFILT_COEFF3_HI		0xF4480003
+
+/* ALLPASSFILT10 */
+#define	R367_QAM_ALLPASSFILT10		0xF449
+#define	F367_QAM_ALLPASSFILT_COEFF4_ME		0xF44900FF
+
+/* ALLPASSFILT11 */
+#define	R367_QAM_ALLPASSFILT11		0xF44A
+#define	F367_QAM_ALLPASSFILT_COEFF4_HI		0xF44A00FF
+
+/* TRL_AGC_CFG */
+#define	R367_QAM_TRL_AGC_CFG		0xF450
+#define	F367_QAM_TRL_AGC_FREEZE		0xF4500080
+#define	F367_QAM_TRL_AGC_REF		0xF450007F
+
+/* TRL_LPF_CFG */
+#define	R367_QAM_TRL_LPF_CFG		0xF454
+#define	F367_QAM_NYQPOINT_INV		0xF4540040
+#define	F367_QAM_TRL_SHIFT		0xF4540030
+#define	F367_QAM_NYQ_COEFF_SEL		0xF454000C
+#define	F367_QAM_TRL_LPF_FREEZE		0xF4540002
+#define	F367_QAM_TRL_LPF_CRT		0xF4540001
+
+/* TRL_LPF_ACQ_GAIN */
+#define	R367_QAM_TRL_LPF_ACQ_GAIN		0xF455
+#define	F367_QAM_TRL_GDIR_ACQ		0xF4550070
+#define	F367_QAM_TRL_GINT_ACQ		0xF4550007
+
+/* TRL_LPF_TRK_GAIN */
+#define	R367_QAM_TRL_LPF_TRK_GAIN		0xF456
+#define	F367_QAM_TRL_GDIR_TRK		0xF4560070
+#define	F367_QAM_TRL_GINT_TRK		0xF4560007
+
+/* TRL_LPF_OUT_GAIN */
+#define	R367_QAM_TRL_LPF_OUT_GAIN		0xF457
+#define	F367_QAM_TRL_GAIN_OUT		0xF4570007
+
+/* TRL_LOCKDET_LTH */
+#define	R367_QAM_TRL_LOCKDET_LTH		0xF458
+#define	F367_QAM_TRL_LCK_THLO		0xF4580007
+
+/* TRL_LOCKDET_HTH */
+#define	R367_QAM_TRL_LOCKDET_HTH		0xF459
+#define	F367_QAM_TRL_LCK_THHI		0xF45900FF
+
+/* TRL_LOCKDET_TRGVAL */
+#define	R367_QAM_TRL_LOCKDET_TRGVAL		0xF45A
+#define	F367_QAM_TRL_LCK_TRG		0xF45A00FF
+
+/* IQ_QAM */
+#define	R367_QAM_IQ_QAM		0xF45C
+#define	F367_QAM_IQ_INPUT		0xF45C0008
+#define	F367_QAM_DETECT_MODE		0xF45C0007
+
+/* FSM_STATE */
+#define	R367_QAM_FSM_STATE		0xF460
+#define	F367_QAM_CRL_DFE		0xF4600080
+#define	F367_QAM_DFE_START		0xF4600040
+#define	F367_QAM_CTRLG_START		0xF4600030
+#define	F367_QAM_FSM_FORCESTATE		0xF460000F
+
+/* FSM_CTL */
+#define	R367_QAM_FSM_CTL		0xF461
+#define	F367_QAM_FEC2_EN		0xF4610040
+#define	F367_QAM_SIT_EN		0xF4610020
+#define	F367_QAM_TRL_AHEAD		0xF4610010
+#define	F367_QAM_TRL2_EN		0xF4610008
+#define	F367_QAM_FSM_EQA1_EN		0xF4610004
+#define	F367_QAM_FSM_BKP_DIS		0xF4610002
+#define	F367_QAM_FSM_FORCE_EN		0xF4610001
+
+/* FSM_STS */
+#define	R367_QAM_FSM_STS		0xF462
+#define	F367_QAM_FSM_STATUS		0xF462000F
+
+/* FSM_SNR0_HTH */
+#define	R367_QAM_FSM_SNR0_HTH		0xF463
+#define	F367_QAM_SNR0_HTH		0xF46300FF
+
+/* FSM_SNR1_HTH */
+#define	R367_QAM_FSM_SNR1_HTH		0xF464
+#define	F367_QAM_SNR1_HTH		0xF46400FF
+
+/* FSM_SNR2_HTH */
+#define	R367_QAM_FSM_SNR2_HTH		0xF465
+#define	F367_QAM_SNR2_HTH		0xF46500FF
+
+/* FSM_SNR0_LTH */
+#define	R367_QAM_FSM_SNR0_LTH		0xF466
+#define	F367_QAM_SNR0_LTH		0xF46600FF
+
+/* FSM_SNR1_LTH */
+#define	R367_QAM_FSM_SNR1_LTH		0xF467
+#define	F367_QAM_SNR1_LTH		0xF46700FF
+
+/* FSM_EQA1_HTH */
+#define	R367_QAM_FSM_EQA1_HTH		0xF468
+#define	F367_QAM_SNR3_HTH_LO		0xF46800F0
+#define	F367_QAM_EQA1_HTH		0xF468000F
+
+/* FSM_TEMPO */
+#define	R367_QAM_FSM_TEMPO		0xF469
+#define	F367_QAM_SIT		0xF46900C0
+#define	F367_QAM_WST		0xF4690038
+#define	F367_QAM_ELT		0xF4690006
+#define	F367_QAM_SNR3_HTH_HI		0xF4690001
+
+/* FSM_CONFIG */
+#define	R367_QAM_FSM_CONFIG		0xF46A
+#define	F367_QAM_FEC2_DFEOFF		0xF46A0004
+#define	F367_QAM_PRIT_STATE		0xF46A0002
+#define	F367_QAM_MODMAP_STATE		0xF46A0001
+
+/* EQU_I_TESTTAP_L */
+#define	R367_QAM_EQU_I_TESTTAP_L		0xF474
+#define	F367_QAM_I_TEST_TAP_L		0xF47400FF
+
+/* EQU_I_TESTTAP_M */
+#define	R367_QAM_EQU_I_TESTTAP_M		0xF475
+#define	F367_QAM_I_TEST_TAP_M		0xF47500FF
+
+/* EQU_I_TESTTAP_H */
+#define	R367_QAM_EQU_I_TESTTAP_H		0xF476
+#define	F367_QAM_I_TEST_TAP_H		0xF476001F
+
+/* EQU_TESTAP_CFG */
+#define	R367_QAM_EQU_TESTAP_CFG		0xF477
+#define	F367_QAM_TEST_FFE_DFE_SEL		0xF4770040
+#define	F367_QAM_TEST_TAP_SELECT		0xF477003F
+
+/* EQU_Q_TESTTAP_L */
+#define	R367_QAM_EQU_Q_TESTTAP_L		0xF478
+#define	F367_QAM_Q_TEST_TAP_L		0xF47800FF
+
+/* EQU_Q_TESTTAP_M */
+#define	R367_QAM_EQU_Q_TESTTAP_M		0xF479
+#define	F367_QAM_Q_TEST_TAP_M		0xF47900FF
+
+/* EQU_Q_TESTTAP_H */
+#define	R367_QAM_EQU_Q_TESTTAP_H		0xF47A
+#define	F367_QAM_Q_TEST_TAP_H		0xF47A001F
+
+/* EQU_TAP_CTRL */
+#define	R367_QAM_EQU_TAP_CTRL		0xF47B
+#define	F367_QAM_MTAP_FRZ		0xF47B0010
+#define	F367_QAM_PRE_FREEZE		0xF47B0008
+#define	F367_QAM_DFE_TAPMON_EN		0xF47B0004
+#define	F367_QAM_FFE_TAPMON_EN		0xF47B0002
+#define	F367_QAM_MTAP_ONLY		0xF47B0001
+
+/* EQU_CTR_CRL_CONTROL_L */
+#define	R367_QAM_EQU_CTR_CRL_CONTROL_L		0xF47C
+#define	F367_QAM_EQU_CTR_CRL_CONTROL_LO		0xF47C00FF
+
+/* EQU_CTR_CRL_CONTROL_H */
+#define	R367_QAM_EQU_CTR_CRL_CONTROL_H		0xF47D
+#define	F367_QAM_EQU_CTR_CRL_CONTROL_HI		0xF47D00FF
+
+/* EQU_CTR_HIPOW_L */
+#define	R367_QAM_EQU_CTR_HIPOW_L		0xF47E
+#define	F367_QAM_CTR_HIPOW_L		0xF47E00FF
+
+/* EQU_CTR_HIPOW_H */
+#define	R367_QAM_EQU_CTR_HIPOW_H		0xF47F
+#define	F367_QAM_CTR_HIPOW_H		0xF47F00FF
+
+/* EQU_I_EQU_LO */
+#define	R367_QAM_EQU_I_EQU_LO		0xF480
+#define	F367_QAM_EQU_I_EQU_L		0xF48000FF
+
+/* EQU_I_EQU_HI */
+#define	R367_QAM_EQU_I_EQU_HI		0xF481
+#define	F367_QAM_EQU_I_EQU_H		0xF4810003
+
+/* EQU_Q_EQU_LO */
+#define	R367_QAM_EQU_Q_EQU_LO		0xF482
+#define	F367_QAM_EQU_Q_EQU_L		0xF48200FF
+
+/* EQU_Q_EQU_HI */
+#define	R367_QAM_EQU_Q_EQU_HI		0xF483
+#define	F367_QAM_EQU_Q_EQU_H		0xF4830003
+
+/* EQU_MAPPER */
+#define	R367_QAM_EQU_MAPPER		0xF484
+#define	F367_QAM_QUAD_AUTO		0xF4840080
+#define	F367_QAM_QUAD_INV		0xF4840040
+#define	F367_QAM_QAM_MODE		0xF4840007
+
+/* EQU_SWEEP_RATE */
+#define	R367_QAM_EQU_SWEEP_RATE		0xF485
+#define	F367_QAM_SNR_PER		0xF48500C0
+#define	F367_QAM_SWEEP_RATE		0xF485003F
+
+/* EQU_SNR_LO */
+#define	R367_QAM_EQU_SNR_LO		0xF486
+#define	F367_QAM_SNR_LO		0xF48600FF
+
+/* EQU_SNR_HI */
+#define	R367_QAM_EQU_SNR_HI		0xF487
+#define	F367_QAM_SNR_HI		0xF48700FF
+
+/* EQU_GAMMA_LO */
+#define	R367_QAM_EQU_GAMMA_LO		0xF488
+#define	F367_QAM_GAMMA_LO		0xF48800FF
+
+/* EQU_GAMMA_HI */
+#define	R367_QAM_EQU_GAMMA_HI		0xF489
+#define	F367_QAM_GAMMA_ME		0xF48900FF
+
+/* EQU_ERR_GAIN */
+#define	R367_QAM_EQU_ERR_GAIN		0xF48A
+#define	F367_QAM_EQA1MU		0xF48A0070
+#define	F367_QAM_CRL2MU		0xF48A000E
+#define	F367_QAM_GAMMA_HI		0xF48A0001
+
+/* EQU_RADIUS */
+#define	R367_QAM_EQU_RADIUS		0xF48B
+#define	F367_QAM_RADIUS		0xF48B00FF
+
+/* EQU_FFE_MAINTAP */
+#define	R367_QAM_EQU_FFE_MAINTAP		0xF48C
+#define	F367_QAM_FFE_MAINTAP_INIT		0xF48C00FF
+
+/* EQU_FFE_LEAKAGE */
+#define	R367_QAM_EQU_FFE_LEAKAGE		0xF48E
+#define	F367_QAM_LEAK_PER		0xF48E00F0
+#define	F367_QAM_EQU_OUTSEL		0xF48E0002
+#define	F367_QAM_PNT2DFE		0xF48E0001
+
+/* EQU_FFE_MAINTAP_POS */
+#define	R367_QAM_EQU_FFE_MAINTAP_POS		0xF48F
+#define	F367_QAM_FFE_LEAK_EN		0xF48F0080
+#define	F367_QAM_DFE_LEAK_EN		0xF48F0040
+#define	F367_QAM_FFE_MAINTAP_POS		0xF48F003F
+
+/* EQU_GAIN_WIDE */
+#define	R367_QAM_EQU_GAIN_WIDE		0xF490
+#define	F367_QAM_DFE_GAIN_WIDE		0xF49000F0
+#define	F367_QAM_FFE_GAIN_WIDE		0xF490000F
+
+/* EQU_GAIN_NARROW */
+#define	R367_QAM_EQU_GAIN_NARROW		0xF491
+#define	F367_QAM_DFE_GAIN_NARROW		0xF49100F0
+#define	F367_QAM_FFE_GAIN_NARROW		0xF491000F
+
+/* EQU_CTR_LPF_GAIN */
+#define	R367_QAM_EQU_CTR_LPF_GAIN		0xF492
+#define	F367_QAM_CTR_GTO		0xF4920080
+#define	F367_QAM_CTR_GDIR		0xF4920070
+#define	F367_QAM_SWEEP_EN		0xF4920008
+#define	F367_QAM_CTR_GINT		0xF4920007
+
+/* EQU_CRL_LPF_GAIN */
+#define	R367_QAM_EQU_CRL_LPF_GAIN		0xF493
+#define	F367_QAM_CRL_GTO		0xF4930080
+#define	F367_QAM_CRL_GDIR		0xF4930070
+#define	F367_QAM_SWEEP_DIR		0xF4930008
+#define	F367_QAM_CRL_GINT		0xF4930007
+
+/* EQU_GLOBAL_GAIN */
+#define	R367_QAM_EQU_GLOBAL_GAIN		0xF494
+#define	F367_QAM_CRL_GAIN		0xF49400F8
+#define	F367_QAM_CTR_INC_GAIN		0xF4940004
+#define	F367_QAM_CTR_FRAC		0xF4940003
+
+/* EQU_CRL_LD_SEN */
+#define	R367_QAM_EQU_CRL_LD_SEN		0xF495
+#define	F367_QAM_CTR_BADPOINT_EN		0xF4950080
+#define	F367_QAM_CTR_GAIN		0xF4950070
+#define	F367_QAM_LIMANEN		0xF4950008
+#define	F367_QAM_CRL_LD_SEN		0xF4950007
+
+/* EQU_CRL_LD_VAL */
+#define	R367_QAM_EQU_CRL_LD_VAL		0xF496
+#define	F367_QAM_CRL_BISTH_LIMIT		0xF4960080
+#define	F367_QAM_CARE_EN		0xF4960040
+#define	F367_QAM_CRL_LD_PER		0xF4960030
+#define	F367_QAM_CRL_LD_WST		0xF496000C
+#define	F367_QAM_CRL_LD_TFS		0xF4960003
+
+/* EQU_CRL_TFR */
+#define	R367_QAM_EQU_CRL_TFR		0xF497
+#define	F367_QAM_CRL_LD_TFR		0xF49700FF
+
+/* EQU_CRL_BISTH_LO */
+#define	R367_QAM_EQU_CRL_BISTH_LO		0xF498
+#define	F367_QAM_CRL_BISTH_LO		0xF49800FF
+
+/* EQU_CRL_BISTH_HI */
+#define	R367_QAM_EQU_CRL_BISTH_HI		0xF499
+#define	F367_QAM_CRL_BISTH_HI		0xF49900FF
+
+/* EQU_SWEEP_RANGE_LO */
+#define	R367_QAM_EQU_SWEEP_RANGE_LO		0xF49A
+#define	F367_QAM_SWEEP_RANGE_LO		0xF49A00FF
+
+/* EQU_SWEEP_RANGE_HI */
+#define	R367_QAM_EQU_SWEEP_RANGE_HI		0xF49B
+#define	F367_QAM_SWEEP_RANGE_HI		0xF49B00FF
+
+/* EQU_CRL_LIMITER */
+#define	R367_QAM_EQU_CRL_LIMITER		0xF49C
+#define	F367_QAM_BISECTOR_EN		0xF49C0080
+#define	F367_QAM_PHEST128_EN		0xF49C0040
+#define	F367_QAM_CRL_LIM		0xF49C003F
+
+/* EQU_MODULUS_MAP */
+#define	R367_QAM_EQU_MODULUS_MAP		0xF49D
+#define	F367_QAM_PNT_DEPTH		0xF49D00E0
+#define	F367_QAM_MODULUS_CMP		0xF49D001F
+
+/* EQU_PNT_GAIN */
+#define	R367_QAM_EQU_PNT_GAIN		0xF49E
+#define	F367_QAM_PNT_EN		0xF49E0080
+#define	F367_QAM_MODULUSMAP_EN		0xF49E0040
+#define	F367_QAM_PNT_GAIN		0xF49E003F
+
+/* FEC_AC_CTR_0 */
+#define	R367_QAM_FEC_AC_CTR_0		0xF4A8
+#define	F367_QAM_BE_BYPASS		0xF4A80020
+#define	F367_QAM_REFRESH47		0xF4A80010
+#define	F367_QAM_CT_NBST		0xF4A80008
+#define	F367_QAM_TEI_ENA		0xF4A80004
+#define	F367_QAM_DS_ENA		0xF4A80002
+#define	F367_QAM_TSMF_EN		0xF4A80001
+
+/* FEC_AC_CTR_1 */
+#define	R367_QAM_FEC_AC_CTR_1		0xF4A9
+#define	F367_QAM_DEINT_DEPTH		0xF4A900FF
+
+/* FEC_AC_CTR_2 */
+#define	R367_QAM_FEC_AC_CTR_2		0xF4AA
+#define	F367_QAM_DEINT_M		0xF4AA00F8
+#define	F367_QAM_DIS_UNLOCK		0xF4AA0004
+#define	F367_QAM_DESCR_MODE		0xF4AA0003
+
+/* FEC_AC_CTR_3 */
+#define	R367_QAM_FEC_AC_CTR_3		0xF4AB
+#define	F367_QAM_DI_UNLOCK		0xF4AB0080
+#define	F367_QAM_DI_FREEZE		0xF4AB0040
+#define	F367_QAM_MISMATCH		0xF4AB0030
+#define	F367_QAM_ACQ_MODE		0xF4AB000C
+#define	F367_QAM_TRK_MODE		0xF4AB0003
+
+/* FEC_STATUS */
+#define	R367_QAM_FEC_STATUS		0xF4AC
+#define	F367_QAM_DEINT_SMCNTR		0xF4AC00E0
+#define	F367_QAM_DEINT_SYNCSTATE		0xF4AC0018
+#define	F367_QAM_DEINT_SYNLOST		0xF4AC0004
+#define	F367_QAM_DESCR_SYNCSTATE		0xF4AC0002
+
+/* RS_COUNTER_0 */
+#define	R367_QAM_RS_COUNTER_0		0xF4AE
+#define	F367_QAM_BK_CT_L		0xF4AE00FF
+
+/* RS_COUNTER_1 */
+#define	R367_QAM_RS_COUNTER_1		0xF4AF
+#define	F367_QAM_BK_CT_H		0xF4AF00FF
+
+/* RS_COUNTER_2 */
+#define	R367_QAM_RS_COUNTER_2		0xF4B0
+#define	F367_QAM_CORR_CT_L		0xF4B000FF
+
+/* RS_COUNTER_3 */
+#define	R367_QAM_RS_COUNTER_3		0xF4B1
+#define	F367_QAM_CORR_CT_H		0xF4B100FF
+
+/* RS_COUNTER_4 */
+#define	R367_QAM_RS_COUNTER_4		0xF4B2
+#define	F367_QAM_UNCORR_CT_L		0xF4B200FF
+
+/* RS_COUNTER_5 */
+#define	R367_QAM_RS_COUNTER_5		0xF4B3
+#define	F367_QAM_UNCORR_CT_H		0xF4B300FF
+
+/* BERT_0 */
+#define	R367_QAM_BERT_0		0xF4B4
+#define	F367_QAM_RS_NOCORR		0xF4B40004
+#define	F367_QAM_CT_HOLD		0xF4B40002
+#define	F367_QAM_CT_CLEAR		0xF4B40001
+
+/* BERT_1 */
+#define	R367_QAM_BERT_1		0xF4B5
+#define	F367_QAM_BERT_ON		0xF4B50020
+#define	F367_QAM_BERT_ERR_SRC		0xF4B50010
+#define	F367_QAM_BERT_ERR_MODE		0xF4B50008
+#define	F367_QAM_BERT_NBYTE		0xF4B50007
+
+/* BERT_2 */
+#define	R367_QAM_BERT_2		0xF4B6
+#define	F367_QAM_BERT_ERRCOUNT_L		0xF4B600FF
+
+/* BERT_3 */
+#define	R367_QAM_BERT_3		0xF4B7
+#define	F367_QAM_BERT_ERRCOUNT_H		0xF4B700FF
+
+/* OUTFORMAT_0 */
+#define	R367_QAM_OUTFORMAT_0		0xF4B8
+#define	F367_QAM_CLK_POLARITY		0xF4B80080
+#define	F367_QAM_FEC_TYPE		0xF4B80040
+#define	F367_QAM_SYNC_STRIP		0xF4B80008
+#define	F367_QAM_TS_SWAP		0xF4B80004
+#define	F367_QAM_OUTFORMAT		0xF4B80003
+
+/* OUTFORMAT_1 */
+#define	R367_QAM_OUTFORMAT_1		0xF4B9
+#define	F367_QAM_CI_DIVRANGE		0xF4B900FF
+
+/* SMOOTHER_2 */
+#define	R367_QAM_SMOOTHER_2		0xF4BE
+#define	F367_QAM_FIFO_BYPASS		0xF4BE0020
+
+/* TSMF_CTRL_0 */
+#define	R367_QAM_TSMF_CTRL_0		0xF4C0
+#define	F367_QAM_TS_NUMBER		0xF4C0001E
+#define	F367_QAM_SEL_MODE		0xF4C00001
+
+/* TSMF_CTRL_1 */
+#define	R367_QAM_TSMF_CTRL_1		0xF4C1
+#define	F367_QAM_CHECK_ERROR_BIT		0xF4C10080
+#define	F367_QAM_CHCK_F_SYNC		0xF4C10040
+#define	F367_QAM_H_MODE		0xF4C10008
+#define	F367_QAM_D_V_MODE		0xF4C10004
+#define	F367_QAM_MODE		0xF4C10003
+
+/* TSMF_CTRL_3 */
+#define	R367_QAM_TSMF_CTRL_3		0xF4C3
+#define	F367_QAM_SYNC_IN_COUNT		0xF4C300F0
+#define	F367_QAM_SYNC_OUT_COUNT		0xF4C3000F
+
+/* TS_ON_ID_0 */
+#define	R367_QAM_TS_ON_ID_0		0xF4C4
+#define	F367_QAM_TS_ID_L		0xF4C400FF
+
+/* TS_ON_ID_1 */
+#define	R367_QAM_TS_ON_ID_1		0xF4C5
+#define	F367_QAM_TS_ID_H		0xF4C500FF
+
+/* TS_ON_ID_2 */
+#define	R367_QAM_TS_ON_ID_2		0xF4C6
+#define	F367_QAM_ON_ID_L		0xF4C600FF
+
+/* TS_ON_ID_3 */
+#define	R367_QAM_TS_ON_ID_3		0xF4C7
+#define	F367_QAM_ON_ID_H		0xF4C700FF
+
+/* RE_STATUS_0 */
+#define	R367_QAM_RE_STATUS_0		0xF4C8
+#define	F367_QAM_RECEIVE_STATUS_L		0xF4C800FF
+
+/* RE_STATUS_1 */
+#define	R367_QAM_RE_STATUS_1		0xF4C9
+#define	F367_QAM_RECEIVE_STATUS_LH		0xF4C900FF
+
+/* RE_STATUS_2 */
+#define	R367_QAM_RE_STATUS_2		0xF4CA
+#define	F367_QAM_RECEIVE_STATUS_HL		0xF4CA00FF
+
+/* RE_STATUS_3 */
+#define	R367_QAM_RE_STATUS_3		0xF4CB
+#define	F367_QAM_RECEIVE_STATUS_HH		0xF4CB003F
+
+/* TS_STATUS_0 */
+#define	R367_QAM_TS_STATUS_0		0xF4CC
+#define	F367_QAM_TS_STATUS_L		0xF4CC00FF
+
+/* TS_STATUS_1 */
+#define	R367_QAM_TS_STATUS_1		0xF4CD
+#define	F367_QAM_TS_STATUS_H		0xF4CD007F
+
+/* TS_STATUS_2 */
+#define	R367_QAM_TS_STATUS_2		0xF4CE
+#define	F367_QAM_ERROR		0xF4CE0080
+#define	F367_QAM_EMERGENCY		0xF4CE0040
+#define	F367_QAM_CRE_TS		0xF4CE0030
+#define	F367_QAM_VER		0xF4CE000E
+#define	F367_QAM_M_LOCK		0xF4CE0001
+
+/* TS_STATUS_3 */
+#define	R367_QAM_TS_STATUS_3		0xF4CF
+#define	F367_QAM_UPDATE_READY		0xF4CF0080
+#define	F367_QAM_END_FRAME_HEADER		0xF4CF0040
+#define	F367_QAM_CONTCNT		0xF4CF0020
+#define	F367_QAM_TS_IDENTIFIER_SEL		0xF4CF000F
+
+/* T_O_ID_0 */
+#define	R367_QAM_T_O_ID_0		0xF4D0
+#define	F367_QAM_ON_ID_I_L		0xF4D000FF
+
+/* T_O_ID_1 */
+#define	R367_QAM_T_O_ID_1		0xF4D1
+#define	F367_QAM_ON_ID_I_H		0xF4D100FF
+
+/* T_O_ID_2 */
+#define	R367_QAM_T_O_ID_2		0xF4D2
+#define	F367_QAM_TS_ID_I_L		0xF4D200FF
+
+/* T_O_ID_3 */
+#define	R367_QAM_T_O_ID_3		0xF4D3
+#define	F367_QAM_TS_ID_I_H		0xF4D300FF
+
diff -Naur linux-3.6.8/drivers/media/dvb/frontends/tda18212dd.c linux-3.6.8.patch/drivers/media/dvb/frontends/tda18212dd.c
--- linux-3.6.8/drivers/media/dvb/frontends/tda18212dd.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/frontends/tda18212dd.c	2012-12-03 09:05:08.956017665 +0100
@@ -0,0 +1,906 @@
+/*
+ * tda18212: Driver for the TDA18212 tuner
+ *
+ * Copyright (C) 2011 Digital Devices GmbH
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/version.h>
+#include <asm/div64.h>
+
+#include "dvb_frontend.h"
+
+#ifndef CHK_ERROR
+    #define CHK_ERROR(s) if ((status = s) < 0) break
+#endif
+
+#define MASTER_PSM_AGC1     0
+#define MASTER_AGC1_6_15dB  1
+
+#define SLAVE_PSM_AGC1      1
+#define SLAVE_AGC1_6_15dB   0
+
+// 0 = 2 Vpp ... 2 = 1 Vpp,   7 = 0.5 Vpp
+#define IF_LEVEL_DVBC    2
+#define IF_LEVEL_DVBT    2
+
+enum {
+	ID_1                = 0x00,
+	ID_2                = 0x01,
+	ID_3                = 0x02,
+	THERMO_1,
+	THERMO_2,
+	POWER_STATE_1,
+	POWER_STATE_2,
+	INPUT_POWER_LEVEL,
+	IRQ_STATUS,
+	IRQ_ENABLE,
+	IRQ_CLEAR,
+	IRQ_SET,
+	AGC1_1,
+	AGC2_1,
+	AGCK_1,
+	RF_AGC_1,
+	IR_MIXER_1          = 0x10,
+	AGC5_1,
+	IF_AGC,
+	IF_1,
+	REFERENCE,
+	IF_FREQUENCY_1,
+	RF_FREQUENCY_1,
+	RF_FREQUENCY_2,
+	RF_FREQUENCY_3,
+	MSM_1,
+	MSM_2,
+	PSM_1,
+	DCC_1,
+	FLO_MAX,
+	IR_CAL_1,
+	IR_CAL_2,
+	IR_CAL_3            = 0x20,
+	IR_CAL_4,
+	VSYNC_MGT,
+	IR_MIXER_2,
+	AGC1_2,
+	AGC5_2,
+	RF_CAL_1,
+	RF_CAL_2,
+	RF_CAL_3,
+	RF_CAL_4,
+	RF_CAL_5,
+	RF_CAL_6,
+	RF_FILTER_1,
+	RF_FILTER_2,
+	RF_FILTER_3,
+	RF_BAND_PASS_FILTER,
+	CP_CURRENT          = 0x30,
+	AGC_DET_OUT         = 0x31,
+	RF_AGC_GAIN_1       = 0x32,
+	RF_AGC_GAIN_2       = 0x33,
+	IF_AGC_GAIN         = 0x34,
+	POWER_1             = 0x35,
+	POWER_2             = 0x36,
+	MISC_1,
+	RFCAL_LOG_1,
+	RFCAL_LOG_2,
+	RFCAL_LOG_3,
+	RFCAL_LOG_4,
+	RFCAL_LOG_5,
+	RFCAL_LOG_6,
+	RFCAL_LOG_7,
+	RFCAL_LOG_8,
+	RFCAL_LOG_9         = 0x40,
+	RFCAL_LOG_10        = 0x41,
+	RFCAL_LOG_11        = 0x42,
+	RFCAL_LOG_12        = 0x43,
+	REG_MAX,
+};
+
+enum HF_Standard {
+	HF_None=0, HF_B, HF_DK, HF_G, HF_I, HF_L, HF_L1, HF_MN, HF_FM_Radio,
+	HF_AnalogMax, HF_DVBT_6MHZ, HF_DVBT_7MHZ, HF_DVBT_8MHZ,
+	HF_DVBT, HF_ATSC,  HF_DVBC_6MHZ,  HF_DVBC_7MHZ,
+	HF_DVBC_8MHZ, HF_DVBC
+};
+
+struct SStandardParams {
+	s32   m_IFFrequency;
+	u32   m_BandWidth;
+	u8    m_IF_1;         // FF IF_HP_fc:2 IF_Notch:1 LP_FC_Offset:2 LP_FC:3
+	u8    m_IR_MIXER_2;   // 03 :6 HI_Pass:1 DC_Notch:1
+	u8    m_AGC1_1;       // 0F :4 AGC1_Top:4
+	u8    m_AGC2_1;       // 0F :4 AGC2_Top:4
+	u8    m_RF_AGC_1_Low; // EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1  RF_AGC_Top:3
+	u8    m_RF_AGC_1_High;// EF RF_AGC_Adapt:1 RF_AGC_Adapt_Top:2 :1 RF_Atten_3dB:1  RF_AGC_Top:3
+	u8    m_IR_MIXER_1;   // 0F :4 IR_mixer_Top:4
+	u8    m_AGC5_1;       // 1F :3 AGC5_Ana AGC5_Top:4
+	u8    m_AGCK_1;       // 0F :4 AGCK_Step:2 AGCK_Mode:2
+	u8    m_PSM_1;        // 20 :2 PSM_StoB:1 :5
+	bool  m_AGC1_Freeze;
+	bool  m_LTO_STO_immune;
+};
+
+struct SStandardParams m_StandardTable[HF_DVBC_8MHZ - HF_DVBT_6MHZ + 1] =
+{
+	{ 3250000, 6000000, 0x20, 0x03, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_6MHZ
+	{ 3500000, 7000000, 0x31, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_7MHZ
+	{ 4000000, 8000000, 0x22, 0x01, 0x00, 0x07, 0x2B, 0x2C, 0x0B, 0x0B, 0x02, 0x20, false, false },    // HF_DVBT_8MHZ
+	{       0,       0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, false, false },    // HF_DVBT (Unused)
+	{ 3250000, 6000000, 0x20, 0x03, 0x0A, 0x07, 0x6D, 0x6D, 0x0E, 0x0E, 0x02, 0x20, false, false },    // HF_ATSC
+	{ 3600000, 6000000, 0x10, 0x01, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_6MHZ
+//    { 5000000, 7000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
+//    { 5000000, 8000000, 0x53, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
+	{ 5000000, 7000000, 0x93, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_7MHZ (not documented by NXP, use same settings as 8 MHZ)
+	{ 5000000, 8000000, 0x43, 0x03, 0x00, 0x07, 0x83, 0x83, 0x0B, 0x0B, 0x02, 0x00, true , true  },    // HF_DVBC_8MHZ
+};
+
+struct tda_state {
+	struct i2c_adapter *i2c;
+	u8 adr;
+
+	enum HF_Standard m_Standard;
+	u32   m_Frequency;
+	u32   IF;
+
+	bool    m_isMaster;
+	bool    m_bPowerMeasurement;
+	bool    m_bLTEnable;
+	bool    m_bEnableFreeze;
+
+	u16   m_ID;
+
+	s32    m_SettlingTime;
+
+	u8    m_IFLevelDVBC;
+	u8    m_IFLevelDVBT;
+	u8    m_Regs[REG_MAX];
+	u8    m_LastPowerLevel;
+};
+
+static int i2c_readn(struct i2c_adapter *adapter, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = data, .len   = len}};
+	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
+}
+
+static int i2c_read(struct i2c_adapter *adap,
+		    u8 adr, u8 *msg, int len, u8 *answ, int alen)
+{
+	struct i2c_msg msgs[2] = { { .addr = adr, .flags = 0,
+				     .buf = msg, .len = len},
+				   { .addr = adr, .flags = I2C_M_RD,
+				     .buf = answ, .len = alen } };
+	if (i2c_transfer(adap, msgs, 2) != 2) {
+		printk("tda18212dd: i2c_read error\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int i2c_write(struct i2c_adapter *adap, u8 adr, u8 *data, int len)
+{
+	struct i2c_msg msg = {.addr = adr, .flags = 0,
+			      .buf = data, .len = len};
+
+	if (i2c_transfer(adap, &msg, 1) != 1) {
+		printk("tda18212: i2c_write error\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int write_regs(struct tda_state *state,
+		      u8 SubAddr, u8 *Regs, u16 nRegs)
+{
+	u8 data[nRegs+1];
+
+	data[0] = SubAddr;
+	memcpy(data + 1, Regs, nRegs);
+	return i2c_write(state->i2c, state->adr, data, nRegs+1);
+}
+
+static int write_reg(struct tda_state *state, u8 SubAddr,u8 Reg)
+{
+	u8 msg[2] = {SubAddr, Reg};
+
+	return i2c_write(state->i2c, state->adr, msg, 2);
+}
+
+static int Read(struct tda_state *state, u8 * Regs)
+{
+	return i2c_readn(state->i2c, state->adr, Regs, REG_MAX);
+}
+
+static int update_regs(struct tda_state *state, u8 RegFrom,u8 RegTo)
+{
+	return write_regs(state, RegFrom,
+			  &state->m_Regs[RegFrom], RegTo-RegFrom+1);
+}
+
+static int update_reg(struct tda_state *state, u8 Reg)
+{
+	return write_reg(state, Reg,state->m_Regs[Reg]);
+}
+
+
+static int read_regs(struct tda_state *state,
+		    u8 SubAddr, u8 *Regs, u16 nRegs)
+{
+	return i2c_read(state->i2c, state->adr,
+			&SubAddr, 1, Regs, nRegs);
+}
+
+static int read_reg(struct tda_state *state,
+		   u8 SubAddr, u8 *Reg)
+{
+	return i2c_read(state->i2c, state->adr,
+			&SubAddr, 1, Reg, 1);
+}
+
+static int read_reg1(struct tda_state *state, u8 Reg)
+{
+	return read_reg(state, Reg, &state->m_Regs[Reg]);
+}
+
+static void init_state(struct tda_state *state)
+{
+    u32   ulIFLevelDVBC = IF_LEVEL_DVBC;
+    u32   ulIFLevelDVBT = IF_LEVEL_DVBT;
+    u32   ulPowerMeasurement = 1;
+    u32   ulLTEnable = 1;
+    u32   ulEnableFreeze = 0;
+
+    state->m_Frequency    = 0;
+    state->m_isMaster = true;
+    state->m_ID = 0;
+    state->m_LastPowerLevel = 0xFF;
+    state->m_IFLevelDVBC = (ulIFLevelDVBC & 0x07);
+    state->m_IFLevelDVBT = (ulIFLevelDVBT & 0x07);
+    state->m_bPowerMeasurement = (ulPowerMeasurement != 0);
+    state->m_bLTEnable = (ulLTEnable != 0);
+    state->m_bEnableFreeze = (ulEnableFreeze != 0);
+}
+
+static int StartCalibration(struct tda_state *state)
+{
+	int  status = 0;
+	do {
+		state->m_Regs[POWER_2] &= ~0x02; // RSSI CK = 31.25 kHz
+		CHK_ERROR(update_reg(state, POWER_2));
+
+		state->m_Regs[AGC1_2] = (state->m_Regs[AGC1_2] & ~0x60) | 0x40;    // AGC1 Do Step = 2
+		CHK_ERROR(update_reg(state, AGC1_2));        // AGC
+
+		state->m_Regs[RF_FILTER_3] = (state->m_Regs[RF_FILTER_3] & ~0xC0) | 0x40;    // AGC2 Do Step = 1
+		CHK_ERROR(update_reg(state, RF_FILTER_3));
+
+		state->m_Regs[AGCK_1] |= 0xC0; // AGCs Assym Up Step = 3      // Datasheet sets all bits to 1!
+		CHK_ERROR(update_reg(state, AGCK_1));
+
+		state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x60) | 0x40;    // AGCs Assym Do Step = 2
+		CHK_ERROR(update_reg(state, AGC5_1));
+
+		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
+		CHK_ERROR(update_reg(state, IRQ_CLEAR));
+
+		state->m_Regs[MSM_1] = 0x3B; // Set Calibration
+		state->m_Regs[MSM_2] = 0x01; // Start MSM
+		CHK_ERROR(update_regs(state, MSM_1,MSM_2));
+		state->m_Regs[MSM_2] = 0x00;
+
+	} while(0);
+	return status;
+}
+
+static int FinishCalibration(struct tda_state *state)
+{
+	int status = 0;
+	u8 RFCal_Log[12];
+
+	do {
+		u8 IRQ = 0;
+		int Timeout = 150; // 1.5 s
+		while(true) {
+			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
+			if ((IRQ & 0x80) != 0 )
+				break;
+			Timeout -= 1;
+			if (Timeout == 0) {
+				status = -1;
+				break;
+			}
+			msleep(10);
+		}
+		CHK_ERROR(status);
+
+		state->m_Regs[FLO_MAX] = 0x0A;
+		CHK_ERROR(update_reg(state, FLO_MAX));
+
+		state->m_Regs[AGC1_1] &= ~0xC0;
+		if( state->m_bLTEnable ) state->m_Regs[AGC1_1] |= 0x80;    // LTEnable
+
+		state->m_Regs[AGC1_1] |= (state->m_isMaster ? MASTER_AGC1_6_15dB : SLAVE_AGC1_6_15dB ) << 6;
+		CHK_ERROR(update_reg(state, AGC1_1));
+
+		state->m_Regs[PSM_1] &= ~0xC0;
+		state->m_Regs[PSM_1] |= (state->m_isMaster ? MASTER_PSM_AGC1 : SLAVE_PSM_AGC1 ) << 6;
+		CHK_ERROR(update_reg(state, PSM_1));
+
+		state->m_Regs[REFERENCE] |= 0x03; // XTOUT = 3
+		CHK_ERROR(update_reg(state, REFERENCE));
+
+		CHK_ERROR(read_regs(state, RFCAL_LOG_1,RFCal_Log,sizeof(RFCal_Log)));
+	} while(0);
+	return status;
+}
+
+static int PowerOn(struct tda_state *state)
+{
+	state->m_Regs[POWER_STATE_2] &= ~0x0F;
+	update_reg(state, POWER_STATE_2);
+	state->m_Regs[REFERENCE] |= 0x40;  // Digital clock source = Sigma Delta
+	update_reg(state, REFERENCE);
+	return 0;
+}
+
+static int Standby(struct tda_state *state)
+{
+	int status = 0;
+
+	do {
+		state->m_Regs[REFERENCE] &= ~0x40;  // Digital clock source = Quarz
+		CHK_ERROR(update_reg(state, REFERENCE));
+
+		state->m_Regs[POWER_STATE_2] &= ~0x0F;
+		state->m_Regs[POWER_STATE_2] |= state->m_isMaster ? 0x08 : 0x0E;
+		CHK_ERROR(update_reg(state, POWER_STATE_2));
+	} while(0);
+	return status;
+}
+
+static int attach_init(struct tda_state *state)
+{
+	int stat = 0;
+	u8 Id[2];
+	u8 PowerState = 0x00;
+
+	state->m_Standard = HF_None;
+
+	/* first read after cold reset sometimes fails on some cards,
+	   try twice */
+	stat = read_regs(state, ID_1, Id, sizeof(Id));
+	stat = read_regs(state, ID_1, Id, sizeof(Id));
+	if (stat < 0)
+		return -1;
+
+	state->m_ID = ((Id[0] & 0x7F) << 8) | Id[1];
+	state->m_isMaster = ((Id[0] & 0x80) != 0);
+	if( !state->m_isMaster )
+		state->m_bLTEnable = false;
+
+	printk("tda18212dd: ChipID %04x\n", state->m_ID);
+
+	if( state->m_ID != 18212 )
+		return -1;
+
+	stat = read_reg(state, POWER_STATE_1 ,&PowerState);
+	if (stat < 0)
+		return stat;
+
+	printk("tda18212dd: PowerState %02x\n", PowerState);
+
+	if (state->m_isMaster) {
+		if( PowerState & 0x02 ) {
+			// msleep for XTAL Calibration (on a PC this should be long done)
+			u8 IRQStatus = 0;
+			int Timeout = 10;
+
+			while(Timeout > 0) {
+				read_reg(state, IRQ_STATUS, &IRQStatus);
+				if (IRQStatus & 0x20)
+					break;
+				Timeout -= 1;
+				msleep(10);
+			}
+			if( (IRQStatus & 0x20) == 0 ) {
+				stat = -ETIMEDOUT;
+			}
+		}
+	} else {
+		write_reg(state, FLO_MAX, 0x00);
+		write_reg(state, CP_CURRENT,0x68);
+	}
+	Read(state, state->m_Regs);
+
+	PowerOn(state);
+	StartCalibration(state);
+	FinishCalibration(state);
+	Standby(state);
+	return stat;
+}
+
+static int PowerMeasurement(struct tda_state *state, u8 *pPowerLevel)
+{
+	int status = 0;
+
+	do {
+		u8 IRQ = 0;
+		int Timeout = 70; // 700 ms
+
+		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
+		CHK_ERROR(update_reg(state, IRQ_CLEAR));
+
+		state->m_Regs[MSM_1] = 0x80; // power measurement
+		state->m_Regs[MSM_2] = 0x01; // Start MSM
+		CHK_ERROR(update_regs(state, MSM_1,MSM_2));
+		state->m_Regs[MSM_2] = 0x00;
+
+		while(true) {
+			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
+			if( (IRQ & 0x80) != 0 )
+				break;
+			Timeout -= 1;
+			if( Timeout == 0 )
+			{
+				status = -1;
+				break;
+			}
+			msleep(10);
+		}
+		CHK_ERROR(status);
+
+		CHK_ERROR(read_reg1(state, INPUT_POWER_LEVEL));
+		*pPowerLevel = state->m_Regs[INPUT_POWER_LEVEL] & 0x7F;
+
+
+		if( *pPowerLevel > 110 ) *pPowerLevel = 110;
+	} while(0);
+	/* printk("PL %d\n", *pPowerLevel); */
+	return status;
+}
+
+static int SetFrequency(struct tda_state *state, u32 Frequency, enum HF_Standard Standard)
+{
+	int status = 0;
+	struct SStandardParams *StandardParams;
+	u32   f = Frequency / 1000;
+	u8 IRQ = 0;
+	int Timeout = 25; // 250 ms
+	u32 fRatio = Frequency / 16000000;
+	u32 fDelta = Frequency - fRatio * 16000000;
+
+	if( Standard < HF_DVBT_6MHZ || Standard > HF_DVBC_8MHZ )
+		return -EINVAL;
+	StandardParams = &m_StandardTable[Standard - HF_DVBT_6MHZ];
+
+	if( StandardParams->m_IFFrequency == 0 )
+		return -EINVAL;
+	state->m_Standard = HF_None;
+	state->m_Frequency = 0;
+
+	do {
+		// IF Level
+		state->m_Regs[IF_AGC] = (Standard >= HF_DVBC_6MHZ) ? state->m_IFLevelDVBC : state->m_IFLevelDVBT;
+		CHK_ERROR(update_reg(state, IF_AGC));
+
+		// ---------------------------------------------------------------------------------
+		// Standard setup
+
+		state->m_Regs[IF_1] = StandardParams->m_IF_1;
+		CHK_ERROR(update_reg(state, IF_1));
+
+		state->m_Regs[IR_MIXER_2] = (state->m_Regs[IR_MIXER_2] & ~0x03) | StandardParams->m_IR_MIXER_2;
+		CHK_ERROR(update_reg(state, IR_MIXER_2));
+
+		state->m_Regs[AGC1_1] = (state->m_Regs[AGC1_1] & ~0x0F) | StandardParams->m_AGC1_1;
+		CHK_ERROR(update_reg(state, AGC1_1));
+
+		state->m_Regs[AGC2_1] = (state->m_Regs[AGC2_1] & ~0x0F) | StandardParams->m_AGC2_1;
+		CHK_ERROR(update_reg(state, AGC2_1));
+
+		state->m_Regs[RF_AGC_1] &= ~0xEF;
+		if( Frequency < 291000000 )
+			state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_Low;
+		else
+			state->m_Regs[RF_AGC_1] |= StandardParams->m_RF_AGC_1_High;
+		CHK_ERROR(update_reg(state, RF_AGC_1));
+
+		state->m_Regs[IR_MIXER_1] = (state->m_Regs[IR_MIXER_1] & ~0x0F) | StandardParams->m_IR_MIXER_1;
+		CHK_ERROR(update_reg(state, IR_MIXER_1));
+
+		state->m_Regs[AGC5_1] = (state->m_Regs[AGC5_1] & ~0x1F) | StandardParams->m_AGC5_1;
+		CHK_ERROR(update_reg(state, AGC5_1));
+
+		state->m_Regs[AGCK_1] = (state->m_Regs[AGCK_1] & ~0x0F) | StandardParams->m_AGCK_1;
+		CHK_ERROR(update_reg(state, AGCK_1));
+
+		state->m_Regs[PSM_1] = (state->m_Regs[PSM_1] & ~0x20) | StandardParams->m_PSM_1;
+		CHK_ERROR(update_reg(state, PSM_1));
+
+		state->m_Regs[IF_FREQUENCY_1] = ( StandardParams->m_IFFrequency / 50000 );
+		CHK_ERROR(update_reg(state, IF_FREQUENCY_1));
+
+		if( state->m_isMaster && StandardParams->m_LTO_STO_immune )
+		{
+			u8 tmp;
+			u8 RF_Filter_Gain;
+
+			CHK_ERROR(read_reg(state, RF_AGC_GAIN_1,&tmp));
+			RF_Filter_Gain = (tmp & 0x30) >> 4;
+
+			state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2);
+			CHK_ERROR(update_reg(state, RF_FILTER_1));
+
+			state->m_Regs[RF_FILTER_1] |= 0x10;    // Force
+			CHK_ERROR(update_reg(state, RF_FILTER_1));
+
+			while( RF_Filter_Gain != 0 )
+			{
+				RF_Filter_Gain -= 1;
+				state->m_Regs[RF_FILTER_1] = (state->m_Regs[RF_FILTER_1] & ~0x0C) | (RF_Filter_Gain << 2);
+				CHK_ERROR(update_reg(state, RF_FILTER_1));
+				msleep(10);
+			}
+			CHK_ERROR(status);
+
+			state->m_Regs[RF_AGC_1] |=  0x08;
+			CHK_ERROR(update_reg(state, RF_AGC_1));
+		}
+
+		// ---------------------------------------------------------------------------------
+
+		state->m_Regs[IRQ_CLEAR] |= 0x80; // Reset IRQ
+		CHK_ERROR(update_reg(state, IRQ_CLEAR));
+
+		CHK_ERROR(PowerOn(state));
+
+		state->m_Regs[RF_FREQUENCY_1] = ((f >> 16) & 0xFF);
+		state->m_Regs[RF_FREQUENCY_2] = ((f >>  8) & 0xFF);
+		state->m_Regs[RF_FREQUENCY_3] = ((f      ) & 0xFF);
+		CHK_ERROR(update_regs(state, RF_FREQUENCY_1,RF_FREQUENCY_3));
+
+		state->m_Regs[MSM_1] = 0x41; // Tune
+		state->m_Regs[MSM_2] = 0x01; // Start MSM
+		CHK_ERROR(update_regs(state, MSM_1, MSM_2));
+		state->m_Regs[MSM_2] = 0x00;
+
+		while(true)
+		{
+			CHK_ERROR(read_reg(state, IRQ_STATUS, &IRQ));
+			if( (IRQ & 0x80) != 0 ) break;
+			Timeout -= 1;
+			if (Timeout == 0) {
+				status = -1;
+				break;
+			}
+			msleep(10);
+		}
+		CHK_ERROR(status);
+
+		// ---------------------------------------------------------------------------------
+
+		if( state->m_isMaster && StandardParams->m_LTO_STO_immune )
+		{
+			state->m_Regs[RF_AGC_1] &=  ~0x08;
+			CHK_ERROR(update_reg(state, RF_AGC_1));
+
+			msleep(50);
+
+			state->m_Regs[RF_FILTER_1] &= ~0x10;    // remove force
+			CHK_ERROR(update_reg(state, RF_FILTER_1));
+		}
+
+		// ---------------------------------------------------------------------------------
+		//  Spur reduction
+
+		if( Frequency < 72000000 )
+		{
+			state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
+		}
+		else if( Frequency < 104000000 )
+		{
+			state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
+		}
+		else if( Frequency < 120000000 )
+		{
+			state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
+		}
+		else
+		{
+			if( fDelta <= 8000000 )
+			{
+				if( fRatio & 1 ) state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
+				else             state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
+			}
+			else
+			{
+				if( fRatio & 1 ) state->m_Regs[REFERENCE] |= 0x40;  // Set digital clock
+				else             state->m_Regs[REFERENCE] &= ~0x40;  // Clear digital clock
+			}
+
+		}
+		CHK_ERROR(update_reg(state, REFERENCE));
+
+		if( StandardParams->m_AGC1_Freeze && state->m_bEnableFreeze )
+		{
+			u8 tmp;
+			int AGC1GainMin = 0;
+			int nSteps = 10;
+			int Step  = 0;
+
+			CHK_ERROR(read_reg(state, AGC1_2,&tmp));
+
+			if( (tmp & 0x80) == 0 )
+			{
+				state->m_Regs[AGC1_2] |= 0x80;         // Loop off
+				CHK_ERROR(update_reg(state, AGC1_2));
+				state->m_Regs[AGC1_2] |= 0x10 ;        // Force gain
+				CHK_ERROR(update_reg(state, AGC1_2));
+			}
+			// Adapt
+			if( state->m_Regs[AGC1_1] & 0x40 ) // AGC1_6_15dB set
+			{
+				AGC1GainMin = 6;
+				nSteps = 4;
+			}
+			while( Step < nSteps )
+			{
+				int Down = 0;
+				int Up = 0, i;
+				u8 AGC1_Gain;
+
+				Step = Step + 1;
+
+				for (i = 0; i < 40; i += 1) {
+					CHK_ERROR(read_reg(state, AGC_DET_OUT, &tmp));
+					Up   += (tmp & 0x02) ?  1 : -4;
+					Down += (tmp & 0x01) ? 14 : -1;
+					msleep(1);
+				}
+				CHK_ERROR(status);
+				AGC1_Gain = (state->m_Regs[AGC1_2] & 0x0F);
+				if( Up >= 15 && AGC1_Gain != 9 )
+				{
+					state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain + 1);
+					CHK_ERROR(update_reg(state, AGC1_2));
+				}
+				else if ( Down >= 10 && AGC1_Gain != AGC1GainMin )
+				{
+					state->m_Regs[AGC1_2] = ( state->m_Regs[AGC1_2] & ~0x0F ) | (AGC1_Gain - 1);
+					CHK_ERROR(update_reg(state, AGC1_2));
+				}
+				else
+				{
+					Step = nSteps;
+				}
+			}
+		}
+		else
+		{
+			state->m_Regs[AGC1_2] &= ~0x10 ;       // unforce gain
+			CHK_ERROR(update_reg(state, AGC1_2));
+			state->m_Regs[AGC1_2] &= ~0x80;         // Loop on
+			CHK_ERROR(update_reg(state, AGC1_2));
+		}
+
+		state->m_Standard = Standard;
+		state->m_Frequency = Frequency;
+
+		if( state->m_bPowerMeasurement )
+			PowerMeasurement(state, &state->m_LastPowerLevel);
+	} while(0);
+
+	return status;
+}
+
+static int sleep(struct dvb_frontend* fe)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	Standby(state);
+	return 0;
+}
+
+static int init(struct dvb_frontend* fe)
+{
+	//struct tda_state *state = fe->tuner_priv;
+	return 0;
+}
+
+static int release(struct dvb_frontend* fe)
+{
+	kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+#ifdef USE_API3
+static int set_params(struct dvb_frontend *fe,
+		      struct dvb_frontend_parameters *params)
+{
+	struct tda_state *state = fe->tuner_priv;
+	int status = 0;
+	int Standard;
+
+	state->m_Frequency = params->frequency;
+
+	if (fe->ops.info.type == FE_OFDM)
+		switch (params->u.ofdm.bandwidth) {
+		case BANDWIDTH_6_MHZ:
+			Standard = HF_DVBT_6MHZ;
+			break;
+		case BANDWIDTH_7_MHZ:
+			Standard = HF_DVBT_7MHZ;
+			break;
+		default:
+		case BANDWIDTH_8_MHZ:
+			Standard = HF_DVBT_8MHZ;
+			break;
+		}
+	else if (fe->ops.info.type == FE_QAM) {
+		Standard = HF_DVBC_8MHZ;
+	} else
+		return -EINVAL;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	SetFrequency(state, state->m_Frequency, Standard);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return status;
+}
+#else
+static int set_params(struct dvb_frontend *fe)
+{
+	struct tda_state *state = fe->tuner_priv;
+	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
+	int status = 0;
+	int Standard;
+
+	state->m_Frequency = p->frequency;
+
+	if (p->delivery_system == SYS_DVBT)
+		switch (p->bandwidth_hz) {
+		case 6000000:
+			Standard = HF_DVBT_6MHZ;
+			break;
+		case 7000000:
+			Standard = HF_DVBT_7MHZ;
+			break;
+		default:
+		case 8000000:
+			Standard = HF_DVBT_8MHZ;
+			break;
+		}
+	else if (p->delivery_system == SYS_DVBC_ANNEX_A) {
+		Standard = HF_DVBC_8MHZ;
+	} else
+		return -EINVAL;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	SetFrequency(state, state->m_Frequency, Standard);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+
+	return status;
+}
+#endif
+
+static int get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	*frequency = state->IF;
+	return 0;
+}
+
+static int get_rf_strength(struct dvb_frontend *fe, u16 *st)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	*st = state->m_LastPowerLevel;
+	return 0;
+}
+
+static int get_if(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct tda_state *state = fe->tuner_priv;
+
+	state->IF = 0;
+	if (state->m_Standard < HF_DVBT_6MHZ ||
+	    state->m_Standard > HF_DVBC_8MHZ)
+		return 0;
+	state->IF = m_StandardTable[state->m_Standard - HF_DVBT_6MHZ].m_IFFrequency;
+	*frequency = state->IF;
+	return 0;
+}
+
+static int get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	//struct tda_state *state = fe->tuner_priv;
+	//*bandwidth = priv->bandwidth;
+	return 0;
+}
+
+
+static struct dvb_tuner_ops tuner_ops = {
+	.info = {
+		.name = "NXP TDA18212",
+		.frequency_min  =  47125000,
+		.frequency_max  = 865000000,
+		.frequency_step =     62500
+	},
+	.init              = init,
+	.sleep             = sleep,
+	.set_params        = set_params,
+	.release           = release,
+	.get_frequency     = get_frequency,
+	.get_if_frequency  = get_if,
+	.get_bandwidth     = get_bandwidth,
+	.get_rf_strength   = get_rf_strength,
+};
+
+struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe,
+				       struct i2c_adapter *i2c, u8 adr)
+{
+	struct tda_state *state;
+	int stat;
+
+	state = kzalloc(sizeof(struct tda_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+	state->adr = adr;
+	state->i2c = i2c;
+	memcpy(&fe->ops.tuner_ops, &tuner_ops, sizeof(struct dvb_tuner_ops));
+	init_state(state);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	stat = attach_init(state);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 0);
+	if (stat < 0) {
+		kfree(state);
+		return 0;
+	}
+	fe->tuner_priv = state;
+	return fe;
+}
+
+EXPORT_SYMBOL_GPL(tda18212dd_attach);
+MODULE_DESCRIPTION("TDA18212 driver");
+MODULE_AUTHOR("DD");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -Naur linux-3.6.8/drivers/media/dvb/frontends/tda18212dd.h linux-3.6.8.patch/drivers/media/dvb/frontends/tda18212dd.h
--- linux-3.6.8/drivers/media/dvb/frontends/tda18212dd.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/frontends/tda18212dd.h	2012-12-03 08:41:17.000000000 +0100
@@ -0,0 +1,5 @@
+#ifndef _TDA18212DD_H_
+#define _TDA18212DD_H_
+struct dvb_frontend *tda18212dd_attach(struct dvb_frontend *fe,
+				       struct i2c_adapter *i2c, u8 adr);
+#endif
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/Kconfig linux-3.6.8.patch/drivers/media/dvb/ngene/Kconfig
--- linux-3.6.8/drivers/media/dvb/ngene/Kconfig	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/Kconfig	2012-12-03 08:41:17.000000000 +0100
@@ -1,12 +1,15 @@
 config DVB_NGENE
 	tristate "Micronas nGene support"
 	depends on DVB_CORE && PCI && I2C
+	select DVB_CXD2099
 	select DVB_LNBP21 if !DVB_FE_CUSTOMISE
 	select DVB_STV6110x if !DVB_FE_CUSTOMISE
 	select DVB_STV090x if !DVB_FE_CUSTOMISE
 	select DVB_LGDT330X if !DVB_FE_CUSTOMISE
 	select DVB_DRXK if !DVB_FE_CUSTOMISE
 	select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+	select DVB_STV0367DD if !DVB_FE_CUSTOMISE
+	select DVB_TDA18212DD if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
 	---help---
 	  Support for Micronas PCI express cards with nGene bridge.
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/Makefile linux-3.6.8.patch/drivers/media/dvb/ngene/Makefile
--- linux-3.6.8/drivers/media/dvb/ngene/Makefile	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/Makefile	2012-12-03 08:58:39.951117965 +0100
@@ -2,7 +2,8 @@
 # Makefile for the nGene device driver
 #
 
-ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o
+ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-av.o \
+	ngene-eeprom.o ngene-dvb.o
 
 obj-$(CONFIG_DVB_NGENE) += ngene.o
 
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/ngene-av.c linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-av.c
--- linux-3.6.8/drivers/media/dvb/ngene/ngene-av.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-av.c	2012-12-03 09:06:17.133472933 +0100
@@ -0,0 +1,348 @@
+/*
+ * ngene-av.c: nGene PCIe bridge driver - DVB video/audio support
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
+ *                         Modifications for new nGene firmware,
+ *                         support for EEPROM-copying,
+ *                         support for new dual DVB-S2 card prototype
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* This file provides the support functions for DVB audio/video devices
+   (/dev/dvb/adapter0/[video|audio]), not to be confused with V4L2 support */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <asm/div64.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/version.h>
+#include <linux/byteorder/generic.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+
+#include "ngene.h"
+
+#if 0
+
+static void *ain_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
+{
+	struct ngene_channel *chan = priv;
+	struct ngene *dev = chan->dev;
+
+	if (dvb_ringbuffer_free(&dev->ain_rbuf) >= len) {
+		dvb_ringbuffer_write(&dev->ain_rbuf, buf, len);
+		wake_up_interruptible(&dev->ain_rbuf.queue);
+	} else
+		printk(KERN_INFO DEVICE_NAME ": Dropped ain packet.\n");
+
+	return 0;
+}
+
+static void *vcap_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
+{
+
+	struct ngene_channel *chan = priv;
+	struct ngene *dev = chan->dev;
+
+	if (len >= 1920 * 1080)
+		len = 1920 * 1080;
+	if (dvb_ringbuffer_free(&dev->vin_rbuf) >= len) {
+		dvb_ringbuffer_write(&dev->vin_rbuf, buf, len);
+		wake_up_interruptible(&dev->vin_rbuf.queue);
+	} else {
+		;/*printk(KERN_INFO DEVICE_NAME ": Dropped vcap packet.\n"); */
+	}
+	return 0;
+}
+
+static ssize_t audio_write(struct file *file,
+			   const char *buf, size_t count, loff_t *ppos)
+{
+	return -EINVAL;
+}
+
+ssize_t audio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	int left;
+	int avail;
+
+	left = count;
+	while (left) {
+		if (wait_event_interruptible(
+				dev->ain_rbuf.queue,
+				dvb_ringbuffer_avail(&dev->ain_rbuf) > 0) < 0)
+			return -EAGAIN;
+		avail = dvb_ringbuffer_avail(&dev->ain_rbuf);
+		if (avail > left)
+			avail = left;
+		dvb_ringbuffer_read_user(&dev->ain_rbuf, buf, avail);
+		left -= avail;
+		buf += avail;
+	}
+	return count;
+}
+
+static int audio_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	struct ngene_channel *chan2 = &chan->dev->channel[2];
+	int ret;
+
+	ret = dvb_generic_open(inode, file);
+	if (ret < 0)
+		return ret;
+	dvb_ringbuffer_flush(&dev->ain_rbuf);
+
+	chan2->Capture1Length = MAX_AUDIO_BUFFER_SIZE;
+	chan2->pBufferExchange = ain_exchange;
+	ngene_command_stream_control(chan2->dev, chan2->number, 0x80,
+				     SMODE_AUDIO_CAPTURE, 0);
+	return ret;
+}
+
+static int audio_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	struct ngene_channel *chan2 = &chan->dev->channel[2];
+
+	ngene_command_stream_control(dev, 2, 0, 0, 0);
+	chan2->pBufferExchange = 0;
+
+	return dvb_generic_release(inode, file);
+}
+
+static const struct file_operations audio_fops = {
+	.owner   = THIS_MODULE,
+	.read    = audio_read,
+	.write   = audio_write,
+	.open    = audio_open,
+	.release = audio_release,
+};
+
+static struct dvb_device dvbdev_audio = {
+	.priv    = 0,
+	.readers = -1,
+	.writers = 1,
+	.users   = 1,
+	.fops    = &audio_fops,
+};
+
+static int video_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	struct ngene_channel *chan0 = &chan->dev->channel[0];
+	int ret;
+
+	ret = dvb_generic_open(inode, file);
+	if (ret < 0)
+		return ret;
+	if ((file->f_flags & O_ACCMODE) != O_RDONLY)
+		return ret;
+	dvb_ringbuffer_flush(&dev->vin_rbuf);
+
+	chan0->nBytesPerLine = 1920 * 2;
+	chan0->nLines = 540;
+	chan0->Capture1Length = 1920 * 2 * 540;
+	chan0->pBufferExchange = vcap_exchange;
+	chan0->itumode = 2;
+	ngene_command_stream_control(chan0->dev, chan0->number,
+				     0x80, SMODE_VIDEO_CAPTURE, 0);
+	return ret;
+}
+
+static int video_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	struct ngene_channel *chan0 = &chan->dev->channel[0];
+
+	ngene_command_stream_control(dev, 0, 0, 0, 0);
+	chan0->pBufferExchange = 0;
+
+	return dvb_generic_release(inode, file);
+}
+
+static ssize_t video_write(struct file *file,
+			   const char *buf, size_t count, loff_t *ppos)
+{
+	return -EINVAL;
+}
+
+ssize_t video_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	int left, avail;
+
+	left = count;
+	while (left) {
+		if (wait_event_interruptible(
+				dev->vin_rbuf.queue,
+				dvb_ringbuffer_avail(&dev->vin_rbuf) > 0) < 0)
+			return -EAGAIN;
+		avail = dvb_ringbuffer_avail(&dev->vin_rbuf);
+		if (avail > left)
+			avail = left;
+		dvb_ringbuffer_read_user(&dev->vin_rbuf, buf, avail);
+		left -= avail;
+		buf += avail;
+	}
+	return count;
+}
+
+/* Why is this not exported from dvb_core ?!?! */
+
+static int dvb_usercopy2(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 */
+	err = func(inode, file, cmd, parg);
+	if (err == -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 video_do_ioctl(struct inode *inode, struct file *file,
+			  unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	int ret = 0;
+	unsigned long arg = (unsigned long)parg;
+
+	switch (cmd) {
+	case VIDEO_SET_STREAMTYPE:
+		switch (arg) {
+		case VIDEO_CAP_MPEG2:
+			/* printk(KERN_INFO DEVICE_NAME ": setting MPEG2\n"); */
+			send_cli(dev, "vdec mpeg2\n");
+			break;
+		case VIDEO_CAP_AVC:
+			/* printk(KERN_INFO DEVICE_NAME ": setting H264\n"); */
+			send_cli(dev, "vdec h264\n");
+			break;
+		case VIDEO_CAP_VC1:
+			/* printk(KERN_INFO DEVICE_NAME ": setting VC1\n"); */
+			send_cli(dev, "vdec vc1\n");
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		return -EINVAL;
+	}
+	return ret;
+}
+
+static int video_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	return dvb_usercopy2(inode, file, cmd, arg, video_do_ioctl);
+}
+
+static const struct file_operations video_fops = {
+	.owner   = THIS_MODULE,
+	.read    = video_read,
+	.write   = video_write,
+	.open    = video_open,
+	.release = video_release,
+	.ioctl   = video_ioctl,
+};
+
+static struct dvb_device dvbdev_video = {
+	.priv    = 0,
+	.readers = -1,
+	.writers = 1,
+	.users   = -1,
+	.fops    = &video_fops,
+};
+#endif
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/ngene-cards.c linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-cards.c
--- linux-3.6.8/drivers/media/dvb/ngene/ngene-cards.c	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-cards.c	2012-12-03 09:06:30.239367796 +0100
@@ -42,6 +42,8 @@
 #include "mt2131.h"
 #include "tda18271c2dd.h"
 #include "drxk.h"
+#include "tda18212dd.h"
+#include "stv0367dd.h"
 
 
 /****************************************************************************/
@@ -84,8 +86,98 @@
 	return 0;
 }
 
+#if 0
+static int tuner_attach_mt2060(struct ngene_channel *chan)
+{
+	struct ngene *dev = chan->dev;
+	void *tconf = dev->card_info->tuner_config[chan->number];
+	u8 drxa = dev->card_info->demoda[chan->number];
+	struct dvb_frontend *fe = chan->fe, *fe2;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+	fe->misc_priv = chan;
+#else
+	fe->sec_priv = chan;
+#endif
+	fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl;
+
+	dev->card_info->gate_ctrl(fe, 1);
+	fe2 = mt2060_attach(fe, &chan->i2c_adapter, tconf, 1220);
+	dev->card_info->gate_ctrl(fe, 0);
+
+	i2c_write_register(&chan->i2c_adapter, drxa, 3, 4);
+	write_demod(&chan->i2c_adapter, drxa, 0x1012, 15);
+	write_demod(&chan->i2c_adapter, drxa, 0x1007, 0xc27);
+	write_demod(&chan->i2c_adapter, drxa, 0x0020, 0x003);
+
+	return fe2 ? 0 : -ENODEV;
+}
+
+static int tuner_attach_xc3028(struct ngene_channel *chan)
+{
+	struct ngene *dev = chan->dev;
+	void *tconf = dev->card_info->tuner_config[chan->number];
+	struct dvb_frontend *fe = chan->fe, *fe2;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+	fe->misc_priv = chan;
+#else
+	fe->sec_priv = chan;
+#endif
+	fe->ops.i2c_gate_ctrl = dev->card_info->gate_ctrl;
+
+	dev->card_info->gate_ctrl(fe, 1);
+	fe2 = xc3028_attach(fe, &chan->i2c_adapter, tconf);
+	dev->card_info->gate_ctrl(fe, 0);
+
+	/*chan->fe->ops.tuner_ops.set_frequency(chan->fe,231250000);*/
+
+	return fe2 ? 0 : -ENODEV;
+}
+
+static int demod_attach_drxd(struct ngene_channel *chan)
+{
+	void *feconf = chan->dev->card_info->fe_config[chan->number];
+
+	chan->fe = drxd_attach(feconf,
+			       chan, &chan->i2c_adapter,
+			       &chan->dev->pci_dev->dev);
+	return (chan->fe) ? 0 : -ENODEV;
+}
+
+static int demod_attach_drxh(struct ngene_channel *chan)
+{
+	void *feconf = chan->dev->card_info->fe_config[chan->number];
+
+	chan->fe = drxh_attach(feconf, chan,
+			       &chan->i2c_adapter, &chan->dev->pci_dev->dev);
+	return (chan->fe) ? 0 : -ENODEV;
+}
+
+static int demod_attach_stb0899(struct ngene_channel *chan)
+{
+	void *feconf = chan->dev->card_info->fe_config[chan->number];
+
+	chan->fe = stb0899_attach(feconf,
+				  chan, &chan->i2c_adapter,
+				  &chan->dev->pci_dev->dev);
+	if (chan->fe) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
+		chan->set_tone = chan->fe->ops->set_tone;
+		chan->fe->ops->set_tone = lnbh21_set_tone;
+		chan->fe->ops->set_voltage = lnbh21_set_voltage;
+#else
+		chan->set_tone = chan->fe->ops.set_tone;
+		chan->fe->ops.set_tone = lnbh21_set_tone;
+		chan->fe->ops.set_voltage = lnbh21_set_voltage;
+#endif
+	}
+
+	return (chan->fe) ? 0 : -ENODEV;
+}
+#endif
 
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct ngene_channel *chan = fe->sec_priv;
 	int status;
@@ -119,12 +211,29 @@
 	return 0;
 }
 
+static int tuner_attach_tda18212dd(struct ngene_channel *chan)
+{
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+
+	i2c = &chan->dev->channel[0].i2c_adapter;
+	fe = dvb_attach(tda18212dd_attach, chan->fe, i2c,
+			(chan->number & 1) ? 0x63 : 0x60);
+	if (!fe) {
+		printk(KERN_ERR "No TDA18212 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
 static int tuner_attach_probe(struct ngene_channel *chan)
 {
 	if (chan->demod_type == 0)
 		return tuner_attach_stv6110(chan);
 	if (chan->demod_type == 1)
 		return tuner_attach_tda18271(chan);
+	if (chan->demod_type == 2)
+		return tuner_attach_tda18212dd(chan);
 	return -EINVAL;
 }
 
@@ -216,18 +325,51 @@
 	struct drxk_config config;
 
 	memset(&config, 0, sizeof(config));
-	config.microcode_name = "drxk_a3.mc";
-	config.qam_demod_parameter_count = 4;
 	config.adr = 0x29 + (chan->number ^ 2);
+	config.microcode_name = "drxk_a3.mc";
 
+#ifdef USE_API3
+	chan->fe = dvb_attach(drxk_attach, &config, i2c, &chan->fe2);
+#else
 	chan->fe = dvb_attach(drxk_attach, &config, i2c);
+#endif
 	if (!chan->fe) {
 		printk(KERN_ERR "No DRXK found!\n");
 		return -ENODEV;
 	}
 	chan->fe->sec_priv = chan;
 	chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
-	chan->fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+	chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
+	return 0;
+}
+
+static int port_has_stv0367(struct i2c_adapter *i2c, int port)
+{
+	u8 val;
+
+	if (i2c_read_reg16(i2c, 0x1c + (port ^ 1), 0xf000, &val) < 0)
+		return 0;
+	if (val != 0x60)
+		return 0;
+	return 1;
+}
+
+static int demod_attach_stv0367dd(struct ngene_channel *chan,
+				  struct i2c_adapter *i2c)
+{
+	struct stv0367_cfg cfg;
+
+	memset(&cfg, 0, sizeof cfg);
+	cfg.adr = 0x1c + (chan->number ^ 1);
+
+	chan->fe = dvb_attach(stv0367_attach, i2c, &cfg, &chan->fe2);
+	if (!chan->fe) {
+		printk(KERN_ERR "No stv0367 found!\n");
+		return -ENODEV;
+	}
+	chan->fe->sec_priv = chan;
+	chan->gate_ctrl = chan->fe->ops.i2c_gate_ctrl;
+	chan->fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
 	return 0;
 }
 
@@ -277,6 +419,9 @@
 	} else if (port_has_drxk(i2c, chan->number^2)) {
 		chan->demod_type = 1;
 		demod_attach_drxk(chan, i2c);
+	} else if (port_has_stv0367(i2c, chan->number)) {
+		chan->demod_type = 2;
+		demod_attach_stv0367dd(chan, i2c);
 	} else {
 		printk(KERN_ERR "No demod found on chan %d\n", chan->number);
 		return -ENODEV;
@@ -317,6 +462,136 @@
 /* Switch control (I2C gates, etc.) *****************************************/
 /****************************************************************************/
 
+#if 0
+static int avf_output(struct ngene_channel *chan, int state)
+{
+	if (chan->dev->card_info->avf[chan->number])
+		i2c_write_register(&chan->i2c_adapter,
+				   chan->dev->card_info->avf[chan->number],
+				   0xf2, state ? 0x89 : 0x80);
+	return 0;
+}
+
+/* Viper expander: sw11,sw12,sw21,sw22,i2csw1,i2csw2,tsen1,tsen2 */
+
+static int exp_set(struct ngene *dev)
+{
+	return i2c_write(&dev->channel[0].i2c_adapter,
+			 dev->card_info->exp, dev->exp_val);
+}
+
+static int exp_init(struct ngene *dev)
+{
+	if (!dev->card_info->exp)
+		return 0;
+	dev->exp_val = dev->card_info->exp_init;
+	return exp_set(dev);
+}
+
+static int exp_set_bit(struct ngene *dev, int bit, int val)
+{
+	if (val)
+		set_bit(bit, &dev->exp_val);
+	else
+		clear_bit(bit, &dev->exp_val);
+	return exp_set(dev);
+}
+
+static int viper_switch_ctrl(struct ngene_channel *chan, int type, int val)
+{
+	switch (type) {
+	case 0: /* I2C tuner gate on/off */
+		return exp_set_bit(chan->dev, 4 + chan->number, val);
+	case 1: /* Stream: 0=TS 1=ITU */
+		avf_output(chan, val);
+		return exp_set_bit(chan->dev, 6 + chan->number, val);
+	case 2: /* Input: 0=digital 1=analog antenna input */
+		exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1);
+		exp_set_bit(chan->dev, 1 + chan->number * 2, val ? 1 : 0);
+		break;
+	}
+	return 0;
+}
+
+static int viper_switch_ctrl2(struct ngene_channel *chan, int type, int val)
+{
+	switch (type) {
+	case 0: /* I2C tuner gate on/off */
+		return exp_set_bit(chan->dev, 4 + chan->number, val);
+	case 1: /* Stream: 0=TS 1=ITU */
+		avf_output(chan, val);
+		return exp_set_bit(chan->dev, 6 + chan->number, val);
+	case 2: /* Input: 0=digital 1=analog antenna input */
+		exp_set_bit(chan->dev, 0 + chan->number * 2, val ? 0 : 1);
+		exp_set_bit(chan->dev, 1 + chan->number * 2, 0);
+		break;
+	}
+	return 0;
+}
+
+static int viper_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+	struct ngene_channel *chan = fe->misc_priv;
+#else /* Why is there no misc_priv available anymore !?!?! */
+	/* Well, just abuse sec :-) */
+	struct ngene_channel *chan = fe->sec_priv;
+#endif
+	struct ngene *dev = chan->dev;
+
+	return dev->card_info->switch_ctrl(chan, 0, enable);
+}
+
+static int python_switch_ctrl(struct ngene_channel *chan, int type, int val)
+{
+	switch (type) {
+	case 0: /* I2C tuner gate on/off */
+		if (chan->number > 1)
+			return -EINVAL;
+		return ngene_command_gpio_set(chan->dev, 3 + chan->number, val);
+	case 1: /* Stream: 0=TS 1=ITU */
+		avf_output(chan, val);
+		return 0;
+	}
+	return 0;
+}
+
+static int viper_reset_xc(struct dvb_frontend *fe)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+	struct ngene_channel *chan = fe->misc_priv;
+#else
+	struct ngene_channel *chan = fe->sec_priv;
+#endif
+	struct ngene *dev = chan->dev;
+
+	printk(KERN_INFO DEVICE_NAME ": Reset XC3028\n");
+
+	if (chan->number > 1)
+		return -EINVAL;
+
+	ngene_command_gpio_set(dev, 3 + chan->number, 0);
+	msleep(150);
+	ngene_command_gpio_set(dev, 3 + chan->number, 1);
+	return 0;
+}
+
+static int python_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
+	struct ngene_channel *chan = fe->misc_priv;
+#else /* Why is there no misc_priv available anymore !?!?! */
+	struct ngene_channel *chan = fe->sec_priv;
+#endif
+	struct ngene *dev = chan->dev;
+
+	if (chan->number == 0)
+		return ngene_command_gpio_set(dev, 3, enable);
+	if (chan->number == 1)
+		return ngene_command_gpio_set(dev, 4, enable);
+	return -EINVAL;
+}
+#endif
 
 static struct stv090x_config fe_cineS2 = {
 	.device         = STV0900,
@@ -466,6 +741,323 @@
 
 /****************************************************************************/
 
+#if 0
+static struct drxd_config fe_terratec_dvbt_0 = {
+	.index          = 0,
+	.demod_address  = 0x70,
+	.demod_revision = 0xa2,
+	.demoda_address = 0x00,
+	.pll_address    = 0x60,
+	.pll_type       = DRXD_PLL_DTT7520X,
+	.clock          = 20000,
+	.pll_set        = ngene_pll_set_th_dtt7520x,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct drxd_config fe_terratec_dvbt_1 = {
+	.index          = 1,
+	.demod_address  = 0x71,
+	.demod_revision = 0xa2,
+	.demoda_address = 0x00,
+	.pll_address    = 0x60,
+	.pll_type       = DRXD_PLL_DTT7520X,
+	.clock          = 20000,
+	.pll_set        = ngene_pll_set_th_dtt7520x,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct ngene_info ngene_info_terratec = {
+	.type           = NGENE_TERRATEC,
+	.name           = "Terratec Integra/Cinergy2400i Dual DVB-T",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach   = {demod_attach_drxd, demod_attach_drxd},
+	.fe_config      = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1},
+	.i2c_access     = 1,
+};
+
+/****************************************************************************/
+
+static struct mt2060_config tuner_python_0 = {
+	.i2c_address    = 0x60,
+	.clock_out      = 3,
+	.input          = 0
+};
+
+static struct mt2060_config tuner_python_1 = {
+	.i2c_address    = 0x61,
+	.clock_out      = 3,
+	.input          = 1
+};
+
+static struct drxd_config fe_python_0 = {
+	.index          = 0,
+	.demod_address  = 0x71,
+	.demod_revision = 0xb1,
+	.demoda_address = 0x41,
+	.clock          = 16000,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct drxd_config fe_python_1 = {
+	.index          = 1,
+	.demod_address  = 0x70,
+	.demod_revision = 0xb1,
+	.demoda_address = 0x45,
+	.clock          = 16000,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct ngene_info ngene_info_python = {
+	.type           = NGENE_PYTHON,
+	.name           = "Micronas MicPython/Hedgehog Dual DVB-T",
+	.io_type        = {NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_AIN, NGENE_IO_AIN},
+	.demod_attach   = {demod_attach_drxd, demod_attach_drxd},
+	.tuner_attach   = {tuner_attach_mt2060, tuner_attach_mt2060},
+	.fe_config      = {&fe_python_0, &fe_python_1},
+	.tuner_config   = {&tuner_python_0, &tuner_python_1},
+	.avf            = {0x43, 0x47},
+	.msp            = {0x40, 0x42},
+	.demoda         = {0x41, 0x45},
+	.gate_ctrl      = python_gate_ctrl,
+	.switch_ctrl    = python_switch_ctrl,
+};
+
+/****************************************************************************/
+
+static struct drxd_config fe_appb_dvbt_0 = {
+	.index          = 0,
+	.demod_address  = 0x71,
+	.demod_revision = 0xa2,
+	.demoda_address = 0x41,
+	.pll_address    = 0x63,
+	.pll_type       = DRXD_PLL_MT3X0823,
+	.clock          = 20000,
+	.pll_set        = ngene_pll_set_mt_3x0823,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct drxd_config fe_appb_dvbt_1 = {
+	.index          = 1,
+	.demod_address  = 0x70,
+	.demod_revision = 0xa2,
+	.demoda_address = 0x45,
+	.pll_address    = 0x60,
+	.pll_type       = DRXD_PLL_MT3X0823,
+	.clock          = 20000,
+	.pll_set        = ngene_pll_set_mt_3x0823,
+	.osc_deviation  = osc_deviation,
+};
+
+static struct ngene_info ngene_info_appboard = {
+	.type           = NGENE_APP,
+	.name           = "Micronas Application Board Dual DVB-T",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach   = {demod_attach_drxd, demod_attach_drxd},
+	.fe_config      = {&fe_appb_dvbt_0, &fe_appb_dvbt_1},
+	.avf            = {0x43, 0x47},
+};
+
+static struct ngene_info ngene_info_appboard_ntsc = {
+	.type           = NGENE_APP,
+	.name           = "Micronas Application Board Dual DVB-T",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach   = {demod_attach_drxd, demod_attach_drxd},
+	.fe_config      = {&fe_appb_dvbt_0, &fe_appb_dvbt_1},
+	.avf            = {0x43, 0x47},
+	.ntsc           = 1,
+};
+
+/****************************************************************************/
+
+static struct stb0899_config fe_sidewinder_0 = {
+	.demod_address  = 0x68,
+	.pll_address    = 0x63,
+};
+
+static struct stb0899_config fe_sidewinder_1 = {
+	.demod_address  = 0x6b,
+	.pll_address    = 0x60,
+};
+
+static struct ngene_info ngene_info_sidewinder = {
+	.type           = NGENE_SIDEWINDER,
+	.name           = "Micronas MicSquirrel/Sidewinder Dual DVB-S2",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach   = {demod_attach_stb0899, demod_attach_stb0899},
+	.fe_config      = {&fe_sidewinder_0, &fe_sidewinder_1},
+	.lnb            = {0x0b, 0x08},
+};
+
+/****************************************************************************/
+/* Yet unnamed S2 card with dual DVB-S2 demod                               */
+/****************************************************************************/
+
+static struct stv0900_config fe_s2_0 = {
+	.addr           = 0x68,
+	.pll            = 0x63,
+	.pll_type       = 0,
+	.nr             = 0,
+};
+
+static struct stv0900_config fe_s2_1 = {
+	.addr           = 0x68,
+	.pll            = 0x60,
+	.pll_type       = 0,
+	.nr             = 1,
+};
+
+static struct ngene_info ngene_info_s2 = {
+	.type           = NGENE_SIDEWINDER,
+	.name           = "S2",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN,
+			   NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach   = {demod_attach_stv0900, demod_attach_stv0900},
+	.fe_config      = {&fe_s2_0, &fe_s2_1},
+	.lnb            = {0x0b, 0x08},
+	.tsf            = {3, 3},
+	.fw_version     = 15,
+};
+
+static struct stv0900_config fe_s2b_0 = {
+	.addr           = 0x68,
+	.pll            = 0x60,
+	.pll_type       = 0x10,
+	.nr             = 0,
+};
+
+static struct stv0900_config fe_s2b_1 = {
+	.addr           = 0x68,
+	.pll            = 0x63,
+	.pll_type       = 0x10,
+	.nr             = 1,
+};
+
+static struct ngene_info ngene_info_s2_b = {
+	.type           = NGENE_SIDEWINDER,
+	.name           = "S2 V2",
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN,
+			   NGENE_IO_TSIN, NGENE_IO_TSIN},
+	.demod_attach   = {demod_attach_stv0900, demod_attach_stv0900},
+	.fe_config      = {&fe_s2b_0, &fe_s2b_1},
+	.lnb            = {0x0b, 0x08},
+	.tsf            = {3, 3},
+	.fw_version     = 17,
+};
+
+/****************************************************************************/
+
+static struct xc3028_config tuner_viper_0 = {
+	.adr            = 0x61,
+	.reset          = viper_reset_xc
+};
+
+static struct xc3028_config tuner_viper_1 = {
+	.adr            = 0x64,
+	.reset          = viper_reset_xc
+};
+
+static struct drxh_config fe_viper_h_0 = {.adr = 0x2b};
+
+static struct drxh_config fe_viper_h_1 = {.adr = 0x29};
+
+static struct drxh_config fe_viper_l_0 = {.adr = 0x2b, .type = 3931};
+
+static struct drxh_config fe_viper_l_1 = {.adr = 0x29, .type = 3931};
+
+static struct ngene_info ngene_info_viper_v1 = {
+	.type           = NGENE_VIPER,
+	.name           = "Micronas MicViper Dual ATSC DRXH",
+	.io_type        = {NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_AIN, NGENE_IO_AIN},
+	.demod_attach   = {demod_attach_drxh, demod_attach_drxh},
+	.fe_config      = {&fe_viper_h_0, &fe_viper_h_1},
+	.tuner_config   = {&tuner_viper_0, &tuner_viper_1},
+	.tuner_attach   = {tuner_attach_xc3028, tuner_attach_xc3028},
+	.avf            = {0x43, 0x47},
+	.msp            = {0x40, 0x42},
+	.exp            = 0x20,
+	.exp_init       = 0xf5,
+	.gate_ctrl      = viper_gate_ctrl,
+	.switch_ctrl    = viper_switch_ctrl,
+	.tsf            = {2, 2},
+};
+
+static struct ngene_info ngene_info_viper_v2 = {
+	.type           = NGENE_VIPER,
+	.name           = "Micronas MicViper Dual ATSC DRXL",
+	.io_type        = {NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_AIN, NGENE_IO_AIN},
+	.demod_attach   = {demod_attach_drxh, demod_attach_drxh},
+	.fe_config      = {&fe_viper_l_0, &fe_viper_l_1},
+	.tuner_config   = {&tuner_viper_0, &tuner_viper_1},
+	.tuner_attach   = {tuner_attach_xc3028, tuner_attach_xc3028},
+	.avf            = {0x43, 0x47},
+	.msp            = {0x40, 0x42},
+	.exp            = 0x38,
+	.exp_init       = 0xf5,
+	.gate_ctrl      = viper_gate_ctrl,
+	.switch_ctrl    = viper_switch_ctrl,
+	.tsf            = {2, 2},
+};
+
+/****************************************************************************/
+
+static struct ngene_info ngene_info_vbox_v1 = {
+	.type           = NGENE_VBOX_V1,
+	.name           = "VBox Cat's Eye 164E",
+	.io_type        = {NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_AIN, NGENE_IO_AIN},
+	.demod_attach   = {demod_attach_drxh, demod_attach_drxh},
+	.fe_config      = {&fe_viper_h_0, &fe_viper_h_1},
+	.tuner_config   = {&tuner_viper_0, &tuner_viper_1},
+	.tuner_attach   = {tuner_attach_xc3028, tuner_attach_xc3028},
+	.avf            = {0x43, 0x47},
+	.msp            = {0x40, 0x42},
+	.exp            = 0x20,
+	.exp_init       = 0xf5,
+	.gate_ctrl      = viper_gate_ctrl,
+	.switch_ctrl    = viper_switch_ctrl,
+	.tsf            = {2, 2},
+};
+
+/****************************************************************************/
+
+static struct ngene_info ngene_info_vbox_v2 = {
+	.type           = NGENE_VBOX_V2,
+	.name           = "VBox Cat's Eye 164E",
+	.io_type        = {NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_TSIN | NGENE_IO_TV,
+			   NGENE_IO_AIN, NGENE_IO_AIN},
+	.demod_attach   = {demod_attach_drxh, demod_attach_drxh},
+	.fe_config      = {&fe_viper_h_0, &fe_viper_h_1},
+	.tuner_config   = {&tuner_viper_0, &tuner_viper_1},
+	.tuner_attach   = {tuner_attach_xc3028, tuner_attach_xc3028},
+	.avf            = {0x43, 0x47},
+	.msp            = {0x40, 0x42},
+	.exp            = 0x20,
+	.exp_init       = 0xf5,
+	.gate_ctrl      = viper_gate_ctrl,
+	.switch_ctrl    = viper_switch_ctrl2,
+	.tsf            = {2, 2},
+};
+
+/****************************************************************************/
+
+static struct ngene_info ngene_info_racer = {
+	.type           = NGENE_RACER,
+	.name           = "Micronas MicRacer HDTV Decoder Card",
+	.io_type        = {NGENE_IO_HDTV, NGENE_IO_NONE,
+			   NGENE_IO_AIN, NGENE_IO_NONE,
+			   NGENE_IO_TSOUT},
+	.i2s            = {0, 0, 1, 0},
+	.fw_version     = 17,
+};
+#endif
 
 
 /****************************************************************************/
@@ -480,6 +1072,8 @@
 /****************************************************************************/
 
 static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
+	NGENE_ID(0x18c3, 0xab04, ngene_info_cineS2),
+	NGENE_ID(0x18c3, 0xab05, ngene_info_cineS2v5),
 	NGENE_ID(0x18c3, 0xabc3, ngene_info_cineS2),
 	NGENE_ID(0x18c3, 0xabc4, ngene_info_cineS2),
 	NGENE_ID(0x18c3, 0xdb01, ngene_info_satixS2),
@@ -488,6 +1082,32 @@
 	NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
 	NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
 	NGENE_ID(0x1461, 0x062e, ngene_info_m780),
+#if 0 /* not (yet?) supported */
+	NGENE_ID(0x18c3, 0x0000, ngene_info_appboard),
+	NGENE_ID(0x18c3, 0x0004, ngene_info_appboard),
+	NGENE_ID(0x18c3, 0x8011, ngene_info_appboard),
+	NGENE_ID(0x18c3, 0x8015, ngene_info_appboard_ntsc),
+	NGENE_ID(0x153b, 0x1167, ngene_info_terratec),
+	NGENE_ID(0x18c3, 0x0030, ngene_info_python),
+	NGENE_ID(0x18c3, 0x0052, ngene_info_sidewinder),
+	NGENE_ID(0x18c3, 0x8f00, ngene_info_racer),
+	NGENE_ID(0x18c3, 0x0041, ngene_info_viper_v1),
+	NGENE_ID(0x18c3, 0x0042, ngene_info_viper_v2),
+	NGENE_ID(0x14f3, 0x0041, ngene_info_vbox_v1),
+	NGENE_ID(0x14f3, 0x0043, ngene_info_vbox_v2),
+	NGENE_ID(0x18c3, 0xabcd, ngene_info_s2),
+	NGENE_ID(0x18c3, 0xabc2, ngene_info_s2_b),
+	NGENE_ID(0x18c3, 0xabc3, ngene_info_s2_b),
+	NGENE_ID(0x18c3, 0x0001, ngene_info_appboard),
+	NGENE_ID(0x18c3, 0x0005, ngene_info_appboard),
+	NGENE_ID(0x18c3, 0x0009, ngene_info_appboard_atsc),
+	NGENE_ID(0x18c3, 0x000b, ngene_info_appboard_atsc),
+	NGENE_ID(0x18c3, 0x0010, ngene_info_shrek_50_fp),
+	NGENE_ID(0x18c3, 0x0011, ngene_info_shrek_60_fp),
+	NGENE_ID(0x18c3, 0x0012, ngene_info_shrek_50),
+	NGENE_ID(0x18c3, 0x0013, ngene_info_shrek_60),
+	NGENE_ID(0x18c3, 0x0000, ngene_info_hognose),
+#endif
 	{0}
 };
 MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/ngene-core.c linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-core.c
--- linux-3.6.8/drivers/media/dvb/ngene/ngene-core.c	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-core.c	2012-12-03 09:06:06.341559356 +0100
@@ -86,6 +86,14 @@
 		if ((Event.UARTStatus & 0x02) && (dev->RxEventNotify))
 			dev->RxEventNotify(dev, Event.TimeStamp,
 					   Event.RXCharacter);
+#if 0
+		if ((Event.GPIOStatus & 0x80) && (dev->Gpio2EventNotify))
+			dev->Gpio2EventNotify(dev, Event.TimeStamp,
+					      Event.GPIOStatus & 0x1f);
+		if ((Event.GPIOStatus & 0x40) && (dev->Gpio3EventNotify))
+			dev->Gpio3EventNotify(dev, Event.TimeStamp,
+					      Event.GPIOStatus & 0x1f);
+#endif
 	}
 }
 
@@ -214,6 +222,13 @@
 		u8 nextWriteIndex =
 			(dev->EventQueueWriteIndex + 1) &
 			(EVENT_QUEUE_SIZE - 1);
+#if 0
+		printk(KERN_ERR DEVICE_NAME
+		       ": Event interrupt %02x Uart = %02x Gpio = %02x\n",
+		       dev->EventBuffer->EventStatus,
+		       dev->EventBuffer->UARTStatus,
+		       dev->EventBuffer->GPIOStatus);
+#endif
 		if (nextWriteIndex != dev->EventQueueReadIndex) {
 			dev->EventQueue[dev->EventQueueWriteIndex] =
 				*(dev->EventBuffer);
@@ -322,12 +337,24 @@
 	ngwritel(1, FORCE_INT);
 
 	ret = wait_event_timeout(dev->cmd_wq, dev->cmd_done == 1, 2 * HZ);
+#if 0
+	if (ret < 0)
+		return ret;
+	if (!dev->cmd_done)
+		;
+#endif
 	if (!ret) {
 		/*ngwritel(0, FORCE_NMI);*/
 
 		printk(KERN_ERR DEVICE_NAME
 		       ": Command timeout cmd=%02x prev=%02x\n",
 		       com->cmd.hdr.Opcode, dev->prev_cmd);
+#if 0
+		printk(KERN_ERR DEVICE_NAME ": Icounts=%08x\n",
+		       ngreadl(NGENE_INT_COUNTS));
+		if (ngreadl(NGENE_INT_COUNTS) == 0xffffffff)
+			ngwritel(0, NGENE_INT_ENABLE);
+#endif
 		dump_command_io(dev);
 		return -1;
 	}
@@ -354,6 +381,19 @@
 	return result;
 }
 
+#if 0
+int ngene_command_nop(struct ngene *dev)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_NOP;
+	com.cmd.hdr.Length = 0;
+	com.in_len = 0;
+	com.out_len = 0;
+
+	return ngene_command(dev, &com);
+}
+#endif
 
 static int ngene_command_load_firmware(struct ngene *dev,
 				       u8 *ngene_fw, u32 size)
@@ -388,6 +428,83 @@
 	return ngene_command(dev, &com);
 }
 
+#if 0
+int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = type ? CMD_SFR_READ : CMD_IRAM_READ;
+	com.cmd.hdr.Length = 1;
+	com.cmd.SfrIramRead.address = adr;
+	com.in_len = 1;
+	com.out_len = 2;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+
+	*data = com.cmd.raw8[1];
+	return 0;
+}
+
+int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = type ? CMD_SFR_WRITE : CMD_IRAM_WRITE;
+	com.cmd.hdr.Length = 2;
+	com.cmd.SfrIramWrite.address = adr;
+	com.cmd.SfrIramWrite.data = data;
+	com.in_len = 2;
+	com.out_len = 1;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int ngene_command_config_uart(struct ngene *dev, u8 config,
+				     tx_cb_t *tx_cb, rx_cb_t *rx_cb)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_CONFIGURE_UART;
+	com.cmd.hdr.Length = sizeof(struct FW_CONFIGURE_UART) - 2;
+	com.cmd.ConfigureUart.UartControl = config;
+	com.in_len = sizeof(struct FW_CONFIGURE_UART);
+	com.out_len = 0;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+
+	dev->TxEventNotify = tx_cb;
+	dev->RxEventNotify = rx_cb;
+
+	dprintk(KERN_DEBUG DEVICE_NAME ": Set UART config %02x.\n", config);
+
+	return 0;
+}
+
+static void tx_cb(struct ngene *dev, u32 ts)
+{
+	dev->tx_busy = 0;
+	wake_up_interruptible(&dev->tx_wq);
+}
+
+static void rx_cb(struct ngene *dev, u32 ts, u8 c)
+{
+	int rp = dev->uart_rp;
+	int nwp, wp = dev->uart_wp;
+
+	/* dprintk(KERN_DEBUG DEVICE_NAME ": %c\n", c); */
+	nwp = (wp + 1) % (UART_RBUF_LEN);
+	if (nwp == rp)
+		return;
+	dev->uart_rbuf[wp] = c;
+	dev->uart_wp = nwp;
+	wake_up_interruptible(&dev->rx_wq);
+}
+#endif
 
 static int ngene_command_config_buf(struct ngene *dev, u8 config)
 {
@@ -433,6 +550,18 @@
 	return ngene_command(dev, &com);
 }
 
+#if 0
+/* The reset is only wired to GPIO4 on MicRacer Revision 1.10 !
+   Also better set bootdelay to 1 in nvram or less. */
+static void ngene_reset_decypher(struct ngene *dev)
+{
+	printk(KERN_INFO DEVICE_NAME ": Resetting Decypher.\n");
+	ngene_command_gpio_set(dev, 4, 0);
+	msleep(1);
+	ngene_command_gpio_set(dev, 4, 1);
+	msleep(2000);
+}
+#endif
 
 /*
  02000640 is sample on rising edge.
@@ -518,6 +647,17 @@
 	}
 }
 
+#if 0
+static void clear_tsin(struct ngene_channel *chan)
+{
+	struct SBufferHeader *Cur = chan->nextBuffer;
+
+	do {
+		memset(&Cur->ngeneBuffer.SR, 0, sizeof(Cur->ngeneBuffer.SR));
+		Cur = Cur->Next;
+	} while (Cur != chan->nextBuffer);
+}
+#endif
 
 static void flush_buffers(struct ngene_channel *chan)
 {
@@ -738,6 +878,14 @@
 	if (dev->card_info->switch_ctrl)
 		dev->card_info->switch_ctrl(chan, 1, state ^ 1);
 
+#if 0
+	/* Disable AVF output if present. */
+	if (dev->card_info->avf[chan->number])
+		i2c_write_register(&chan->i2c_adapter,
+				   chan->dev->card_info->avf[chan->number],
+				   0xf2, state ? 0x80 : 0x89);
+
+#endif
 	if (state) {
 		spin_lock_irq(&chan->state_lock);
 
@@ -777,6 +925,89 @@
 	}
 }
 
+#if 0
+/****************************************************************************/
+/* Decypher firmware loading ************************************************/
+/****************************************************************************/
+
+#define DECYPHER_FW "decypher.fw"
+
+static int dec_ts_send(struct ngene *dev, u8 *buf, u32 len)
+{
+#if 0
+	if (wait_event_interruptible(dev->tsout_rbuf.queue,
+				     dvb_ringbuffer_free
+				     (&dev->tsout_rbuf) >= len) < 0)
+		return 0;
+#else
+	while (dvb_ringbuffer_free(&dev->tsout_rbuf) < len)
+		msleep(1);
+
+#endif
+
+	dvb_ringbuffer_write(&dev->tsout_rbuf, buf, len);
+
+	return len;
+}
+
+u8 dec_fw_fill_ts[188] = { 0x47, 0x09, 0x0e, 0x10, 0xff, 0xff, 0x00, 0x00 };
+
+int dec_fw_send(struct ngene *dev, u8 *fw, u32 size)
+{
+	struct ngene_channel *chan = &dev->channel[4];
+	u32 len = 180, cc = 0;
+	u8 buf[8] = { 0x47, 0x09, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00 };
+
+	set_transfer(chan, 1);
+	msleep(100);
+	while (size) {
+		len = 180;
+		if (len > size)
+			len = size;
+		buf[3] = 0x10 | (cc & 0x0f);
+		buf[4] = (cc >> 8);
+		buf[5] = cc & 0xff;
+		buf[6] = len;
+
+		dec_ts_send(dev, buf, 8);
+		dec_ts_send(dev, fw, len);
+		if (len < 180)
+			dec_ts_send(dev, dec_fw_fill_ts + len + 8, 180 - len);
+		cc++;
+		size -= len;
+		fw += len;
+	}
+	for (len = 0; len < 512; len++)
+		dec_ts_send(dev, dec_fw_fill_ts, 188);
+	while (dvb_ringbuffer_avail(&dev->tsout_rbuf))
+		msleep(10);
+	msleep(100);
+	set_transfer(chan, 0);
+	return 0;
+}
+
+int dec_fw_boot(struct ngene *dev)
+{
+	u32 size;
+	const struct firmware *fw = NULL;
+	u8 *dec_fw;
+
+	if (request_firmware(&fw, DECYPHER_FW, &dev->pci_dev->dev) < 0) {
+		printk(KERN_ERR DEVICE_NAME
+		       ": %s not found. Check hotplug directory.\n",
+		       DECYPHER_FW);
+		return -1;
+	}
+	printk(KERN_INFO DEVICE_NAME ": Booting decypher firmware file %s\n",
+	       DECYPHER_FW);
+
+	size = fw->size;
+	dec_fw = (u8 *)fw->data;
+	dec_fw_send(dev, dec_fw, size);
+	release_firmware(fw);
+	return 0;
+}
+#endif
 
 /****************************************************************************/
 /* nGene hardware init and release functions ********************************/
@@ -1071,6 +1302,85 @@
 	0
 };
 
+#if 0
+static int allocate_buffer(struct pci_dev *pci_dev, dma_addr_t of,
+			   struct SRingBufferDescriptor *rbuf,
+			   u32 entries, u32 size1, u32 size2)
+{
+	if (create_ring_buffer(pci_dev, rbuf, entries) < 0)
+		return -ENOMEM;
+
+	if (AllocateRingBuffers(pci_dev, of, rbuf, size1, size2) < 0)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int channel_allocate_buffers(struct ngene_channel *chan)
+{
+	struct ngene *dev = chan->dev;
+	int type = dev->card_info->io_type[chan->number];
+	int status;
+
+	chan->State = KSSTATE_STOP;
+
+	if (type & (NGENE_IO_TV | NGENE_IO_HDTV | NGENE_IO_AIN)) {
+		status = create_ring_buffer(dev->pci_dev,
+					    &chan->RingBuffer,
+					    RingBufferSizes[chan->number]);
+		if (status < 0)
+			return -ENOMEM;
+
+		if (type & (NGENE_IO_TV | NGENE_IO_AIN)) {
+			status = AllocateRingBuffers(dev->pci_dev,
+						     dev->PAOverflowBuffer,
+						     &chan->RingBuffer,
+						     Buffer1Sizes[chan->number],
+						     Buffer2Sizes[chan->
+								  number]);
+			if (status < 0)
+				return -ENOMEM;
+		} else if (type & NGENE_IO_HDTV) {
+			status = AllocateRingBuffers(dev->pci_dev,
+						     dev->PAOverflowBuffer,
+						     &chan->RingBuffer,
+						     MAX_HDTV_BUFFER_SIZE, 0);
+			if (status < 0)
+				return -ENOMEM;
+		}
+	}
+
+	if (type & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
+
+		status = create_ring_buffer(dev->pci_dev,
+					    &chan->TSRingBuffer, RING_SIZE_TS);
+		if (status < 0)
+			return -ENOMEM;
+
+		status = AllocateRingBuffers(dev->pci_dev,
+					     dev->PAOverflowBuffer,
+					     &chan->TSRingBuffer,
+					     MAX_TS_BUFFER_SIZE, 0);
+		if (status)
+			return -ENOMEM;
+	}
+
+	if (type & NGENE_IO_TSOUT) {
+		status = create_ring_buffer(dev->pci_dev,
+					    &chan->TSIdleBuffer, 1);
+		if (status < 0)
+			return -ENOMEM;
+		status = AllocateRingBuffers(dev->pci_dev,
+					     dev->PAOverflowBuffer,
+					     &chan->TSIdleBuffer,
+					     MAX_TS_BUFFER_SIZE, 0);
+		if (status)
+			return -ENOMEM;
+		FillTSIdleBuffer(&chan->TSIdleBuffer, &chan->TSRingBuffer);
+	}
+	return 0;
+}
+#endif
 
 static int AllocCommonBuffers(struct ngene *dev)
 {
@@ -1324,6 +1634,10 @@
 		u8 tsin12_config[6]   = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 };
 		u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 };
 		u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 };
+#if 0
+		u8 tsin34_config[6]   = { 0x00, 0x00, 0x00, 0x60, 0x60, 0x00 };
+		u8 tsio35_config[6]   = { 0x00, 0x00, 0x00, 0x60, 0x00, 0x60 };
+#endif
 		u8 *bconf = tsin12_config;
 
 		if (dev->card_info->io_type[2]&NGENE_IO_TSIN &&
@@ -1333,10 +1647,22 @@
 			    dev->ci.en)
 				bconf = tsio1235_config;
 		}
+#if 0
+		if (dev->card_info->io_type[0] == NGENE_IO_HDTV) {
+			bconf = hdtv_config;
+			ngene_reset_decypher(dev);
+		}
+#endif
 		stat = ngene_command_config_free_buf(dev, bconf);
 	} else {
 		int bconf = BUFFER_CONFIG_4422;
 
+#if 0
+		if (dev->card_info->io_type[0] == NGENE_IO_HDTV) {
+			bconf = BUFFER_CONFIG_8022;
+			ngene_reset_decypher(dev);
+		}
+#endif
 		if (dev->card_info->io_type[3] == NGENE_IO_TSIN)
 			bconf = BUFFER_CONFIG_3333;
 		stat = ngene_command_config_buf(dev, bconf);
@@ -1409,8 +1735,10 @@
 	if (stat < 0)
 		goto fail;
 
-	return 0;
+	if (!stat)
+		return stat;
 
+	/* otherwise error: fall through */
 fail:
 	ngwritel(0, NGENE_INT_ENABLE);
 	free_irq(dev->pci_dev->irq, dev);
@@ -1695,6 +2023,33 @@
 
 
 	dev->i2c_current_bus = -1;
+#if 0
+	exp_init(dev);
+
+	/* Disable analog TV decoder chips if present */
+	if (dev->card_info->msp[0])
+		i2c_write_msp_register(&dev->channel[0].i2c_adapter,
+				       dev->card_info->msp[0], 0x00, 0x0000);
+	if (dev->card_info->msp[1])
+		i2c_write_msp_register(&dev->channel[1].i2c_adapter,
+				       dev->card_info->msp[1], 0x00, 0x0000);
+	{
+		u16 data;
+		read_msp(&dev->channel[0].i2c_adapter,
+			 dev->card_info->msp[0], 0x00, &data);
+	}
+	if (dev->card_info->avf[0])
+		i2c_write_register(&dev->channel[0].i2c_adapter,
+				   dev->card_info->avf[0], 0xf2, 0x80);
+	if (dev->card_info->avf[1])
+		i2c_write_register(&dev->channel[1].i2c_adapter,
+				   dev->card_info->avf[1], 0xf2, 0x80);
+	if (copy_eeprom) {
+		i2c_copy_eeprom(&dev->channel[0].i2c_adapter, 0x50, 0x52);
+		i2c_dump_eeprom(&dev->channel[0].i2c_adapter, 0x52);
+	}
+	/*i2c_check_eeprom(&dev->i2c_adapter);*/
+#endif
 
 	/* Register DVB adapters and devices for both channels */
 	if (init_channels(dev) < 0)
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/ngene-dvb.c linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-dvb.c
--- linux-3.6.8/drivers/media/dvb/ngene/ngene-dvb.c	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-dvb.c	2012-12-03 09:05:52.497670334 +0100
@@ -42,10 +42,319 @@
 
 #include "ngene.h"
 
+#if 0
+int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode,
+			 u16 lines, u16 bpl, u16 vblines, u16 vbibpl)
+{
+	if (!(mode & SMODE_TRANSPORT_STREAM))
+		return -EINVAL;
+
+	if (lines * bpl > MAX_VIDEO_BUFFER_SIZE)
+		return -EINVAL;
+
+	if ((mode & SMODE_TRANSPORT_STREAM) && (((bpl * lines) & 0xff) != 0))
+		return -EINVAL;
+
+	if ((mode & SMODE_VIDEO_CAPTURE) && (bpl & 7) != 0)
+		return -EINVAL;
+
+	return ngene_command_stream_control(dev, stream, control, mode, 0);
+}
+#endif
 
 /****************************************************************************/
 /* COMMAND API interface ****************************************************/
 /****************************************************************************/
+#if 0
+
+static int command_do_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	int err = 0;
+
+	switch (cmd) {
+	case IOCTL_MIC_NO_OP:
+		err = ngene_command_nop(dev);
+		break;
+
+	case IOCTL_MIC_DOWNLOAD_FIRMWARE:
+		break;
+
+	case IOCTL_MIC_I2C_READ:
+	{
+		MIC_I2C_READ *msg = parg;
+
+		err = ngene_command_i2c_read(dev, msg->I2CAddress >> 1,
+					     msg->OutData, msg->OutLength,
+					     msg->OutData, msg->InLength, 1);
+		break;
+	}
+
+	case IOCTL_MIC_I2C_WRITE:
+	{
+		MIC_I2C_WRITE *msg = parg;
+
+		err = ngene_command_i2c_write(dev, msg->I2CAddress >> 1,
+					      msg->Data, msg->Length);
+		break;
+	}
+
+	case IOCTL_MIC_TEST_GETMEM:
+	{
+		MIC_MEM *m = parg;
+
+		if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024)
+			return -EINVAL;
+
+		/* WARNING, only use this on x86,
+		   other archs may not swallow this  */
+		err = copy_to_user(m->Data, dev->iomem + m->Start, m->Length);
+		break;
+	}
+
+	case IOCTL_MIC_TEST_SETMEM:
+	{
+		MIC_MEM *m = parg;
+
+		if (m->Length > 64 * 1024 || m->Start + m->Length > 64 * 1024)
+			return -EINVAL;
+
+		err = copy_from_user(dev->iomem + m->Start, m->Data, m->Length);
+		break;
+	}
+
+	case IOCTL_MIC_SFR_READ:
+	{
+		MIC_IMEM *m = parg;
+
+		err = ngene_command_imem_read(dev, m->Address, &m->Data, 1);
+		break;
+	}
+
+	case IOCTL_MIC_SFR_WRITE:
+	{
+		MIC_IMEM *m = parg;
+
+		err = ngene_command_imem_write(dev, m->Address, m->Data, 1);
+		break;
+	}
+
+	case IOCTL_MIC_IRAM_READ:
+	{
+		MIC_IMEM *m = parg;
+
+		err = ngene_command_imem_read(dev, m->Address, &m->Data, 0);
+		break;
+	}
+
+	case IOCTL_MIC_IRAM_WRITE:
+	{
+		MIC_IMEM *m = parg;
+
+		err = ngene_command_imem_write(dev, m->Address, m->Data, 0);
+		break;
+	}
+
+	case IOCTL_MIC_STREAM_CONTROL:
+	{
+		MIC_STREAM_CONTROL *m = parg;
+
+		err = ngene_stream_control(dev, m->Stream, m->Control, m->Mode,
+					   m->nLines, m->nBytesPerLine,
+					   m->nVBILines, m->nBytesPerVBILine);
+		break;
+	}
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+	return err;
+}
+
+static int command_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	void *parg = (void *)arg, *pbuf = NULL;
+	char  buf[64];
+	int   res = -EFAULT;
+
+	if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		parg = buf;
+		if (_IOC_SIZE(cmd) > sizeof(buf)) {
+			pbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
+			if (!pbuf)
+				return -ENOMEM;
+			parg = pbuf;
+		}
+		if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+			goto error;
+	}
+	res = command_do_ioctl(inode, file, cmd, parg);
+	if (res < 0)
+		goto error;
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+			res = -EFAULT;
+error:
+	kfree(pbuf);
+	return res;
+}
+
+struct page *ngene_nopage(struct vm_area_struct *vma,
+			  unsigned long address, int *type)
+{
+	return 0;
+}
+
+static int ngene_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long padr = pci_resource_start(dev->pci_dev, 0) + off;
+	unsigned long psize = pci_resource_len(dev->pci_dev, 0) - off;
+
+	if (size > psize)
+		return -EINVAL;
+
+	if (io_remap_pfn_range(vma, vma->vm_start, padr >> PAGE_SHIFT, size,
+			       vma->vm_page_prot))
+		return -EAGAIN;
+	return 0;
+}
+
+
+static int write_uart(struct ngene *dev, u8 *data, int len)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_WRITE_UART;
+	com.cmd.hdr.Length = len;
+	memcpy(com.cmd.WriteUart.Data, data, len);
+	com.cmd.WriteUart.Data[len] = 0;
+	com.cmd.WriteUart.Data[len + 1] = 0;
+	com.in_len = len;
+	com.out_len = 0;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int send_cli(struct ngene *dev, char *cmd)
+{
+	/* printk(KERN_INFO DEVICE_NAME ": %s", cmd); */
+	return write_uart(dev, cmd, strlen(cmd));
+}
+
+static int send_cli_val(struct ngene *dev, char *cmd, u32 val)
+{
+	char s[32];
+
+	snprintf(s, 32, "%s %d\n", cmd, val);
+	/* printk(KERN_INFO DEVICE_NAME ": %s", s); */
+	return write_uart(dev, s, strlen(s));
+}
+
+static int ngene_command_write_uart_user(struct ngene *dev,
+					 const u8 *data, int len)
+{
+	struct ngene_command com;
+
+	dev->tx_busy = 1;
+	com.cmd.hdr.Opcode = CMD_WRITE_UART;
+	com.cmd.hdr.Length = len;
+
+	if (copy_from_user(com.cmd.WriteUart.Data, data, len))
+		return -EFAULT;
+	com.in_len = len;
+	com.out_len = 0;
+
+	if (ngene_command(dev, &com) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static ssize_t uart_write(struct file *file, const char *buf,
+			  size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	int len, ret = 0;
+	size_t left = count;
+
+	while (left) {
+		len = left;
+		if (len > 250)
+			len = 250;
+		ret = wait_event_interruptible(dev->tx_wq, dev->tx_busy == 0);
+		if (ret < 0)
+			return ret;
+		ngene_command_write_uart_user(dev, buf, len);
+		left -= len;
+		buf += len;
+	}
+	return count;
+}
+
+static ssize_t uart_read(struct file *file, char *buf,
+			 size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	int left;
+	int wp, rp, avail, len;
+
+	if (!dev->uart_rbuf)
+		return -EINVAL;
+	if (count > 128)
+		count = 128;
+	left = count;
+	while (left) {
+		if (wait_event_interruptible(dev->rx_wq,
+					     dev->uart_wp != dev->uart_rp) < 0)
+			return -EAGAIN;
+		wp = dev->uart_wp;
+		rp = dev->uart_rp;
+		avail = (wp - rp);
+
+		if (avail < 0)
+			avail += UART_RBUF_LEN;
+		if (avail > left)
+			avail = left;
+		if (wp < rp) {
+			len = UART_RBUF_LEN - rp;
+			if (len > avail)
+				len = avail;
+			if (copy_to_user(buf, dev->uart_rbuf + rp, len))
+				return -EFAULT;
+			if (len < avail)
+				if (copy_to_user(buf + len, dev->uart_rbuf,
+						 avail - len))
+					return -EFAULT;
+		} else {
+			if (copy_to_user(buf, dev->uart_rbuf + rp, avail))
+				return -EFAULT;
+		}
+		dev->uart_rp = (rp + avail) % UART_RBUF_LEN;
+		left -= avail;
+		buf += avail;
+	}
+	return count;
+}
+
+#endif
 
 static ssize_t ts_write(struct file *file, const char *buf,
 			size_t count, loff_t *ppos)
@@ -133,6 +442,11 @@
 	struct ngene_channel *chan = priv;
 	struct ngene *dev = chan->dev;
 
+#if 0
+	printk(KERN_INFO DEVICE_NAME ": tsin %08x %02x %02x %02x %02x\n",
+	       len, ((u8 *) buf)[512 * 188], ((u8 *) buf)[0],
+	       ((u8 *) buf)[1], ((u8 *) buf)[2]);
+#endif
 
 	if (flags & DF_SWAP32)
 		swap_buffer(buf, len);
@@ -191,12 +505,49 @@
 	return buf;
 }
 
+#if 0
+static void set_dto(struct ngene_channel *chan, u32 rate)
+{
+	u64 val = rate * 0x89705f41ULL; /* times val for 2^26 Hz */
+
+	val = ((val >> 25) + 1) >> 1;
+	chan->AudioDTOValue = (u32) val;
+	/* chan->AudioDTOUpdated=1; */
+	/* printk(KERN_INFO DEVICE_NAME ": Setting DTO to %08x\n", val); */
+}
+#endif
 
 
 int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct ngene_channel *chan = dvbdmx->priv;
+#if 0
+	struct ngene *dev = chan->dev;
+
+	if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) {
+		switch (dvbdmxfeed->pes_type) {
+		case DMX_TS_PES_VIDEO:
+			send_cli_val(dev, "vpid", dvbdmxfeed->pid);
+			send_cli(dev, "res 1080i50\n");
+			/* send_cli(dev, "vdec mpeg2\n"); */
+			break;
+
+		case DMX_TS_PES_AUDIO:
+			send_cli_val(dev, "apid", dvbdmxfeed->pid);
+			send_cli(dev, "start\n");
+			break;
+
+		case DMX_TS_PES_PCR:
+			send_cli_val(dev, "pcrpid", dvbdmxfeed->pid);
+			break;
+
+		default:
+			break;
+		}
+
+	}
+#endif
 
 	if (chan->users == 0) {
 		if (!chan->dev->cmd_timeout_workaround || !chan->running)
@@ -210,6 +561,27 @@
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
 	struct ngene_channel *chan = dvbdmx->priv;
+#if 0
+	struct ngene *dev = chan->dev;
+
+	if (dev->card_info->io_type[chan->number] & NGENE_IO_TSOUT) {
+		switch (dvbdmxfeed->pes_type) {
+		case DMX_TS_PES_VIDEO:
+			send_cli(dev, "stop\n");
+			break;
+
+		case DMX_TS_PES_AUDIO:
+			break;
+
+		case DMX_TS_PES_PCR:
+			break;
+
+		default:
+			break;
+		}
+
+	}
+#endif
 
 	if (--chan->users)
 		return chan->users;
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/ngene-eeprom.c linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-eeprom.c
--- linux-3.6.8/drivers/media/dvb/ngene/ngene-eeprom.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-eeprom.c	2012-12-03 08:41:17.000000000 +0100
@@ -0,0 +1,284 @@
+/*
+ * ngene-eeprom.c: nGene PCIe bridge driver - eeprom support
+ *
+ * Copyright (C) 2005-2007 Micronas
+ *
+ * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de>
+ *                         Modifications for new nGene firmware,
+ *                         support for EEPROM-copying,
+ *                         support for new dual DVB-S2 card prototype
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 only, as published by the Free Software Foundation.
+ *
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#if 0
+static int copy_eeprom;
+module_param(copy_eeprom, int, 0444);
+MODULE_PARM_DESC(copy_eeprom, "Copy eeprom.");
+
+#define MICNG_EE_START      0x0100
+#define MICNG_EE_END        0x0FF0
+
+#define MICNG_EETAG_END0    0x0000
+#define MICNG_EETAG_END1    0xFFFF
+
+/* 0x0001 - 0x000F reserved for housekeeping */
+/* 0xFFFF - 0xFFFE reserved for housekeeping */
+
+/* Micronas assigned tags
+   EEProm tags for hardware support */
+
+#define MICNG_EETAG_DRXD1_OSCDEVIATION  0x1000  /* 2 Bytes data */
+#define MICNG_EETAG_DRXD2_OSCDEVIATION  0x1001  /* 2 Bytes data */
+
+#define MICNG_EETAG_MT2060_1_1STIF      0x1100  /* 2 Bytes data */
+#define MICNG_EETAG_MT2060_2_1STIF      0x1101  /* 2 Bytes data */
+
+/* Tag range for OEMs */
+
+#define MICNG_EETAG_OEM_FIRST  0xC000
+#define MICNG_EETAG_OEM_LAST   0xFFEF
+
+static int i2c_write_eeprom(struct i2c_adapter *adapter,
+			    u8 adr, u16 reg, u8 data)
+{
+	u8 m[3] = {(reg >> 8), (reg & 0xff), data};
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m,
+			      .len = sizeof(m)};
+
+	if (i2c_transfer(adapter, &msg, 1) != 1) {
+		dprintk(KERN_ERR DEVICE_NAME ": Error writing EEPROM!\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int i2c_read_eeprom(struct i2c_adapter *adapter,
+			   u8 adr, u16 reg, u8 *data, int len)
+{
+	u8 msg[2] = {(reg >> 8), (reg & 0xff)};
+	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+				   .buf = msg, .len = 2 },
+				  {.addr = adr, .flags = I2C_M_RD,
+				   .buf = data, .len = len} };
+
+	if (i2c_transfer(adapter, msgs, 2) != 2) {
+		dprintk(KERN_ERR DEVICE_NAME ": Error reading EEPROM\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int ReadEEProm(struct i2c_adapter *adapter,
+		      u16 Tag, u32 MaxLen, u8 *data, u32 *pLength)
+{
+	int status = 0;
+	u16 Addr = MICNG_EE_START, Length, tag = 0;
+	u8  EETag[3];
+
+	while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
+		if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
+			return -1;
+		tag = (EETag[0] << 8) | EETag[1];
+		if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
+			return -1;
+		if (tag == Tag)
+			break;
+		Addr += sizeof(u16) + 1 + EETag[2];
+	}
+	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
+		printk(KERN_ERR DEVICE_NAME
+		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
+		       tag, EETag[2]);
+		return -1;
+	}
+	Length = EETag[2];
+	if (Length > MaxLen)
+		Length = (u16) MaxLen;
+	if (Length > 0) {
+		Addr += sizeof(u16) + 1;
+		status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length);
+		if (!status) {
+			*pLength = EETag[2];
+			if (Length < EETag[2])
+				; /*status=STATUS_BUFFER_OVERFLOW; */
+		}
+	}
+	return status;
+}
+
+static int WriteEEProm(struct i2c_adapter *adapter,
+		       u16 Tag, u32 Length, u8 *data)
+{
+	int status = 0;
+	u16 Addr = MICNG_EE_START;
+	u8 EETag[3];
+	u16 tag = 0;
+	int retry, i;
+
+	while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
+		if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
+			return -1;
+		tag = (EETag[0] << 8) | EETag[1];
+		if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
+			return -1;
+		if (tag == Tag)
+			break;
+		Addr += sizeof(u16) + 1 + EETag[2];
+	}
+	if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
+		printk(KERN_ERR DEVICE_NAME
+		       ": Reached EOEE @ Tag = %04x Length = %3d\n",
+		       tag, EETag[2]);
+		return -1;
+	}
+
+	if (Length > EETag[2])
+		return -EINVAL;
+	/* Note: We write the data one byte at a time to avoid
+	   issues with page sizes. (which are different for
+	   each manufacture and eeprom size)
+	 */
+	Addr += sizeof(u16) + 1;
+	for (i = 0; i < Length; i++, Addr++) {
+		status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]);
+
+		if (status)
+			break;
+
+		/* Poll for finishing write cycle */
+		retry = 10;
+		while (retry) {
+			u8 Tmp;
+
+			msleep(50);
+			status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1);
+			if (status)
+				break;
+			if (Tmp != data[i])
+				printk(KERN_ERR DEVICE_NAME
+				       "eeprom write error\n");
+			retry -= 1;
+		}
+		if (status) {
+			printk(KERN_ERR DEVICE_NAME
+			       ": Timeout polling eeprom\n");
+			break;
+		}
+	}
+	return status;
+}
+
+static void i2c_init_eeprom(struct i2c_adapter *adapter)
+{
+	u8 tags[] = {0x10, 0x00, 0x02, 0x00, 0x00,
+		     0x10, 0x01, 0x02, 0x00, 0x00,
+		     0x00, 0x00, 0x00};
+
+	int i;
+
+	for (i = 0; i < sizeof(tags); i++)
+		i2c_write_eeprom(adapter, 0x50, 0x0100 + i, tags[i]);
+}
+
+int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data)
+{
+	int stat;
+	u8 buf[2];
+	u32 len = 0;
+
+	stat = ReadEEProm(adapter, tag, 2, buf, &len);
+	if (stat)
+		return stat;
+	if (len != 2)
+		return -EINVAL;
+
+	*data = (buf[0] << 8) | buf[1];
+	return 0;
+}
+
+static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data)
+{
+	int stat;
+	u8 buf[2];
+
+	buf[0] = data >> 8;
+	buf[1] = data & 0xff;
+	stat = WriteEEProm(adapter, tag, 2, buf);
+	if (stat)
+		return stat;
+	return 0;
+}
+
+int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr)
+{
+	u8 buf[64];
+	int i;
+
+	if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) {
+		printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n");
+		return -1;
+	}
+	for (i = 0; i < sizeof(buf); i++) {
+		if (!(i & 15))
+			printk(KERN_DEBUG "\n");
+		printk(KERN_DEBUG "%02x ", buf[i]);
+	}
+	printk("\n");
+
+	return 0;
+}
+
+int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2)
+{
+	u8 buf[64];
+	int i;
+
+	if (i2c_read_eeprom(adapter, adr, 0x0000, buf, sizeof(buf))) {
+		printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n");
+		return -1;
+	}
+	buf[36] = 0xc3;
+	buf[39] = 0xab;
+	for (i = 0; i < sizeof(buf); i++) {
+		i2c_write_eeprom(adapter, adr2, i, buf[i]);
+		msleep(10);
+	}
+	return 0;
+}
+
+int i2c_check_eeprom(struct i2c_adapter *adapter)
+{
+	u8 buf[13];
+
+	i2c_dump_eeprom(adapter);
+
+	if (i2c_read_eeprom(adapter, 0x50, 0x0100, buf, sizeof(buf))) {
+		printk(KERN_ERR DEVICE_NAME ": No EEPROM?\n");
+		return -1;
+	}
+	if (buf[0] != 0x10 || buf[1] != 0x00) {
+		printk(KERN_INFO DEVICE_NAME
+		       ": Initializing EEPROM TAG area\n");
+		i2c_init_eeprom(adapter);
+	}
+	return 0;
+}
+
+#endif
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/ngene.h linux-3.6.8.patch/drivers/media/dvb/ngene/ngene.h
--- linux-3.6.8/drivers/media/dvb/ngene/ngene.h	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/ngene.h	2012-12-03 08:41:17.000000000 +0100
@@ -653,6 +653,11 @@
 	struct dmx_frontend   mem_frontend;
 	int                   users;
 	struct video_device  *v4l_dev;
+#if 0
+	struct dvb_device    *command_dev;
+	struct dvb_device    *audio_dev;
+	struct dvb_device    *video_dev;
+#endif
 	struct dvb_device    *ci_dev;
 	struct tasklet_struct demux_tasklet;
 
@@ -691,6 +696,9 @@
 	struct mychip        *mychip;
 	struct snd_card      *soundcard;
 	u8                   *evenbuffer;
+#if 0
+	u8                   *soundbuffer;
+#endif
 	u8                    dma_on;
 	int                   soundstreamon;
 	int                   audiomute;
@@ -849,6 +857,10 @@
 	u8    lnb[4];
 	int   i2c_access;
 	u8    ntsc;
+#if 0
+	u8    exp;
+	u8    exp_init;
+#endif
 	u8    tsf[4];
 	u8    i2s[4];
 
@@ -885,6 +897,25 @@
 };
 #endif
 
+#if 0
+int ngene_command_stream_control(struct ngene *dev,
+				 u8 stream, u8 control, u8 mode, u8 flags);
+int ngene_command_nop(struct ngene *dev);
+int ngene_command_i2c_read(struct ngene *dev, u8 adr,
+			   u8 *out, u8 outlen, u8 *in, u8 inlen, int flag);
+int ngene_command_i2c_write(struct ngene *dev, u8 adr, u8 *out, u8 outlen);
+int ngene_command_imem_read(struct ngene *dev, u8 adr, u8 *data, int type);
+int ngene_command_imem_write(struct ngene *dev, u8 adr, u8 data, int type);
+int ngene_stream_control(struct ngene *dev, u8 stream, u8 control, u8 mode,
+			 u16 lines, u16 bpl, u16 vblines, u16 vbibpl);
+
+int ngene_v4l2_init(struct ngene_channel *chan);
+void ngene_v4l2_remove(struct ngene_channel *chan);
+int ngene_snd_exit(struct ngene_channel *chan);
+int ngene_snd_init(struct ngene_channel *chan);
+
+struct i2c_client *avf4910a_attach(struct i2c_adapter *adap, int addr);
+#endif
 
 /* Provided by ngene-core.c */
 int __devinit ngene_probe(struct pci_dev *pci_dev,
@@ -915,6 +946,15 @@
 			       struct dmx_frontend *mem_frontend,
 			       struct dvb_adapter *dvb_adapter);
 
+/* Provided by ngene-eeprom.c */
+#if 0
+int i2c_copy_eeprom(struct i2c_adapter *adapter, u8 adr, u8 adr2);
+int i2c_dump_eeprom(struct i2c_adapter *adapter, u8 adr);
+int i2c_check_eeprom(struct i2c_adapter *adapter);
+int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data);
+int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data);
+#endif
+
 #endif
 
 /*  LocalWords:  Endif
diff -Naur linux-3.6.8/drivers/media/dvb/ngene/ngene-i2c.c linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-i2c.c
--- linux-3.6.8/drivers/media/dvb/ngene/ngene-i2c.c	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/media/dvb/ngene/ngene-i2c.c	2012-12-03 09:05:39.359775326 +0100
@@ -77,6 +77,11 @@
 {
 	struct ngene_command com;
 
+#if 0
+	/* Probing by writing 0 bytes does not work */
+	if (!outlen)
+		outlen++;
+#endif
 
 	com.cmd.hdr.Opcode = CMD_I2C_WRITE;
 	com.cmd.hdr.Length = outlen + 1;
@@ -148,6 +153,39 @@
 	return num;
 }
 
+#if 0
+static int ngene_i2c_algo_control(struct i2c_adapter *adap,
+				  unsigned int cmd, unsigned long arg)
+{
+	struct ngene_channel *chan =
+		(struct ngene_channel *)i2c_get_adapdata(adap);
+
+	switch (cmd) {
+	case IOCTL_MIC_TUN_RDY:
+		chan->tun_rdy = 1;
+		if (chan->dec_rdy == 1)
+			chan->tun_dec_rdy = 1;
+		break;
+
+	case IOCTL_MIC_DEC_RDY:
+		chan->dec_rdy = 1;
+		if (chan->tun_rdy == 1)
+			chan->tun_dec_rdy = 1;
+		break;
+
+	case IOCTL_MIC_TUN_DETECT:
+		{
+			int *palorbtsc = (int *)arg;
+			*palorbtsc = chan->dev->card_info->ntsc;
+			break;
+		}
+
+	default:
+		break;
+	}
+	return 0;
+}
+#endif
 
 static u32 ngene_i2c_functionality(struct i2c_adapter *adap)
 {
@@ -174,3 +212,78 @@
 	return i2c_add_adapter(adap);
 }
 
+#if 0
+int i2c_write(struct i2c_adapter *adapter, u8 adr, u8 data)
+{
+	u8 m[1] = {data};
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 1};
+
+	if (i2c_transfer(adapter, &msg, 1) != 1) {
+		printk(KERN_ERR DEVICE_NAME
+		       ": Failed to write to I2C adr %02x!\n", adr);
+		return -1;
+	}
+	return 0;
+}
+
+static int i2c_write_register(struct i2c_adapter *adapter,
+			      u8 adr, u8 reg, u8 data)
+{
+	u8 m[2] = {reg, data};
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 2};
+
+	if (i2c_transfer(adapter, &msg, 1) != 1) {
+		printk(KERN_ERR DEVICE_NAME
+		       ": Failed to write to I2C register %02x@%02x!\n",
+		       reg, adr);
+		return -1;
+	}
+	return 0;
+}
+
+static int i2c_write_read(struct i2c_adapter *adapter,
+			  u8 adr, u8 *w, u8 wlen, u8 *r, u8 rlen)
+{
+	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+				   .buf = w, .len = wlen},
+				  {.addr = adr, .flags = I2C_M_RD,
+				   .buf = r, .len = rlen} };
+
+	if (i2c_transfer(adapter, msgs, 2) != 2) {
+		printk(KERN_ERR DEVICE_NAME ": error in i2c_write_read\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int test_dec_i2c(struct i2c_adapter *adapter, int reg)
+{
+	u8 data[256] = { reg, 0x00, 0x93, 0x78, 0x43, 0x45 };
+	u8 data2[256];
+	int i;
+
+	memset(data2, 0, 256);
+	i2c_write_read(adapter, 0x66, data, 2, data2, 4);
+	for (i = 0; i < 4; i++)
+		printk(KERN_DEBUG "%02x ", data2[i]);
+	printk(KERN_DEBUG "\n");
+
+	return 0;
+}
+
+static int i2c_write_msp_register(struct i2c_adapter *adapter,
+				  u8 adr, u8 reg, u16 data)
+{
+	u8 m[3] = {reg, (data >> 8) & 0xff, data & 0xff};
+	struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m, .len = 3 };
+
+	if (i2c_transfer(adapter, &msg, 1) != 1) {
+		printk(KERN_ERR DEVICE_NAME
+		       ": Failed to write to I2C register %02x@%02x!\n",
+		       reg, adr);
+		return -1;
+	}
+	return 0;
+}
+
+#endif
diff -Naur linux-3.6.8/drivers/staging/media/cxd2099/cxd2099.c linux-3.6.8.patch/drivers/staging/media/cxd2099/cxd2099.c
--- linux-3.6.8/drivers/staging/media/cxd2099/cxd2099.c	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/staging/media/cxd2099/cxd2099.c	2012-12-03 08:41:17.000000000 +0100
@@ -117,9 +117,10 @@
 
 static int read_block(struct cxd *ci, u8 adr, u8 *data, u8 n)
 {
-	int status;
+	int status = 0;
 
-	status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
+	if (ci->lastaddress != adr)
+		status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr);
 	if (!status) {
 		ci->lastaddress = adr;
 		status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, n);
diff -Naur linux-3.6.8/drivers/staging/media/cxd2099/Makefile linux-3.6.8.patch/drivers/staging/media/cxd2099/Makefile
--- linux-3.6.8/drivers/staging/media/cxd2099/Makefile	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/staging/media/cxd2099/Makefile	2012-12-03 08:41:17.000000000 +0100
@@ -1,5 +1,5 @@
 obj-$(CONFIG_DVB_CXD2099) += cxd2099.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core/
-ccflags-y += -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners/
+EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
+EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
+EXTRA_CFLAGS += -Idrivers/media/common/tuners/
diff -Naur linux-3.6.8/drivers/staging/media/cxd2099/TODO linux-3.6.8.patch/drivers/staging/media/cxd2099/TODO
--- linux-3.6.8/drivers/staging/media/cxd2099/TODO	2012-11-26 21:15:45.000000000 +0100
+++ linux-3.6.8.patch/drivers/staging/media/cxd2099/TODO	1970-01-01 01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-For now, data is passed through '/dev/dvb/adapterX/sec0':
- - Encrypted data must be written to 'sec0'.
- - Decrypted data can be read from 'sec0'.
- - Setup the CAM using device 'ca0'.
-
-But this is wrong. There are some discussions about the proper way for
-doing it, as seen at:
-	http://www.mail-archive.com/linux-media@vger.kernel.org/msg22196.html
-
-While there's no proper fix for it, the driver should be kept in staging.
-
-Patches should be submitted to: linux-media@vger.kernel.org.
