All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a
@ 2014-08-02  3:48 Antti Palosaari
  2014-08-02  3:48 ` [PATCH 1/5] cxd2843: do not call get_if_frequency() when it is NULL Antti Palosaari
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: Antti Palosaari @ 2014-08-02  3:48 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

After cold power-on, my device wasn't able to find DuoFlex C/C2/T/T2
Expansion card, which I added yesterday. I looked old and new drivers
and tried many things, but no success. Old kernel driver was ages,
many years, behind manufacturer current Linux driver and there has
been a tons of changes. So I ended up upgrading Linux kernel driver
to 0.9.15a (it was 0.5).

Now it is very near Digital Devices official driver, only modulator
and network streaming stuff is removed and CI is abusing SEC like
earlier also.

Few device models are not supported due to missing kernel driver or
missing device profile. Those devices are based of following DTV
frontend chipsets:
MaxLinear MxL5xx
STMicroelectronics STV0910
STMicroelectronics STV0367


Tree for testing is here:
http://git.linuxtv.org/cgit.cgi/anttip/media_tree.git/log/?h=digitaldevices

regards
Antti


Antti Palosaari (5):
  cxd2843: do not call get_if_frequency() when it is NULL
  ddbridge: disable driver building
  ddbridge: remove driver temporarily
  ddbridge: add needed files from manufacturer driver 0.9.15a
  ddbridge: clean up driver for release

 drivers/media/dvb-frontends/cxd2843.c      |    3 +-
 drivers/media/pci/ddbridge/Makefile        |    2 -
 drivers/media/pci/ddbridge/ddbridge-core.c | 3175 +++++++++++++++++++---------
 drivers/media/pci/ddbridge/ddbridge-i2c.c  |  232 ++
 drivers/media/pci/ddbridge/ddbridge-regs.h |  347 ++-
 drivers/media/pci/ddbridge/ddbridge.c      |  456 ++++
 drivers/media/pci/ddbridge/ddbridge.h      |  407 +++-
 7 files changed, 3518 insertions(+), 1104 deletions(-)
 create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c
 create mode 100644 drivers/media/pci/ddbridge/ddbridge.c

-- 
http://palosaari.fi/


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/5] cxd2843: do not call get_if_frequency() when it is NULL
  2014-08-02  3:48 [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Antti Palosaari
@ 2014-08-02  3:48 ` Antti Palosaari
  2014-08-02  3:48 ` [PATCH 2/5] ddbridge: disable driver building Antti Palosaari
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2014-08-02  3:48 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Calling NULL callback crash kernel. Check its existence before
call it.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/dvb-frontends/cxd2843.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-frontends/cxd2843.c b/drivers/media/dvb-frontends/cxd2843.c
index 10fc240..433d913 100644
--- a/drivers/media/dvb-frontends/cxd2843.c
+++ b/drivers/media/dvb-frontends/cxd2843.c
@@ -1154,7 +1154,8 @@ static int set_parameters(struct dvb_frontend *fe)
 		state->plp = fe->dtv_property_cache.stream_id & 0xff;
 	}
 	/* printk("PLP = %08x, bw = %u\n", state->plp, state->bw); */
-	fe->ops.tuner_ops.get_if_frequency(fe, &IF);
+	if (fe->ops.tuner_ops.get_if_frequency)
+		fe->ops.tuner_ops.get_if_frequency(fe, &IF);
 	stat = Start(state, IF);
 	return stat;
 }
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/5] ddbridge: disable driver building
  2014-08-02  3:48 [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Antti Palosaari
  2014-08-02  3:48 ` [PATCH 1/5] cxd2843: do not call get_if_frequency() when it is NULL Antti Palosaari
@ 2014-08-02  3:48 ` Antti Palosaari
  2014-08-02  3:48 ` [PATCH 3/5] ddbridge: remove driver temporarily Antti Palosaari
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2014-08-02  3:48 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Disable building that driver for a wile. We do massive driver
update from latest vendor driver and this is to avoid Kernel
compilation breakage.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/pci/ddbridge/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile
index 7446c8b..39e922c 100644
--- a/drivers/media/pci/ddbridge/Makefile
+++ b/drivers/media/pci/ddbridge/Makefile
@@ -4,7 +4,8 @@
 
 ddbridge-objs := ddbridge-core.o
 
-obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
+#obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
+obj-$() += ddbridge.o
 
 ccflags-y += -Idrivers/media/dvb-core/
 ccflags-y += -Idrivers/media/dvb-frontends/
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/5] ddbridge: remove driver temporarily
  2014-08-02  3:48 [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Antti Palosaari
  2014-08-02  3:48 ` [PATCH 1/5] cxd2843: do not call get_if_frequency() when it is NULL Antti Palosaari
  2014-08-02  3:48 ` [PATCH 2/5] ddbridge: disable driver building Antti Palosaari
@ 2014-08-02  3:48 ` Antti Palosaari
  2014-09-23 11:33   ` Mauro Carvalho Chehab
  2014-08-02  3:48 ` [PATCH 4/5] ddbridge: add needed files from manufacturer driver 0.9.15a Antti Palosaari
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: Antti Palosaari @ 2014-08-02  3:48 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Remove driver (version 0.5) as we will update driver to latest
vendor version 0.9.15. Driver has changed too much for normal
feature by feature update, so better to remove it totally and
build new one based directly to latest vendor version.

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/pci/ddbridge/ddbridge-core.c | 1887 ----------------------------
 drivers/media/pci/ddbridge/ddbridge-regs.h |  151 ---
 drivers/media/pci/ddbridge/ddbridge.h      |  188 ---
 3 files changed, 2226 deletions(-)
 delete mode 100644 drivers/media/pci/ddbridge/ddbridge-core.c
 delete mode 100644 drivers/media/pci/ddbridge/ddbridge-regs.h
 delete mode 100644 drivers/media/pci/ddbridge/ddbridge.h

diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
deleted file mode 100644
index 9f5837f..0000000
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ /dev/null
@@ -1,1887 +0,0 @@
-/*
- * ddbridge.c: Digital Devices PCIe bridge driver
- *
- * Copyright (C) 2010-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/module.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/io.h>
-#include <linux/pci.h>
-#include <linux/pci_ids.h>
-#include <linux/timer.h>
-#include <linux/i2c.h>
-#include <linux/swab.h>
-#include <linux/vmalloc.h>
-#include "ddbridge.h"
-
-#include "ddbridge-regs.h"
-
-#include "tda18271c2dd.h"
-#include "stv6110x.h"
-#include "stv090x.h"
-#include "lnbh24.h"
-#include "drxk.h"
-#include "cxd2843.h"
-#include "tda18212.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-/* MSI had problems with lost interrupts, fixed but needs testing */
-#undef CONFIG_PCI_MSI
-
-/******************************************************************************/
-
-static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
-{
-	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = val,  .len   = 1 } };
-	return (i2c_transfer(adapter, msgs, 1) == 1) ? 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 },
-				  {.addr = adr,  .flags = I2C_M_RD,
-				   .buf  = val,  .len   = 1 } };
-	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
-}
-
-static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
-			  u16 reg, u8 *val)
-{
-	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} };
-	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
-}
-
-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_write_reg(struct i2c_adapter *adap, u8 adr, u8 reg, u8 val)
-{
-	u8 msg[2] = {reg, val};
-
-	return i2c_write(adap, adr, msg, 2);
-}
-
-static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
-{
-	struct ddb *dev = i2c->dev;
-	int stat;
-	u32 val;
-
-	i2c->done = 0;
-	ddbwritel((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);
-			printk(KERN_ERR "IRS %08x\n", istat);
-			ddbwritel(istat, INTERRUPT_ACK);
-		}
-		return -EIO;
-	}
-	val = ddbreadl(i2c->regs+I2C_COMMAND);
-	if (val & 0x70000)
-		return -EIO;
-	return 0;
-}
-
-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 *dev = i2c->dev;
-	u8 addr = 0;
-
-	if (num)
-		addr = msg[0].addr;
-
-	if (num == 2 && msg[1].flags & I2C_M_RD &&
-	    !(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);
-		if (!ddb_i2c_cmd(i2c, addr, 1)) {
-			memcpy_fromio(msg[1].buf,
-				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
-				      msg[1].len);
-			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);
-		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);
-		if (!ddb_i2c_cmd(i2c, addr, 3)) {
-			ddbcpyfrom(msg[0].buf,
-				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
-			return num;
-		}
-	}
-	return -EIO;
-}
-
-
-static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
-{
-	return I2C_FUNC_SMBUS_EMUL;
-}
-
-struct i2c_algorithm ddb_i2c_algo = {
-	.master_xfer   = ddb_i2c_master_xfer,
-	.functionality = ddb_i2c_functionality,
-};
-
-static void ddb_i2c_release(struct ddb *dev)
-{
-	int i;
-	struct ddb_i2c *i2c;
-	struct i2c_adapter *adap;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		i2c = &dev->i2c[i];
-		adap = &i2c->adap;
-		i2c_del_adapter(adap);
-	}
-}
-
-static int ddb_i2c_init(struct ddb *dev)
-{
-	int i, j, stat = 0;
-	struct ddb_i2c *i2c;
-	struct i2c_adapter *adap;
-
-	for (i = 0; i < dev->info->port_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,
-			  i2c->regs + I2C_TASKADDRESS);
-		init_waitqueue_head(&i2c->wq);
-
-		adap = &i2c->adap;
-		i2c_set_adapdata(adap, i2c);
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
-		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
-#else
-#ifdef I2C_CLASS_TV_ANALOG
-		adap->class = I2C_CLASS_TV_ANALOG;
-#endif
-#endif
-		strcpy(adap->name, "ddbridge");
-		adap->algo = &ddb_i2c_algo;
-		adap->algo_data = (void *)i2c;
-		adap->dev.parent = &dev->pdev->dev;
-		stat = i2c_add_adapter(adap);
-		if (stat)
-			break;
-	}
-	if (stat)
-		for (j = 0; j < i; j++) {
-			i2c = &dev->i2c[j];
-			adap = &i2c->adap;
-			i2c_del_adapter(adap);
-		}
-	return stat;
-}
-
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-#if 0
-static void set_table(struct ddb *dev, u32 off,
-		      dma_addr_t *pbuf, u32 num)
-{
-	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);
-	}
-}
-#endif
-
-static void ddb_address_table(struct ddb *dev)
-{
-	u32 i, j, base;
-	u64 mem;
-	dma_addr_t *pbuf;
-
-	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);
-		}
-	}
-}
-
-static void io_free(struct pci_dev *pdev, u8 **vbuf,
-		    dma_addr_t *pbuf, u32 size, int num)
-{
-	int i;
-
-	for (i = 0; i < num; i++) {
-		if (vbuf[i]) {
-			pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
-			vbuf[i] = 0;
-		}
-	}
-}
-
-static int io_alloc(struct pci_dev *pdev, u8 **vbuf,
-		    dma_addr_t *pbuf, u32 size, int num)
-{
-	int i;
-
-	for (i = 0; i < num; i++) {
-		vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
-		if (!vbuf[i])
-			return -ENOMEM;
-	}
-	return 0;
-}
-
-static int ddb_buffers_alloc(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		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)
-				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)
-				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)
-				return -1;
-			if (io_alloc(dev->pdev, port->output->vbuf,
-				     port->output->pbuf,
-				     port->output->dma_buf_size,
-				     port->output->dma_buf_num) < 0)
-				return -1;
-			break;
-		default:
-			break;
-		}
-	}
-	ddb_address_table(dev);
-	return 0;
-}
-
-static void ddb_buffers_free(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	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);
-	}
-}
-
-static void ddb_input_start(struct ddb_input *input)
-{
-	struct ddb *dev = input->port->dev;
-
-	spin_lock_irq(&input->lock);
-	input->cbuf = 0;
-	input->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);
-}
-
-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);
-}
-
-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);
-}
-
-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);
-}
-
-static u32 ddb_output_free(struct ddb_output *output)
-{
-	u32 idx, off, stat = output->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))
-			return 0;
-		return 188;
-	}
-	diff = off - output->coff;
-	if (diff <= 0 || diff > 188)
-		return 188;
-	return 0;
-}
-
-static ssize_t ddb_output_write(struct ddb_output *output,
-				const u8 *buf, size_t count)
-{
-	struct ddb *dev = output->port->dev;
-	u32 idx, off, stat = output->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) &&
-		    (off == 0)) {
-			if (len <= 188)
-				break;
-			len -= 188;
-		}
-		if (output->cbuf == idx) {
-			if (off > output->coff) {
-#if 1
-				len = off - output->coff;
-				len -= (len % 188);
-				if (len <= 188)
-
-#endif
-					break;
-				len -= 188;
-			}
-		}
-		if (len > left)
-			len = left;
-		if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
-				   buf, len))
-			return -EIO;
-		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);
-		}
-		ddbwritel((output->cbuf << 11) | (output->coff >> 7),
-			  DMA_BUFFER_ACK(output->nr + 8));
-	}
-	return count - left;
-}
-
-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));
-
-	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));
-		return 0;
-	}
-	if (input->cbuf != idx)
-		return 188;
-	return 0;
-}
-
-static ssize_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;
-	int ret;
-
-	idx = (stat >> 11) & 0x1f;
-
-	while (left) {
-		if (input->cbuf == idx)
-			return count - left;
-		free = input->dma_buf_size - input->coff;
-		if (free > left)
-			free = left;
-		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
-				   input->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;
-		}
-		left -= free;
-		ddbwritel((input->cbuf << 11) | (input->coff >> 7),
-			  DMA_BUFFER_ACK(input->nr));
-	}
-	return count;
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-#if 0
-static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
-{
-	int i;
-
-	for (i = 0; i < dev->info->port_num * 2; i++) {
-		if (dev->input[i].fe == fe)
-			return &dev->input[i];
-	}
-	return NULL;
-}
-#endif
-
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-	struct ddb_input *input = fe->sec_priv;
-	struct ddb_port *port = input->port;
-	int status;
-
-	if (enable) {
-		mutex_lock(&port->i2c_gate_lock);
-		status = input->gate_ctrl(fe, 1);
-	} else {
-		status = input->gate_ctrl(fe, 0);
-		mutex_unlock(&port->i2c_gate_lock);
-	}
-	return status;
-}
-
-static int demod_attach_drxk(struct ddb_input *input)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct dvb_frontend *fe;
-	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);
-
-	fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
-	if (!input->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;
-	return 0;
-}
-
-static int demod_attach_cxd2843(struct ddb_input *input)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct dvb_frontend *fe;
-	struct cxd2843_cfg cxd2843_0 = {
-		.adr = 0x6c,
-	};
-	struct cxd2843_cfg cxd2843_1 = {
-		.adr = 0x6d,
-	};
-
-	fe = input->fe = dvb_attach(cxd2843_attach, i2c,
-				  (input->nr & 1) ?
-				  &cxd2843_1 : &cxd2843_0);
-	if (!input->fe) {
-		pr_err("No cxd2837/38/43 found!\n");
-		return -ENODEV;
-	}
-	fe->sec_priv = input;
-	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
-	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-	return 0;
-}
-
-static int tuner_attach_tda18271(struct ddb_input *input)
-{
-	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 (!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 struct tda18212_config tda18212_config_60 = {
-	.i2c_address = 0x60,
-	.if_dvbt_6 = 3550,
-	.if_dvbt_7 = 3700,
-	.if_dvbt_8 = 4150,
-	.if_dvbt2_6 = 3250,
-	.if_dvbt2_7 = 4000,
-	.if_dvbt2_8 = 4000,
-	.if_dvbc = 5000,
-};
-
-static struct tda18212_config tda18212_config_63 = {
-	.i2c_address = 0x63,
-	.if_dvbt_6 = 3550,
-	.if_dvbt_7 = 3700,
-	.if_dvbt_8 = 4150,
-	.if_dvbt2_6 = 3250,
-	.if_dvbt2_7 = 4000,
-	.if_dvbt2_8 = 4000,
-	.if_dvbc = 5000,
-};
-
-static int tuner_attach_tda18212(struct ddb_input *input)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct dvb_frontend *fe;
-	struct tda18212_config *config;
-
-	if (input->nr & 1)
-		config = &tda18212_config_63;
-	else
-		config = &tda18212_config_60;
-
-	fe = dvb_attach(tda18212_attach, input->fe, i2c, config);
-	if (!fe) {
-		pr_err("No TDA18212 found!\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-static struct stv090x_config stv0900 = {
-	.device         = STV0900,
-	.demod_mode     = STV090x_DUAL,
-	.clk_mode       = STV090x_CLK_EXT,
-
-	.xtal           = 27000000,
-	.address        = 0x69,
-
-	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-
-	.repeater_level = STV090x_RPTLEVEL_16,
-
-	.adc1_range	= STV090x_ADC_1Vpp,
-	.adc2_range	= STV090x_ADC_1Vpp,
-
-	.diseqc_envelope_mode = true,
-};
-
-static struct stv090x_config stv0900_aa = {
-	.device         = STV0900,
-	.demod_mode     = STV090x_DUAL,
-	.clk_mode       = STV090x_CLK_EXT,
-
-	.xtal           = 27000000,
-	.address        = 0x68,
-
-	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
-
-	.repeater_level = STV090x_RPTLEVEL_16,
-
-	.adc1_range	= STV090x_ADC_1Vpp,
-	.adc2_range	= STV090x_ADC_1Vpp,
-
-	.diseqc_envelope_mode = true,
-};
-
-static struct stv6110x_config stv6110a = {
-	.addr    = 0x60,
-	.refclk	 = 27000000,
-	.clk_div = 1,
-};
-
-static struct stv6110x_config stv6110b = {
-	.addr    = 0x63,
-	.refclk	 = 27000000,
-	.clk_div = 1,
-};
-
-static int demod_attach_stv0900(struct ddb_input *input, int type)
-{
-	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->nr & 1) ? STV090x_DEMODULATOR_1
-			       : STV090x_DEMODULATOR_0);
-	if (!input->fe) {
-		printk(KERN_ERR "No STV0900 found!\n");
-		return -ENODEV;
-	}
-	if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
-			0, (input->nr & 1) ?
-			(0x09 - type) : (0x0b - type))) {
-		printk(KERN_ERR "No LNBH24 found!\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static int tuner_attach_stv6110(struct ddb_input *input, int type)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
-	struct stv6110x_config *tunerconf = (input->nr & 1) ?
-		&stv6110b : &stv6110a;
-	struct stv6110x_devctl *ctl;
-
-	ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
-	if (!ctl) {
-		printk(KERN_ERR "No STV6110X found!\n");
-		return -ENODEV;
-	}
-	printk(KERN_INFO "attach tuner input %d adr %02x\n",
-			 input->nr, tunerconf->addr);
-
-	feconf->tuner_init          = ctl->tuner_init;
-	feconf->tuner_sleep         = ctl->tuner_sleep;
-	feconf->tuner_set_mode      = ctl->tuner_set_mode;
-	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
-	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
-	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
-	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
-	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
-	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
-	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
-	feconf->tuner_get_status    = ctl->tuner_get_status;
-
-	return 0;
-}
-
-static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
-			    int (*start_feed)(struct dvb_demux_feed *),
-			    int (*stop_feed)(struct dvb_demux_feed *),
-			    void *priv)
-{
-	dvbdemux->priv = priv;
-
-	dvbdemux->filternum = 256;
-	dvbdemux->feednum = 256;
-	dvbdemux->start_feed = start_feed;
-	dvbdemux->stop_feed = stop_feed;
-	dvbdemux->write_to_decoder = NULL;
-	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
-				      DMX_SECTION_FILTERING |
-				      DMX_MEMORY_BASED_FILTERING);
-	return dvb_dmx_init(dvbdemux);
-}
-
-static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
-			       struct dvb_demux *dvbdemux,
-			       struct dmx_frontend *hw_frontend,
-			       struct dmx_frontend *mem_frontend,
-			       struct dvb_adapter *dvb_adapter)
-{
-	int ret;
-
-	dmxdev->filternum = 256;
-	dmxdev->demux = &dvbdemux->dmx;
-	dmxdev->capabilities = 0;
-	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
-	if (ret < 0)
-		return ret;
-
-	hw_frontend->source = DMX_FRONTEND_0;
-	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
-	mem_frontend->source = DMX_MEMORY_FE;
-	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
-	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
-}
-
-static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct ddb_input *input = dvbdmx->priv;
-
-	if (!input->users)
-		ddb_input_start(input);
-
-	return ++input->users;
-}
-
-static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
-	struct ddb_input *input = dvbdmx->priv;
-
-	if (--input->users)
-		return input->users;
-
-	ddb_input_stop(input);
-	return 0;
-}
-
-
-static void dvb_input_detach(struct ddb_input *input)
-{
-	struct dvb_adapter *adap = &input->adap;
-	struct dvb_demux *dvbdemux = &input->demux;
-
-	switch (input->attached) {
-	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;
-		}
-	case 4:
-		dvb_net_release(&input->dvbnet);
-
-	case 3:
-		dvbdemux->dmx.close(&dvbdemux->dmx);
-		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &input->hw_frontend);
-		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
-					      &input->mem_frontend);
-		dvb_dmxdev_release(&input->dmxdev);
-
-	case 2:
-		dvb_dmx_release(&input->demux);
-
-	case 1:
-		dvb_unregister_adapter(adap);
-	}
-	input->attached = 0;
-}
-
-static int dvb_input_attach(struct ddb_input *input)
-{
-	int ret;
-	struct ddb_port *port = input->port;
-	struct dvb_adapter *adap = &input->adap;
-	struct dvb_demux *dvbdemux = &input->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;
-
-	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
-				      start_feed,
-				      stop_feed, input);
-	if (ret < 0)
-		return ret;
-	input->attached = 2;
-
-	ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
-					 &input->hw_frontend,
-					 &input->mem_frontend, adap);
-	if (ret < 0)
-		return ret;
-	input->attached = 3;
-
-	ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
-	if (ret < 0)
-		return ret;
-	input->attached = 4;
-
-	input->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 (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_DVBCT2_SONY:
-	case DDB_TUNER_DVBC2T2_SONY:
-	case DDB_TUNER_ISDBT_SONY:
-		if (demod_attach_cxd2843(input) < 0)
-			return -ENODEV;
-		if (tuner_attach_tda18212(input) < 0)
-			return -ENODEV;
-		if (input->fe) {
-			if (dvb_register_frontend(adap, input->fe) < 0)
-				return -ENODEV;
-		}
-		break;
-	}
-	input->attached = 5;
-	return 0;
-}
-
-/****************************************************************************/
-/****************************************************************************/
-
-static ssize_t ts_write(struct file *file, const char *buf,
-			size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	size_t left = count;
-	int stat;
-
-	while (left) {
-		if (ddb_output_free(output) < 188) {
-			if (file->f_flags & O_NONBLOCK)
-				break;
-			if (wait_event_interruptible(
-				    output->wq, ddb_output_free(output) >= 188) < 0)
-				break;
-		}
-		stat = ddb_output_write(output, buf, left);
-		if (stat < 0)
-			break;
-		buf += stat;
-		left -= stat;
-	}
-	return (left == count) ? -EAGAIN : (count - left);
-}
-
-static ssize_t ts_read(struct file *file, char *buf,
-		       size_t count, loff_t *ppos)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	struct ddb_input *input = output->port->input[0];
-	int left, read;
-
-	count -= count % 188;
-	left = count;
-	while (left) {
-		if (ddb_input_avail(input) < 188) {
-			if (file->f_flags & O_NONBLOCK)
-				break;
-			if (wait_event_interruptible(
-				    input->wq, ddb_input_avail(input) >= 188) < 0)
-				break;
-		}
-		read = ddb_input_read(input, buf, left);
-		if (read < 0)
-			return read;
-		left -= read;
-		buf += read;
-	}
-	return (left == count) ? -EAGAIN : (count - left);
-}
-
-static unsigned int ts_poll(struct file *file, poll_table *wait)
-{
-	/*
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-	struct ddb_input *input = output->port->input[0];
-	*/
-	unsigned int mask = 0;
-
-#if 0
-	if (data_avail_to_read)
-		mask |= POLLIN | POLLRDNORM;
-	if (data_avail_to_write)
-		mask |= POLLOUT | POLLWRNORM;
-
-	poll_wait(file, &read_queue, wait);
-	poll_wait(file, &write_queue, wait);
-#endif
-	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 = {
-	.priv    = 0,
-	.readers = -1,
-	.writers = -1,
-	.users   = -1,
-	.fops    = &ci_fops,
-};
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static void input_tasklet(unsigned long data)
-{
-	struct ddb_input *input = (struct ddb_input *) data;
-	struct ddb *dev = input->port->dev;
-
-	spin_lock(&input->lock);
-	if (!input->running) {
-		spin_unlock(&input->lock);
-		return;
-	}
-	input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->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);
-}
-
-static void output_tasklet(unsigned long data)
-{
-	struct ddb_output *output = (struct ddb_output *) data;
-	struct ddb *dev = output->port->dev;
-
-	spin_lock(&output->lock);
-	if (!output->running) {
-		spin_unlock(&output->lock);
-		return;
-	}
-	output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
-	wake_up(&output->wq);
-	spin_unlock(&output->lock);
-}
-
-
-struct cxd2099_cfg cxd_cfg = {
-	.bitrate =  62000,
-	.adr     =  0x40,
-	.polarity = 1,
-	.clock_mode = 1,
-};
-
-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;
-	}
-	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;
-}
-
-static int ddb_port_attach(struct ddb_port *port)
-{
-	int ret = 0;
-
-	switch (port->class) {
-	case DDB_PORT_TUNER:
-		ret = dvb_input_attach(port->input[0]);
-		if (ret < 0)
-			break;
-		ret = dvb_input_attach(port->input[1]);
-		break;
-	case DDB_PORT_CI:
-		ret = ddb_ci_attach(port);
-		break;
-	default:
-		break;
-	}
-	if (ret < 0)
-		printk(KERN_ERR "port_attach on port %d failed\n", port->nr);
-	return ret;
-}
-
-static int ddb_ports_attach(struct ddb *dev)
-{
-	int i, ret = 0;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		ret = ddb_port_attach(port);
-		if (ret < 0)
-			break;
-	}
-	return ret;
-}
-
-static void ddb_ports_detach(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		switch (port->class) {
-		case DDB_PORT_TUNER:
-			dvb_input_detach(port->input[0]);
-			dvb_input_detach(port->input[1]);
-			break;
-		case DDB_PORT_CI:
-			if (port->output->dev)
-				dvb_unregister_device(port->output->dev);
-			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;
-		}
-	}
-}
-
-/****************************************************************************/
-/****************************************************************************/
-
-static int port_has_ci(struct ddb_port *port)
-{
-	u8 val;
-	return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
-}
-
-static int port_has_stv0900(struct ddb_port *port)
-{
-	u8 val;
-	if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
-		return 0;
-	return 1;
-}
-
-static int port_has_stv0900_aa(struct ddb_port *port)
-{
-	u8 val;
-	if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
-		return 0;
-	return 1;
-}
-
-static int port_has_drxks(struct ddb_port *port)
-{
-	u8 val;
-	if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
-		return 0;
-	if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
-		return 0;
-	return 1;
-}
-
-static int port_has_cxd28xx(struct ddb_port *port, u8 *id)
-{
-	int status;
-
-	status = i2c_write_reg(&port->i2c->adap, 0x6e, 0, 0);
-	if (status)
-		return 0;
-	status = i2c_read_reg(&port->i2c->adap, 0x6e, 0xfd, id);
-	if (status)
-		return 0;
-	return 1;
-}
-
-static void ddb_port_probe(struct ddb_port *port)
-{
-	struct ddb *dev = port->dev;
-	char *modname = "NO MODULE";
-	u8 id;
-
-	port->class = DDB_PORT_NONE;
-
-	if (port_has_ci(port)) {
-		modname = "CI";
-		port->class = DDB_PORT_CI;
-		ddbwritel(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);
-	} 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);
-	} 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);
-	} else if (port_has_cxd28xx(port, &id)) {
-		switch (id) {
-		case 0xa4:
-			modname = "DUAL DVB-C2T2 CXD2843";
-			port->type = DDB_TUNER_DVBC2T2_SONY;
-			break;
-		case 0xb1:
-			modname = "DUAL DVB-CT2 CXD2837";
-			port->type = DDB_TUNER_DVBCT2_SONY;
-			break;
-		case 0xb0:
-			modname = "DUAL ISDB-T CXD2838";
-			port->type = DDB_TUNER_ISDBT_SONY;
-			break;
-		default:
-			return;
-		}
-		port->class = DDB_PORT_TUNER;
-		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
-	}
-	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)
-{
-	struct ddb *dev = port->dev;
-	struct ddb_input *input = &dev->input[nr];
-
-	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);
-}
-
-static void ddb_output_init(struct ddb_port *port, int nr)
-{
-	struct ddb *dev = port->dev;
-	struct ddb_output *output = &dev->output[nr];
-	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);
-}
-
-static void ddb_ports_init(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	for (i = 0; i < dev->info->port_num; i++) {
-		port = &dev->port[i];
-		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);
-		ddb_output_init(port, i);
-	}
-}
-
-static void ddb_ports_release(struct ddb *dev)
-{
-	int i;
-	struct ddb_port *port;
-
-	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);
-	}
-}
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static void irq_handle_i2c(struct ddb *dev, int n)
-{
-	struct ddb_i2c *i2c = &dev->i2c[n];
-
-	i2c->done = 1;
-	wake_up(&i2c->wq);
-}
-
-static irqreturn_t irq_handler(int irq, void *dev_id)
-{
-	struct ddb *dev = (struct ddb *) dev_id;
-	u32 s = ddbreadl(INTERRUPT_STATUS);
-
-	if (!s)
-		return IRQ_NONE;
-
-	do {
-		ddbwritel(s, INTERRUPT_ACK);
-
-		if (s & 0x00000001)
-			irq_handle_i2c(dev, 0);
-		if (s & 0x00000002)
-			irq_handle_i2c(dev, 1);
-		if (s & 0x00000004)
-			irq_handle_i2c(dev, 2);
-		if (s & 0x00000008)
-			irq_handle_i2c(dev, 3);
-
-		if (s & 0x00000100)
-			tasklet_schedule(&dev->input[0].tasklet);
-		if (s & 0x00000200)
-			tasklet_schedule(&dev->input[1].tasklet);
-		if (s & 0x00000400)
-			tasklet_schedule(&dev->input[2].tasklet);
-		if (s & 0x00000800)
-			tasklet_schedule(&dev->input[3].tasklet);
-		if (s & 0x00001000)
-			tasklet_schedule(&dev->input[4].tasklet);
-		if (s & 0x00002000)
-			tasklet_schedule(&dev->input[5].tasklet);
-		if (s & 0x00004000)
-			tasklet_schedule(&dev->input[6].tasklet);
-		if (s & 0x00008000)
-			tasklet_schedule(&dev->input[7].tasklet);
-
-		if (s & 0x00010000)
-			tasklet_schedule(&dev->output[0].tasklet);
-		if (s & 0x00020000)
-			tasklet_schedule(&dev->output[1].tasklet);
-		if (s & 0x00040000)
-			tasklet_schedule(&dev->output[2].tasklet);
-		if (s & 0x00080000)
-			tasklet_schedule(&dev->output[3].tasklet);
-
-		/* if (s & 0x000f0000)	printk(KERN_DEBUG "%08x\n", istat); */
-	} while ((s = ddbreadl(INTERRUPT_STATUS)));
-
-	return IRQ_HANDLED;
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
-{
-	u32 data, shift;
-
-	if (wlen > 4)
-		ddbwritel(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)
-			;
-	}
-
-	if (rlen)
-		ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
-	else
-		ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
-
-	data = 0;
-	shift = ((4 - wlen) * 8);
-	while (wlen) {
-		data <<= 8;
-		data |= *wbuf;
-		wlen--;
-		wbuf++;
-	}
-	if (shift)
-		data <<= shift;
-	ddbwritel(data, SPI_DATA);
-	while (ddbreadl(SPI_CONTROL) & 0x0004)
-		;
-
-	if (!rlen) {
-		ddbwritel(0, SPI_CONTROL);
-		return 0;
-	}
-	if (rlen > 4)
-		ddbwritel(1, SPI_CONTROL);
-
-	while (rlen > 4) {
-		ddbwritel(0xffffffff, SPI_DATA);
-		while (ddbreadl(SPI_CONTROL) & 0x0004)
-			;
-		data = ddbreadl(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)
-		;
-
-	data = ddbreadl(SPI_DATA);
-	ddbwritel(0, SPI_CONTROL);
-
-	if (rlen < 4)
-		data <<= ((4 - rlen) * 8);
-
-	while (rlen > 0) {
-		*rbuf = ((data >> 24) & 0xff);
-		data <<= 8;
-		rbuf++;
-		rlen--;
-	}
-	return 0;
-}
-
-#define DDB_MAGIC 'd'
-
-struct ddb_flashio {
-	__u8 *write_buf;
-	__u32 write_len;
-	__u8 *read_buf;
-	__u32 read_len;
-};
-
-#define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
-
-#define DDB_NAME "ddbridge"
-
-static u32 ddb_num;
-static struct ddb *ddbs[32];
-static struct class *ddb_class;
-static int ddb_major;
-
-static int ddb_open(struct inode *inode, struct file *file)
-{
-	struct ddb *dev = ddbs[iminor(inode)];
-
-	file->private_data = dev;
-	return 0;
-}
-
-static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct ddb *dev = file->private_data;
-	void *parg = (void *)arg;
-	int res;
-
-	switch (cmd) {
-	case IOCTL_DDB_FLASHIO:
-	{
-		struct ddb_flashio fio;
-		u8 *rbuf, *wbuf;
-
-		if (copy_from_user(&fio, parg, sizeof(fio)))
-			return -EFAULT;
-
-		if (fio.write_len > 1028 || fio.read_len > 1028)
-			return -EINVAL;
-		if (fio.write_len + fio.read_len > 1028)
-			return -EINVAL;
-
-		wbuf = &dev->iobuf[0];
-		rbuf = wbuf + fio.write_len;
-
-		if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
-			return -EFAULT;
-		res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
-		if (res)
-			return res;
-		if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
-			return -EFAULT;
-		break;
-	}
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static const struct file_operations ddb_fops = {
-	.unlocked_ioctl = ddb_ioctl,
-	.open           = ddb_open,
-};
-
-static char *ddb_devnode(struct device *device, umode_t *mode)
-{
-	struct ddb *dev = dev_get_drvdata(device);
-
-	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
-}
-
-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);
-		return PTR_ERR(ddb_class);
-	}
-	ddb_class->devnode = ddb_devnode;
-	return 0;
-}
-
-static void ddb_class_destroy(void)
-{
-	class_destroy(ddb_class);
-	unregister_chrdev(ddb_major, DDB_NAME);
-}
-
-static int ddb_device_create(struct ddb *dev)
-{
-	dev->nr = ddb_num++;
-	dev->ddb_dev = device_create(ddb_class, NULL,
-				     MKDEV(ddb_major, dev->nr),
-				     dev, "ddbridge%d", dev->nr);
-	ddbs[dev->nr] = dev;
-	if (IS_ERR(dev->ddb_dev))
-		return -1;
-	return 0;
-}
-
-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));
-}
-
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
-static void ddb_unmap(struct ddb *dev)
-{
-	if (dev->regs)
-		iounmap(dev->regs);
-	vfree(dev);
-}
-
-
-static void ddb_remove(struct pci_dev *pdev)
-{
-	struct ddb *dev = pci_get_drvdata(pdev);
-
-	ddb_ports_detach(dev);
-	ddb_i2c_release(dev);
-
-	ddbwritel(0, INTERRUPT_ENABLE);
-	free_irq(dev->pdev->irq, dev);
-#ifdef CONFIG_PCI_MSI
-	if (dev->msi)
-		pci_disable_msi(dev->pdev);
-#endif
-	ddb_ports_release(dev);
-	ddb_buffers_free(dev);
-	ddb_device_destroy(dev);
-
-	ddb_unmap(dev);
-	pci_set_drvdata(pdev, 0);
-	pci_disable_device(pdev);
-}
-
-
-static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct ddb *dev;
-	int stat = 0;
-	int irq_flag = IRQF_SHARED;
-
-	if (pci_enable_device(pdev) < 0)
-		return -ENODEV;
-
-	dev = vmalloc(sizeof(struct ddb));
-	if (dev == NULL)
-		return -ENOMEM;
-	memset(dev, 0, sizeof(struct ddb));
-
-	dev->pdev = pdev;
-	pci_set_drvdata(pdev, dev);
-	dev->info = (struct ddb_info *) id->driver_data;
-	printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name);
-
-	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
-			    pci_resource_len(dev->pdev, 0));
-	if (!dev->regs) {
-		stat = -ENOMEM;
-		goto fail;
-	}
-	printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
-
-#ifdef CONFIG_PCI_MSI
-	if (pci_msi_enabled())
-		stat = pci_enable_msi(dev->pdev);
-	if (stat) {
-		printk(KERN_INFO ": MSI not available.\n");
-	} else {
-		irq_flag = 0;
-		dev->msi = 1;
-	}
-#endif
-	stat = request_irq(dev->pdev->irq, irq_handler,
-			   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);
-
-	if (ddb_i2c_init(dev) < 0)
-		goto fail1;
-	ddb_ports_init(dev);
-	if (ddb_buffers_alloc(dev) < 0) {
-		printk(KERN_INFO ": Could not allocate buffer memory\n");
-		goto fail2;
-	}
-	if (ddb_ports_attach(dev) < 0)
-		goto fail3;
-	ddb_device_create(dev);
-	return 0;
-
-fail3:
-	ddb_ports_detach(dev);
-	printk(KERN_ERR "fail3\n");
-	ddb_ports_release(dev);
-fail2:
-	printk(KERN_ERR "fail2\n");
-	ddb_buffers_free(dev);
-fail1:
-	printk(KERN_ERR "fail1\n");
-	if (dev->msi)
-		pci_disable_msi(dev->pdev);
-	free_irq(dev->pdev->irq, dev);
-fail:
-	printk(KERN_ERR "fail\n");
-	ddb_unmap(dev);
-	pci_set_drvdata(pdev, 0);
-	pci_disable_device(pdev);
-	return -1;
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/******************************************************************************/
-
-static struct ddb_info ddb_none = {
-	.type     = DDB_NONE,
-	.name     = "Digital Devices PCIe bridge",
-};
-
-static struct ddb_info ddb_octopus = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Octopus DVB adapter",
-	.port_num = 4,
-};
-
-static struct ddb_info ddb_octopus_le = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Octopus LE DVB adapter",
-	.port_num = 2,
-};
-
-static struct ddb_info ddb_octopus_mini = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Octopus Mini",
-	.port_num = 4,
-};
-
-static struct ddb_info ddb_v6 = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Cine S2 V6 DVB adapter",
-	.port_num = 3,
-};
-static struct ddb_info ddb_v6_5 = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Cine S2 V6.5 DVB adapter",
-	.port_num = 4,
-};
-
-static struct ddb_info ddb_dvbct = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices DVBCT V6.1 DVB adapter",
-	.port_num = 3,
-};
-
-static struct ddb_info ddb_satixS2v3 = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Mystique SaTiX-S2 V3 DVB adapter",
-	.port_num = 3,
-};
-
-static struct ddb_info ddb_octopusv3 = {
-	.type     = DDB_OCTOPUS,
-	.name     = "Digital Devices Octopus V3 DVB adapter",
-	.port_num = 4,
-};
-
-#define DDVID 0xdd01 /* Digital Devices Vendor ID */
-
-#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {	\
-	.vendor      = _vend,    .device    = _dev, \
-	.subvendor   = _subvend, .subdevice = _subdev, \
-	.driver_data = (unsigned long)&_driverdata }
-
-static const struct pci_device_id ddb_id_tbl[] = {
-	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_mini),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
-	DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
-	DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
-	DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
-	/* in case sub-ids got deleted in flash */
-	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
-	{0}
-};
-MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
-
-
-static struct pci_driver ddb_pci_driver = {
-	.name        = "DDBridge",
-	.id_table    = ddb_id_tbl,
-	.probe       = ddb_probe,
-	.remove      = ddb_remove,
-};
-
-static __init int module_init_ddbridge(void)
-{
-	int ret;
-
-	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
-	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
-
-	ret = ddb_class_create();
-	if (ret < 0)
-		return ret;
-	ret = pci_register_driver(&ddb_pci_driver);
-	if (ret < 0)
-		ddb_class_destroy();
-	return ret;
-}
-
-static __exit void module_exit_ddbridge(void)
-{
-	pci_unregister_driver(&ddb_pci_driver);
-	ddb_class_destroy();
-}
-
-module_init(module_init_ddbridge);
-module_exit(module_exit_ddbridge);
-
-MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
-MODULE_AUTHOR("Ralph Metzler");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.5");
diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h
deleted file mode 100644
index a3ccb31..0000000
--- a/drivers/media/pci/ddbridge/ddbridge-regs.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * ddbridge-regs.h: Digital Devices PCIe bridge driver
- *
- * Copyright (C) 2010-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
- */
-
-/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */
-
-/* Register Definitions */
-
-#define CUR_REGISTERMAP_VERSION 0x10000
-
-#define HARDWARE_VERSION       0x00
-#define REGISTERMAP_VERSION    0x04
-
-/* ------------------------------------------------------------------------- */
-/* SPI Controller */
-
-#define SPI_CONTROL     0x10
-#define SPI_DATA        0x14
-
-/* ------------------------------------------------------------------------- */
-
-/* Interrupt controller                                     */
-/* How many MSI's are available depends on HW (Min 2 max 8) */
-/* How many are usable also depends on Host platform        */
-
-#define INTERRUPT_BASE   (0x40)
-
-#define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
-#define MSI0_ENABLE      (INTERRUPT_BASE + 0x00)
-#define MSI1_ENABLE      (INTERRUPT_BASE + 0x04)
-#define MSI2_ENABLE      (INTERRUPT_BASE + 0x08)
-#define MSI3_ENABLE      (INTERRUPT_BASE + 0x0C)
-#define MSI4_ENABLE      (INTERRUPT_BASE + 0x10)
-#define MSI5_ENABLE      (INTERRUPT_BASE + 0x14)
-#define MSI6_ENABLE      (INTERRUPT_BASE + 0x18)
-#define MSI7_ENABLE      (INTERRUPT_BASE + 0x1C)
-
-#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
-#define INTERRUPT_ACK    (INTERRUPT_BASE + 0x20)
-
-#define INTMASK_I2C1        (0x00000001)
-#define INTMASK_I2C2        (0x00000002)
-#define INTMASK_I2C3        (0x00000004)
-#define INTMASK_I2C4        (0x00000008)
-
-#define INTMASK_CIRQ1       (0x00000010)
-#define INTMASK_CIRQ2       (0x00000020)
-#define INTMASK_CIRQ3       (0x00000040)
-#define INTMASK_CIRQ4       (0x00000080)
-
-#define INTMASK_TSINPUT1    (0x00000100)
-#define INTMASK_TSINPUT2    (0x00000200)
-#define INTMASK_TSINPUT3    (0x00000400)
-#define INTMASK_TSINPUT4    (0x00000800)
-#define INTMASK_TSINPUT5    (0x00001000)
-#define INTMASK_TSINPUT6    (0x00002000)
-#define INTMASK_TSINPUT7    (0x00004000)
-#define INTMASK_TSINPUT8    (0x00008000)
-
-#define INTMASK_TSOUTPUT1   (0x00010000)
-#define INTMASK_TSOUTPUT2   (0x00020000)
-#define INTMASK_TSOUTPUT3   (0x00040000)
-#define INTMASK_TSOUTPUT4   (0x00080000)
-
-/* ------------------------------------------------------------------------- */
-/* I2C Master Controller */
-
-#define I2C_BASE        (0x80)  /* Byte offset */
-
-#define I2C_COMMAND     (0x00)
-#define I2C_TIMING      (0x04)
-#define I2C_TASKLENGTH  (0x08)     /* High read, low write */
-#define I2C_TASKADDRESS (0x0C)     /* High read, low write */
-
-#define I2C_MONITOR     (0x1C)
-
-#define I2C_BASE_1      (I2C_BASE + 0x00)
-#define I2C_BASE_2      (I2C_BASE + 0x20)
-#define I2C_BASE_3      (I2C_BASE + 0x40)
-#define I2C_BASE_4      (I2C_BASE + 0x60)
-
-#define I2C_BASE_N(i)   (I2C_BASE + (i) * 0x20)
-
-#define I2C_TASKMEM_BASE    (0x1000)    /* Byte offset */
-#define I2C_TASKMEM_SIZE    (0x1000)
-
-#define I2C_SPEED_400   (0x04030404)
-#define I2C_SPEED_200   (0x09080909)
-#define I2C_SPEED_154   (0x0C0B0C0C)
-#define I2C_SPEED_100   (0x13121313)
-#define I2C_SPEED_77    (0x19181919)
-#define I2C_SPEED_50    (0x27262727)
-
-
-/* ------------------------------------------------------------------------- */
-/* DMA  Controller */
-
-#define DMA_BASE_WRITE        (0x100)
-#define DMA_BASE_READ         (0x140)
-
-#define DMA_CONTROL     (0x00)                  /* 64 */
-#define DMA_ERROR       (0x04)                  /* 65 ( only read instance ) */
-
-#define DMA_DIAG_CONTROL                (0x1C)  /* 71 */
-#define DMA_DIAG_PACKETCOUNTER_LOW      (0x20)  /* 72 */
-#define DMA_DIAG_PACKETCOUNTER_HIGH     (0x24)  /* 73 */
-#define DMA_DIAG_TIMECOUNTER_LOW        (0x28)  /* 74 */
-#define DMA_DIAG_TIMECOUNTER_HIGH       (0x2C)  /* 75 */
-#define DMA_DIAG_RECHECKCOUNTER         (0x30)  /* 76  ( Split completions on read ) */
-#define DMA_DIAG_WAITTIMEOUTINIT        (0x34)  /* 77 */
-#define DMA_DIAG_WAITOVERFLOWCOUNTER    (0x38)  /* 78 */
-#define DMA_DIAG_WAITCOUNTER            (0x3C)  /* 79 */
-
-/* ------------------------------------------------------------------------- */
-/* DMA  Buffer */
-
-#define TS_INPUT_BASE       (0x200)
-#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 16 + 0x00)
-
-#define TS_OUTPUT_BASE       (0x280)
-#define TS_OUTPUT_CONTROL(i)         (TS_OUTPUT_BASE + (i) * 16 + 0x00)
-
-#define DMA_BUFFER_BASE     (0x300)
-
-#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x00)
-#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 16 + 0x04)
-#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x08)
-#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 16 + 0x0c)
-
-#define DMA_BASE_ADDRESS_TABLE  (0x2000)
-#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
-
diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
deleted file mode 100644
index 04c56c2..0000000
--- a/drivers/media/pci/ddbridge/ddbridge.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * ddbridge.h: Digital Devices PCIe bridge driver
- *
- * Copyright (C) 2010-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
- */
-
-#ifndef _DDBRIDGE_H_
-#define _DDBRIDGE_H_
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <asm/dma.h>
-#include <linux/dvb/frontend.h>
-#include <linux/dvb/ca.h>
-#include <linux/socket.h>
-
-#include "dmxdev.h"
-#include "dvbdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_ringbuffer.h"
-#include "dvb_ca_en50221.h"
-#include "dvb_net.h"
-#include "cxd2099.h"
-
-#define DDB_MAX_I2C     4
-#define DDB_MAX_PORT    4
-#define DDB_MAX_INPUT   8
-#define DDB_MAX_OUTPUT  4
-
-struct ddb_info {
-	int   type;
-#define DDB_NONE         0
-#define DDB_OCTOPUS      1
-	char *name;
-	int   port_num;
-	u32   port_type[DDB_MAX_PORT];
-};
-
-/* DMA_SIZE MUST be divisible by 188 and 128 !!! */
-
-#define INPUT_DMA_MAX_BUFS 32      /* hardware table limit */
-#define INPUT_DMA_BUFS 8
-#define INPUT_DMA_SIZE (128*47*21)
-
-#define OUTPUT_DMA_MAX_BUFS 32
-#define OUTPUT_DMA_BUFS 8
-#define OUTPUT_DMA_SIZE (128*47*21)
-
-struct ddb;
-struct ddb_port;
-
-struct ddb_input {
-	struct ddb_port       *port;
-	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;
-
-	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 dvb_frontend   *fe;
-	struct dvb_frontend   *fe2;
-	struct dmxdev          dmxdev;
-	struct dvb_demux       demux;
-	struct dvb_net         dvbnet;
-	struct dmx_frontend    hw_frontend;
-	struct dmx_frontend    mem_frontend;
-	int                    users;
-	int (*gate_ctrl)(struct dvb_frontend *, int);
-};
-
-struct ddb_output {
-	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_i2c {
-	struct ddb            *dev;
-	u32                    nr;
-	struct i2c_adapter     adap;
-	struct i2c_adapter     adap2;
-	u32                    regs;
-	u32                    rbuf;
-	u32                    wbuf;
-	int                    done;
-	wait_queue_head_t      wq;
-};
-
-struct ddb_port {
-	struct ddb            *dev;
-	u32                    nr;
-	struct ddb_i2c        *i2c;
-	struct mutex           i2c_gate_lock;
-	u32                    class;
-#define DDB_PORT_NONE           0
-#define DDB_PORT_CI             1
-#define DDB_PORT_TUNER          2
-	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_DVBCT2_SONY  18
-#define DDB_TUNER_ISDBT_SONY   19
-#define DDB_TUNER_DVBC2T2_SONY 20
-	u32                    adr;
-
-	struct ddb_input      *input[2];
-	struct ddb_output     *output;
-	struct dvb_ca_en50221 *en;
-};
-
-struct ddb {
-	struct pci_dev        *pdev;
-	unsigned char         *regs;
-	struct ddb_port        port[DDB_MAX_PORT];
-	struct ddb_i2c         i2c[DDB_MAX_I2C];
-	struct ddb_input       input[DDB_MAX_INPUT];
-	struct ddb_output      output[DDB_MAX_OUTPUT];
-
-	struct device         *ddb_dev;
-	int                    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))
-
-/****************************************************************************/
-
-#endif
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/5] ddbridge: add needed files from manufacturer driver 0.9.15a
  2014-08-02  3:48 [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Antti Palosaari
                   ` (2 preceding siblings ...)
  2014-08-02  3:48 ` [PATCH 3/5] ddbridge: remove driver temporarily Antti Palosaari
@ 2014-08-02  3:48 ` Antti Palosaari
  2014-08-02  3:48 ` [PATCH 5/5] ddbridge: clean up driver for release Antti Palosaari
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2014-08-02  3:48 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 144585 bytes --]

Add files:
ddbridge.c
ddbridge-core.c
ddbridge.h
ddbridge-i2c.c
ddbridge-regs.h

These files are taken, without any modification, from the latest
Digital Devices (device manufacturer) Linux driver version 0.9.15a.

md5sum dddvb-0.9.15a.tar.bz2 e7f313ce5b548aeb55d168ad8b34b91a

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/pci/ddbridge/ddbridge-core.c | 3735 ++++++++++++++++++++++++++++
 drivers/media/pci/ddbridge/ddbridge-i2c.c  |  257 ++
 drivers/media/pci/ddbridge/ddbridge-regs.h |  436 ++++
 drivers/media/pci/ddbridge/ddbridge.c      |  460 ++++
 drivers/media/pci/ddbridge/ddbridge.h      |  499 ++++
 5 files changed, 5387 insertions(+)
 create mode 100644 drivers/media/pci/ddbridge/ddbridge-core.c
 create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c
 create mode 100644 drivers/media/pci/ddbridge/ddbridge-regs.h
 create mode 100644 drivers/media/pci/ddbridge/ddbridge.c
 create mode 100644 drivers/media/pci/ddbridge/ddbridge.h

diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
new file mode 100644
index 0000000..a301be6
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -0,0 +1,3735 @@
+/*
+ * ddbridge-core.c: Digital Devices bridge core functions
+ *
+ * Copyright (C) 2010-2013 Digital Devices GmbH
+ *                         Ralph Metzler <rmetzler@digitaldevices.de>
+ *
+ * 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
+ */
+
+DEFINE_MUTEX(redirect_lock);
+
+static int ci_bitrate = 72000;
+module_param(ci_bitrate, int, 0444);
+MODULE_PARM_DESC(ci_bitrate, " Bitrate for output to CI.");
+
+static int ts_loop = -1;
+module_param(ts_loop, int, 0444);
+MODULE_PARM_DESC(ts_loop, "TS in/out test loop on port ts_loop");
+
+static int vlan;
+module_param(vlan, int, 0444);
+MODULE_PARM_DESC(vlan, "VLAN and QoS IDs enabled");
+
+static int tt;
+module_param(tt, int, 0444);
+MODULE_PARM_DESC(tt, "");
+
+#define DDB_MAX_ADAPTER 32
+static struct ddb *ddbs[DDB_MAX_ADAPTER];
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#include "ddbridge-mod.c"
+#include "ddbridge-i2c.c"
+#include "ddbridge-ns.c"
+
+
+static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma)
+{
+	u32 i, base;
+	u64 mem;
+
+	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);
+}
+
+static void ddb_set_dma_tables(struct ddb *dev)
+{
+	u32 i;
+
+	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 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 int ddb_unredirect(struct ddb_port *port)
+{
+	struct ddb_input *oredi, *iredi = 0;
+	struct ddb_output *iredo = 0;
+
+	/*pr_info("unredirect %d.%d\n", port->dev->nr, port->nr);*/
+	mutex_lock(&redirect_lock);
+	if (port->output->dma->running) {
+		mutex_unlock(&redirect_lock);
+		return -EBUSY;
+	}
+	oredi = port->output->redi;
+	if (!oredi)
+		goto done;
+	if (port->input[0]) {
+		iredi = port->input[0]->redi;
+		iredo = port->input[0]->redo;
+
+		if (iredo) {
+			iredo->port->output->redi = oredi;
+			if (iredo->port->input[0]) {
+				iredo->port->input[0]->redi = iredi;
+				ddb_redirect_dma(oredi->port->dev,
+						 oredi->dma, iredo->dma);
+			}
+			port->input[0]->redo = 0;
+			ddb_set_dma_table(port->dev, port->input[0]->dma);
+		}
+		oredi->redi = iredi;
+		port->input[0]->redi = 0;
+	}
+	oredi->redo = 0;
+	port->output->redi = 0;
+
+	ddb_set_dma_table(oredi->port->dev, oredi->dma);
+done:
+	mutex_unlock(&redirect_lock);
+	return 0;
+}
+
+static int ddb_redirect(u32 i, u32 p)
+{
+	struct ddb *idev = ddbs[(i >> 4) & 0x1f];
+	struct ddb_input *input, *input2;
+	struct ddb *pdev = ddbs[(p >> 4) & 0x1f];
+	struct ddb_port *port;
+
+	if (!idev->has_dma || !pdev->has_dma)
+		return -EINVAL;
+	if (!idev || !pdev)
+		return -EINVAL;
+
+	port = &pdev->port[p & 0x0f];
+	if (!port->output)
+		return -EINVAL;
+	if (ddb_unredirect(port))
+		return -EBUSY;
+
+	if (i == 8)
+		return 0;
+
+	input = &idev->input[i & 7];
+	if (!input)
+		return -EINVAL;
+
+	mutex_lock(&redirect_lock);
+	if (port->output->dma->running || input->dma->running) {
+		mutex_unlock(&redirect_lock);
+		return -EBUSY;
+	}
+	input2 = port->input[0];
+	if (input2) {
+		if (input->redi) {
+			input2->redi = input->redi;
+			input->redi = 0;
+		} else
+			input2->redi = input;
+	}
+	input->redo = port->output;
+	port->output->redi = input;
+
+	ddb_redirect_dma(input->port->dev, input->dma, port->output->dma);
+	mutex_unlock(&redirect_lock);
+	return 0;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+#ifdef DDB_ALT_DMA
+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
+{
+	int i;
+
+	if (!dma)
+		return;
+	for (i = 0; i < dma->num; i++) {
+		if (dma->vbuf[i]) {
+			dma_unmap_single(&pdev->dev, dma->pbuf[i],
+					 dma->size,
+					 dir ? DMA_TO_DEVICE :
+					 DMA_FROM_DEVICE);
+			kfree(dma->vbuf[i]);
+			dma->vbuf[i] = 0;
+		}
+	}
+}
+
+static int dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
+{
+	int i;
+
+	if (!dma)
+		return 0;
+	for (i = 0; i < dma->num; i++) {
+		dma->vbuf[i] = kmalloc(dma->size, __GFP_REPEAT);
+		if (!dma->vbuf[i])
+			return -ENOMEM;
+		dma->pbuf[i] = dma_map_single(&pdev->dev, dma->vbuf[i],
+					      dma->size,
+					      dir ? DMA_TO_DEVICE :
+					      DMA_FROM_DEVICE);
+		if (dma_mapping_error(&pdev->dev, dma->pbuf[i])) {
+			kfree(dma->vbuf[i]);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+#else
+
+static void dma_free(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
+{
+	int i;
+
+	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 dma_alloc(struct pci_dev *pdev, struct ddb_dma *dma, int dir)
+{
+	int 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;
+}
+#endif
+
+static int ddb_buffers_alloc(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		switch (port->class) {
+		case DDB_PORT_TUNER:
+			if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0)
+				return -1;
+			if (dma_alloc(dev->pdev, port->input[1]->dma, 0) < 0)
+				return -1;
+			break;
+		case DDB_PORT_CI:
+		case DDB_PORT_LOOP:
+			if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0)
+				return -1;
+		case DDB_PORT_MOD:
+			if (dma_alloc(dev->pdev, port->output->dma, 1) < 0)
+				return -1;
+			break;
+		default:
+			break;
+		}
+	}
+	ddb_set_dma_tables(dev);
+	return 0;
+}
+
+static void ddb_buffers_free(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+
+		if (port->input[0])
+			dma_free(dev->pdev, port->input[0]->dma, 0);
+		if (port->input[1])
+			dma_free(dev->pdev, port->input[1]->dma, 0);
+		if (port->output)
+			dma_free(dev->pdev, port->output->dma, 1);
+	}
+}
+
+static void ddb_output_start(struct ddb_output *output)
+{
+	struct ddb *dev = output->port->dev;
+	u32 con2;
+
+	con2 = ((output->port->obr << 13) + 71999) / 72000;
+	con2 = (con2 << 16) | output->port->gap;
+
+	if (output->dma) {
+		spin_lock_irq(&output->dma->lock);
+		output->dma->cbuf = 0;
+		output->dma->coff = 0;
+		output->dma->stat = 0;
+		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr));
+	}
+	if (output->port->class == DDB_PORT_MOD)
+		ddbridge_mod_output_start(output);
+	else {
+		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, con2, TS_OUTPUT_CONTROL2(output->nr));
+	}
+	if (output->dma) {
+		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->class != DDB_PORT_MOD) {
+		if (output->port->input[0]->port->class == DDB_PORT_LOOP)
+			/*ddbwritel(dev, 0x15, TS_OUTPUT_CONTROL(output->nr));
+			  ddbwritel(dev, 0x45,
+			  TS_OUTPUT_CONTROL(output->nr));*/
+			ddbwritel(dev, (1 << 13) | 0x15,
+				  TS_OUTPUT_CONTROL(output->nr));
+		else
+			ddbwritel(dev, 0x1d, TS_OUTPUT_CONTROL(output->nr));
+	}
+	if (output->dma) {
+		output->dma->running = 1;
+		spin_unlock_irq(&output->dma->lock);
+	}
+}
+
+static void ddb_output_stop(struct ddb_output *output)
+{
+	struct ddb *dev = output->port->dev;
+
+	if (output->dma)
+		spin_lock_irq(&output->dma->lock);
+	if (output->port->class == DDB_PORT_MOD)
+		ddbridge_mod_output_stop(output);
+	else
+		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
+	if (output->dma) {
+		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr));
+		output->dma->running = 0;
+		spin_unlock_irq(&output->dma->lock);
+	}
+}
+
+static void ddb_input_stop(struct ddb_input *input)
+{
+	struct ddb *dev = input->port->dev;
+
+	if (input->dma)
+		spin_lock_irq(&input->dma->lock);
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+	if (input->dma) {
+		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr));
+		input->dma->running = 0;
+		spin_unlock_irq(&input->dma->lock);
+	}
+	/*pr_info("input_stop %d.%d\n", dev->nr, input->nr);*/
+}
+
+static void ddb_input_start(struct ddb_input *input)
+{
+	struct ddb *dev = input->port->dev;
+
+	if (input->dma) {
+		spin_lock_irq(&input->dma->lock);
+		input->dma->cbuf = 0;
+		input->dma->coff = 0;
+		input->dma->stat = 0;
+		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(input->dma->nr));
+	}
+	ddbwritel(dev, 0, TS_INPUT_CONTROL2(input->nr));
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(dev, 2, TS_INPUT_CONTROL(input->nr));
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(input->nr));
+
+	if (input->dma) {
+		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));
+	}
+	if (dev->info->type == DDB_OCTONET)
+		ddbwritel(dev, 0x01, TS_INPUT_CONTROL(input->nr));
+	else
+		ddbwritel(dev, 0x09, TS_INPUT_CONTROL(input->nr));
+	if (input->dma) {
+		input->dma->running = 1;
+		spin_unlock_irq(&input->dma->lock);
+	}
+	/*pr_info("input_start %d.%d\n", dev->nr, input->nr);*/
+}
+
+
+static int ddb_dvb_input_start(struct ddb_input *input)
+{
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+
+	if (!dvb->users)
+		ddb_input_start(input);
+
+	return ++dvb->users;
+}
+
+static int ddb_dvb_input_stop(struct ddb_input *input)
+{
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+
+	if (--dvb->users)
+		return dvb->users;
+
+	ddb_input_stop(input);
+	return 0;
+}
+
+static void ddb_input_start_all(struct ddb_input *input)
+{
+	struct ddb_input *i = input;
+	struct ddb_output *o;
+
+	mutex_lock(&redirect_lock);
+	while (i && (o = i->redo)) {
+		ddb_output_start(o);
+		i = o->port->input[0];
+		if (i)
+			ddb_input_start(i);
+	}
+	ddb_input_start(input);
+	mutex_unlock(&redirect_lock);
+}
+
+static void ddb_input_stop_all(struct ddb_input *input)
+{
+	struct ddb_input *i = input;
+	struct ddb_output *o;
+
+	mutex_lock(&redirect_lock);
+	ddb_input_stop(input);
+	while (i && (o = i->redo)) {
+		ddb_output_stop(o);
+		i = o->port->input[0];
+		if (i)
+			ddb_input_stop(i);
+	}
+	mutex_unlock(&redirect_lock);
+}
+
+static u32 ddb_output_free(struct ddb_output *output)
+{
+	u32 idx, off, stat = output->dma->stat;
+	s32 diff;
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	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->dma->coff;
+	if (diff <= 0 || diff > 188)
+		return 188;
+	return 0;
+}
+
+#if 0
+static u32 ddb_dma_free(struct ddb_dma *dma)
+{
+	u32 idx, off, stat = dma->stat;
+	s32 p1, p2, diff;
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	p1 = idx * dma->size + off;
+	p2 = dma->cbuf * dma->size + dma->coff;
+
+	diff = p1 - p2;
+	if (diff <= 0)
+		diff += dma->num * dma->size;
+	return diff;
+}
+#endif
+
+static ssize_t ddb_output_write(struct ddb_output *output,
+				const u8 *buf, size_t count)
+{
+	struct ddb *dev = output->port->dev;
+	u32 idx, off, stat = output->dma->stat;
+	u32 left = count, len;
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	while (left) {
+		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->dma->cbuf == idx) {
+			if (off > output->dma->coff) {
+				len = off - output->dma->coff;
+				len -= (len % 188);
+				if (len <= 188)
+					break;
+				len -= 188;
+			}
+		}
+		if (len > left)
+			len = left;
+		if (copy_from_user(output->dma->vbuf[output->dma->cbuf] +
+				   output->dma->coff,
+				   buf, len))
+			return -EIO;
+#ifdef DDB_ALT_DMA
+		dma_sync_single_for_device(dev->dev,
+					   output->dma->pbuf[
+						   output->dma->cbuf],
+					   output->dma->size, DMA_TO_DEVICE);
+#endif
+		left -= len;
+		buf += len;
+		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(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->dma->stat;
+	u32 ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(input->dma->nr));
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	if (ctrl & 4) {
+		pr_err("IA %d %d %08x\n", idx, off, ctrl);
+		ddbwritel(dev, stat, DMA_BUFFER_ACK(input->dma->nr));
+		return 0;
+	}
+	if (input->dma->cbuf != idx)
+		return 188;
+	return 0;
+}
+
+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, off, free, stat = input->dma->stat;
+	int ret;
+
+	idx = (stat >> 11) & 0x1f;
+	off = (stat & 0x7ff) << 7;
+
+	while (left) {
+		if (input->dma->cbuf == idx)
+			return count - left;
+		free = input->dma->size - input->dma->coff;
+		if (free > left)
+			free = left;
+#ifdef DDB_ALT_DMA
+		dma_sync_single_for_cpu(dev->dev,
+					input->dma->pbuf[input->dma->cbuf],
+					input->dma->size, DMA_FROM_DEVICE);
+#endif
+		ret = copy_to_user(buf, input->dma->vbuf[input->dma->cbuf] +
+				   input->dma->coff, free);
+		if (ret)
+			return -EFAULT;
+		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(dev,
+			  (input->dma->cbuf << 11) | (input->dma->coff >> 7),
+			  DMA_BUFFER_ACK(input->dma->nr));
+	}
+	return count;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+
+static ssize_t ts_write(struct file *file, const char *buf,
+			size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb *dev = output->port->dev;
+	size_t left = count;
+	int stat;
+
+	if (!dev->has_dma)
+		return -EINVAL;
+	while (left) {
+		if (ddb_output_free(output) < 188) {
+			if (file->f_flags & O_NONBLOCK)
+				break;
+			if (wait_event_interruptible(
+				    output->dma->wq,
+				    ddb_output_free(output) >= 188) < 0)
+				break;
+		}
+		stat = ddb_output_write(output, buf, left);
+		if (stat < 0)
+			return stat;
+		buf += stat;
+		left -= stat;
+	}
+	return (left == count) ? -EAGAIN : (count - left);
+}
+
+static ssize_t ts_read(struct file *file, char *buf,
+		       size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+	struct ddb *dev = output->port->dev;
+	size_t left = count;
+	int stat;
+
+	if (!dev->has_dma)
+		return -EINVAL;
+	while (left) {
+		if (ddb_input_avail(input) < 188) {
+			if (file->f_flags & O_NONBLOCK)
+				break;
+			if (wait_event_interruptible(
+				    input->dma->wq,
+				    ddb_input_avail(input) >= 188) < 0)
+				break;
+		}
+		stat = ddb_input_read(input, buf, left);
+		if (stat < 0)
+			return stat;
+		left -= stat;
+		buf += stat;
+	}
+	return (count && (left == count)) ? -EAGAIN : (count - left);
+}
+
+static unsigned int ts_poll(struct file *file, poll_table *wait)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+	struct ddb_input *input = output->port->input[0];
+
+	unsigned int mask = 0;
+
+	poll_wait(file, &input->dma->wq, wait);
+	poll_wait(file, &output->dma->wq, wait);
+	if (ddb_input_avail(input) >= 188)
+		mask |= POLLIN | POLLRDNORM;
+	if (ddb_output_free(output) >= 188)
+		mask |= POLLOUT | POLLWRNORM;
+	return mask;
+}
+
+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];
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		if (!input)
+			return -EINVAL;
+		ddb_input_stop(input);
+	} else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		if (!output)
+			return -EINVAL;
+		ddb_output_stop(output);
+	}
+	return dvb_generic_release(inode, file);
+}
+
+static 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];
+
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
+		if (!input)
+			return -EINVAL;
+		if (input->redo || input->redi)
+			return -EBUSY;
+	} else if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		if (!output)
+			return -EINVAL;
+	}
+	err = dvb_generic_open(inode, file);
+	if (err < 0)
+		return err;
+	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+		ddb_input_start(input);
+	else if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+		ddb_output_start(output);
+	return err;
+}
+
+static int mod_release(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		if (!output)
+			return -EINVAL;
+		ddb_output_stop(output);
+	}
+	return dvb_generic_release(inode, file);
+}
+
+static int mod_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb_output *output = dvbdev->priv;
+
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
+		if (!output)
+			return -EINVAL;
+	}
+	err = dvb_generic_open(inode, file);
+	if (err < 0)
+		return err;
+	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
+		ddb_output_start(output);
+	return err;
+}
+static const struct file_operations ci_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ts_read,
+	.write   = ts_write,
+	.open    = ts_open,
+	.release = ts_release,
+	.poll    = ts_poll,
+	.mmap    = 0,
+};
+
+static struct dvb_device dvbdev_ci = {
+	.priv    = 0,
+	.readers = 1,
+	.writers = 1,
+	.users   = 2,
+	.fops    = &ci_fops,
+};
+
+
+/****************************************************************************/
+/****************************************************************************/
+
+static long mod_ioctl(struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
+}
+
+static const struct file_operations mod_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ts_read,
+	.write   = ts_write,
+	.open    = mod_open,
+	.release = mod_release,
+	.poll    = ts_poll,
+	.mmap    = 0,
+	.unlocked_ioctl = mod_ioctl,
+};
+
+static struct dvb_device dvbdev_mod = {
+	.priv    = 0,
+	.readers = 1,
+	.writers = 1,
+	.users   = 2,
+	.fops    = &mod_fops,
+};
+
+
+#if 0
+static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
+{
+	int i;
+
+	for (i = 0; i < dev->info->port_num * 2; i++) {
+		if (dev->input[i].fe == fe)
+			return &dev->input[i];
+	}
+	return NULL;
+}
+#endif
+
+static int locked_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct ddb_input *input = fe->sec_priv;
+	struct ddb_port *port = input->port;
+	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
+	int status;
+
+	if (enable) {
+		mutex_lock(&port->i2c_gate_lock);
+		status = dvb->i2c_gate_ctrl(fe, 1);
+	} else {
+		status = dvb->i2c_gate_ctrl(fe, 0);
+		mutex_unlock(&port->i2c_gate_lock);
+	}
+	return status;
+}
+
+#ifdef CONFIG_DVB_DRXK
+static int demod_attach_drxk(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	fe = dvb->fe = dvb_attach(drxk_attach,
+				  i2c, 0x29 + (input->nr&1),
+				  &dvb->fe2);
+	if (!fe) {
+		pr_err("No DRXK found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
+	return 0;
+}
+#endif
+
+#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 ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	fe = dvb->fe = dvb_attach(stv0367ter_attach,
+				  (input->nr & 1) ? &stv0367_1 : &stv0367_0,
+				  i2c);
+	if (!dvb->fe) {
+		pr_err("No stv0367 found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
+	return 0;
+}
+#endif
+
+struct cxd2843_cfg cxd2843_0 = {
+	.adr = 0x6c,
+};
+
+struct cxd2843_cfg cxd2843_1 = {
+	.adr = 0x6d,
+};
+
+struct cxd2843_cfg cxd2843p_0 = {
+	.adr = 0x6c,
+	.parallel = 1,
+};
+
+struct cxd2843_cfg cxd2843p_1 = {
+	.adr = 0x6d,
+	.parallel = 1,
+};
+
+static int demod_attach_cxd2843(struct ddb_input *input, int par)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	if (par)
+		fe = dvb->fe = dvb_attach(cxd2843_attach, i2c,
+					  (input->nr & 1) ?
+					  &cxd2843p_1 : &cxd2843p_0);
+	else
+		fe = dvb->fe = dvb_attach(cxd2843_attach, i2c,
+					  (input->nr & 1) ?
+					  &cxd2843_1 : &cxd2843_0);
+	if (!dvb->fe) {
+		pr_err("No cxd2837/38/43 found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
+	return 0;
+}
+
+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 ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	fe = dvb->fe = dvb_attach(stv0367_attach, i2c,
+				  (input->nr & 1) ?
+				  &stv0367dd_1 : &stv0367dd_0,
+				  &dvb->fe2);
+	if (!dvb->fe) {
+		pr_err("No stv0367 found!\n");
+		return -ENODEV;
+	}
+	fe->sec_priv = input;
+	dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl;
+	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
+	return 0;
+}
+
+static int tuner_attach_tda18271(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	if (dvb->fe->ops.i2c_gate_ctrl)
+		dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 1);
+	fe = dvb_attach(tda18271c2dd_attach, dvb->fe, i2c, 0x60);
+	if (dvb->fe->ops.i2c_gate_ctrl)
+		dvb->fe->ops.i2c_gate_ctrl(dvb->fe, 0);
+	if (!fe) {
+		pr_err("No TDA18271 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int tuner_attach_tda18212dd(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	fe = dvb_attach(tda18212dd_attach, dvb->fe, i2c,
+			(input->nr & 1) ? 0x63 : 0x60);
+	if (!fe) {
+		pr_err("No TDA18212 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_DVB_TDA18212
+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 ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+	struct tda18212_config *cfg;
+
+	cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0;
+	fe = dvb_attach(tda18212_attach, dvb->fe, i2c, cfg);
+	if (!fe) {
+		pr_err("No TDA18212 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+#endif
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static struct stv090x_config stv0900 = {
+	.device         = STV0900,
+	.demod_mode     = STV090x_DUAL,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 27000000,
+	.address        = 0x69,
+
+	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+	.ts1_tei        = 1,
+	.ts2_tei        = 1,
+
+	.repeater_level = STV090x_RPTLEVEL_16,
+
+	.adc1_range	= STV090x_ADC_1Vpp,
+	.adc2_range	= STV090x_ADC_1Vpp,
+
+	.diseqc_envelope_mode = true,
+};
+
+static struct stv090x_config stv0900_aa = {
+	.device         = STV0900,
+	.demod_mode     = STV090x_DUAL,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 27000000,
+	.address        = 0x68,
+
+	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+	.ts1_tei        = 1,
+	.ts2_tei        = 1,
+
+	.repeater_level = STV090x_RPTLEVEL_16,
+
+	.adc1_range	= STV090x_ADC_1Vpp,
+	.adc2_range	= STV090x_ADC_1Vpp,
+
+	.diseqc_envelope_mode = true,
+};
+
+static struct stv6110x_config stv6110a = {
+	.addr    = 0x60,
+	.refclk	 = 27000000,
+	.clk_div = 1,
+};
+
+static struct stv6110x_config stv6110b = {
+	.addr    = 0x63,
+	.refclk	 = 27000000,
+	.clk_div = 1,
+};
+
+static int demod_attach_stv0900(struct ddb_input *input, int type)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+
+	dvb->fe = dvb_attach(stv090x_attach, feconf, i2c,
+			     (input->nr & 1) ? STV090x_DEMODULATOR_1
+			     : STV090x_DEMODULATOR_0);
+	if (!dvb->fe) {
+		pr_err("No STV0900 found!\n");
+		return -ENODEV;
+	}
+	if (!dvb_attach(lnbh24_attach, dvb->fe, i2c, 0,
+			0, (input->nr & 1) ?
+			(0x09 - type) : (0x0b - type))) {
+		pr_err("No LNBH24 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int tuner_attach_stv6110(struct ddb_input *input, int type)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
+	struct stv6110x_config *tunerconf = (input->nr & 1) ?
+		&stv6110b : &stv6110a;
+	struct stv6110x_devctl *ctl;
+
+	ctl = dvb_attach(stv6110x_attach, dvb->fe, tunerconf, i2c);
+	if (!ctl) {
+		pr_err("No STV6110X found!\n");
+		return -ENODEV;
+	}
+	pr_info("attach tuner input %d adr %02x\n",
+		input->nr, tunerconf->addr);
+
+	feconf->tuner_init          = ctl->tuner_init;
+	feconf->tuner_sleep         = ctl->tuner_sleep;
+	feconf->tuner_set_mode      = ctl->tuner_set_mode;
+	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
+	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
+	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
+	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
+	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
+	feconf->tuner_get_status    = ctl->tuner_get_status;
+
+	return 0;
+}
+
+static struct stv0910_cfg stv0910 = {
+	.adr      = 0x68,
+	.parallel = 1,
+	.rptlvl   = 4,
+	.clk      = 30000000,
+};
+
+static int demod_attach_stv0910(struct ddb_input *input, int type)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+
+	dvb->fe = dvb_attach(stv0910_attach, i2c, &stv0910, (input->nr & 1));
+	if (!dvb->fe) {
+		pr_err("No STV0910 found!\n");
+		return -ENODEV;
+	}
+	if (!dvb_attach(lnbh25_attach, dvb->fe, i2c,
+			(input->nr & 1) ? 0x09 : 0x08)) {
+		pr_err("No LNBH25 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int tuner_attach_stv6111(struct ddb_input *input)
+{
+	struct i2c_adapter *i2c = &input->port->i2c->adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_frontend *fe;
+
+	fe = dvb_attach(stv6111_attach, dvb->fe, i2c,
+			(input->nr & 1) ? 0x63 : 0x60);
+	if (!fe) {
+		pr_err("No STV6111 found!\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static struct mxl5xx_cfg mxl5xx = {
+	.adr      = 0x60,
+	.type     = 0x01,
+	.clk      = 27000000,
+	.cap      = 12,
+};
+
+static int lnb_command(struct ddb *dev, u32 lnb, u32 cmd)
+{
+	u32 c, v = 0;
+
+	v = LNB_TONE & (dev->lnb_tone << (15 - lnb));
+	pr_info("lnb_control[%u] = %08x\n", lnb, cmd | v);
+	ddbwritel(dev, cmd | v, LNB_CONTROL(lnb));
+	for (c = 0; c < 10; c++) {
+		v = ddbreadl(dev, LNB_CONTROL(lnb));
+		pr_info("ctrl = %08x\n", v);
+		if ((v & LNB_BUSY) == 0)
+			break;
+		msleep(20);
+	}
+	return 0;
+}
+
+static int dd_send_master_cmd(struct dvb_frontend *fe,
+			      struct dvb_diseqc_master_cmd *cmd)
+{
+	struct ddb_input *input = fe->sec_priv;
+	struct ddb_port *port = input->port;
+	struct ddb *dev = port->dev;
+	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
+	int i;
+
+	mutex_lock(&dev->lnb_lock);
+	ddbwritel(dev, 0, LNB_BUF_LEVEL(dvb->input));
+	for (i = 0; i < cmd->msg_len; i++)
+		ddbwritel(dev, cmd->msg[i], LNB_BUF_WRITE(dvb->input));
+	lnb_command(dev, dvb->input, LNB_CMD_DISEQC);
+	mutex_unlock(&dev->lnb_lock);
+	return 0;
+}
+
+static int dd_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+	struct ddb_input *input = fe->sec_priv;
+	struct ddb_port *port = input->port;
+	struct ddb *dev = port->dev;
+	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
+	int s = 0;
+
+	mutex_lock(&dev->lnb_lock);
+	switch (tone) {
+	case SEC_TONE_OFF:
+		dev->lnb_tone &= ~(1ULL << dvb->input);
+		break;
+	case SEC_TONE_ON:
+		dev->lnb_tone |= (1ULL << dvb->input);
+		break;
+	default:
+		s = -EINVAL;
+		break;
+	};
+	if (!s)
+		s = lnb_command(dev, dvb->input, LNB_CMD_NOP);
+	mutex_unlock(&dev->lnb_lock);
+	return 0;
+}
+
+static int dd_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+
+	return 0;
+}
+
+static int dd_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct ddb_input *input = fe->sec_priv;
+	struct ddb_port *port = input->port;
+	struct ddb *dev = port->dev;
+	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
+	int s = 0;
+
+	mutex_lock(&dev->lnb_lock);
+	switch (voltage) {
+	case SEC_VOLTAGE_OFF:
+		lnb_command(dev, dvb->input, LNB_CMD_OFF);
+		break;
+	case SEC_VOLTAGE_13:
+		lnb_command(dev, dvb->input, LNB_CMD_LOW);
+		break;
+	case SEC_VOLTAGE_18:
+		lnb_command(dev, dvb->input, LNB_CMD_HIGH);
+		break;
+	default:
+		s = -EINVAL;
+		break;
+	};
+	mutex_unlock(&dev->lnb_lock);
+	return s;
+}
+
+static int dd_set_input(struct dvb_frontend *fe)
+{
+	
+	return 0;
+}
+
+static int fe_attach_mxl5xx(struct ddb_input *input)
+{
+	struct ddb *dev = input->port->dev;
+	struct i2c_adapter *i2c = &dev->i2c[0].adap;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	int demod, tuner;
+
+	demod = input->nr;
+	tuner = demod & 3;
+	dvb->fe = dvb_attach(mxl5xx_attach, i2c, &mxl5xx,
+			     demod, tuner);
+	if (!dvb->fe) {
+		pr_err("No MXL5XX found!\n");
+		return -ENODEV;
+	}
+	if (input->nr < 4) 
+		lnb_command(dev, input->nr, LNB_CMD_INIT);
+	dvb->fe->ops.set_voltage = dd_set_voltage;
+	dvb->fe->ops.enable_high_lnb_voltage = dd_enable_high_lnb_voltage;
+	dvb->fe->ops.set_tone = dd_set_tone;
+	dvb->fe->ops.diseqc_send_master_cmd = dd_send_master_cmd;
+	dvb->fe->sec_priv = input;
+	dvb->set_input = dvb->fe->ops.set_input;
+	dvb->fe->ops.set_input = dd_set_input;
+	dvb->input = tuner;
+	return 0;
+}
+
+static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
+				   int (*start_feed)(struct dvb_demux_feed *),
+				   int (*stop_feed)(struct dvb_demux_feed *),
+				   void *priv)
+{
+	dvbdemux->priv = priv;
+
+	dvbdemux->filternum = 256;
+	dvbdemux->feednum = 256;
+	dvbdemux->start_feed = start_feed;
+	dvbdemux->stop_feed = stop_feed;
+	dvbdemux->write_to_decoder = NULL;
+	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
+				      DMX_SECTION_FILTERING |
+				      DMX_MEMORY_BASED_FILTERING);
+	return dvb_dmx_init(dvbdemux);
+}
+
+static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
+				      struct dvb_demux *dvbdemux,
+				      struct dmx_frontend *hw_frontend,
+				      struct dmx_frontend *mem_frontend,
+				      struct dvb_adapter *dvb_adapter)
+{
+	int ret;
+
+	dmxdev->filternum = 256;
+	dmxdev->demux = &dvbdemux->dmx;
+	dmxdev->capabilities = 0;
+	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
+	if (ret < 0)
+		return ret;
+
+	hw_frontend->source = DMX_FRONTEND_0;
+	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
+	mem_frontend->source = DMX_MEMORY_FE;
+	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
+	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
+}
+
+#if 0
+static int start_input(struct ddb_input *input)
+{
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+
+	if (!dvb->users)
+		ddb_input_start_all(input);
+
+	return ++dvb->users;
+}
+
+static int stop_input(struct ddb_input *input)
+{
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+
+	if (--dvb->users)
+		return dvb->users;
+
+	ddb_input_stop_all(input);
+	return 0;
+}
+#endif
+
+static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct ddb_input *input = dvbdmx->priv;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+
+	if (!dvb->users)
+		ddb_input_start_all(input);
+
+	return ++dvb->users;
+}
+
+static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
+	struct ddb_input *input = dvbdmx->priv;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+
+	if (--dvb->users)
+		return dvb->users;
+
+	ddb_input_stop_all(input);
+	return 0;
+}
+
+static void dvb_input_detach(struct ddb_input *input)
+{
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct dvb_demux *dvbdemux = &dvb->demux;
+
+	switch (dvb->attached) {
+	case 0x31:
+		if (dvb->fe2)
+			dvb_unregister_frontend(dvb->fe2);
+		if (dvb->fe)
+			dvb_unregister_frontend(dvb->fe);
+		/* fallthrough */
+	case 0x30:
+		dvb_frontend_detach(dvb->fe);
+		dvb->fe = dvb->fe2 = NULL;
+		/* fallthrough */
+	case 0x21:
+		if (input->port->dev->ns_num)
+			dvb_netstream_release(&dvb->dvbns);
+		/* fallthrough */
+	case 0x20:
+		dvb_net_release(&dvb->dvbnet);
+		/* fallthrough */
+	case 0x11:
+		dvbdemux->dmx.close(&dvbdemux->dmx);
+		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+					      &dvb->hw_frontend);
+		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
+					      &dvb->mem_frontend);
+		dvb_dmxdev_release(&dvb->dmxdev);
+		/* fallthrough */
+	case 0x10:
+		dvb_dmx_release(&dvb->demux);
+		/* fallthrough */
+	case 0x01:
+		break;
+	}
+	dvb->attached = 0x00;
+}
+
+static int dvb_register_adapters(struct ddb *dev)
+{
+	int i, ret = 0;
+	struct ddb_port *port;
+	struct dvb_adapter *adap;
+
+	if (adapter_alloc == 3 || dev->info->type == DDB_MOD) {
+		port = &dev->port[0];
+		adap = port->dvb[0].adap;
+		ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
+					   port->dev->dev,
+					   adapter_nr);
+		if (ret < 0)
+			return ret;
+		port->dvb[0].adap_registered = 1;
+		for (i = 0; i < dev->info->port_num; i++) {
+			port = &dev->port[i];
+			port->dvb[0].adap = adap;
+			port->dvb[1].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->dvb[0].adap;
+			ret = dvb_register_adapter(adap, "DDBridge",
+						   THIS_MODULE,
+						   port->dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->dvb[0].adap_registered = 1;
+
+			if (adapter_alloc > 0) {
+				port->dvb[1].adap = port->dvb[0].adap;
+				break;
+			}
+			adap = port->dvb[1].adap;
+			ret = dvb_register_adapter(adap, "DDBridge",
+						   THIS_MODULE,
+						   port->dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->dvb[1].adap_registered = 1;
+			break;
+
+		case DDB_PORT_CI:
+		case DDB_PORT_LOOP:
+			adap = port->dvb[0].adap;
+			ret = dvb_register_adapter(adap, "DDBridge",
+						   THIS_MODULE,
+						   port->dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->dvb[0].adap_registered = 1;
+			break;
+		default:
+			if (adapter_alloc < 2)
+				break;
+			adap = port->dvb[0].adap;
+			ret = dvb_register_adapter(adap, "DDBridge",
+						   THIS_MODULE,
+						   port->dev->dev,
+						   adapter_nr);
+			if (ret < 0)
+				return ret;
+			port->dvb[0].adap_registered = 1;
+			break;
+		}
+	}
+	return ret;
+}
+
+static void dvb_unregister_adapters(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+	struct ddb_dvb *dvb;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+
+		dvb = &port->dvb[0];
+		if (dvb->adap_registered)
+			dvb_unregister_adapter(dvb->adap);
+		dvb->adap_registered = 0;
+
+		dvb = &port->dvb[1];
+		if (dvb->adap_registered)
+			dvb_unregister_adapter(dvb->adap);
+		dvb->adap_registered = 0;
+	}
+}
+
+static int dvb_input_attach(struct ddb_input *input)
+{
+	int ret = 0;
+	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
+	struct ddb_port *port = input->port;
+	struct dvb_adapter *adap = dvb->adap;
+	struct dvb_demux *dvbdemux = &dvb->demux;
+
+	dvb->attached = 0x01;
+
+	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
+				      start_feed,
+				      stop_feed, input);
+	if (ret < 0)
+		return ret;
+	dvb->attached = 0x10;
+
+	ret = my_dvb_dmxdev_ts_card_init(&dvb->dmxdev,
+					 &dvb->demux,
+					 &dvb->hw_frontend,
+					 &dvb->mem_frontend, adap);
+	if (ret < 0)
+		return ret;
+	dvb->attached = 0x11;
+
+	ret = dvb_net_init(adap, &dvb->dvbnet, dvb->dmxdev.demux);
+	if (ret < 0)
+		return ret;
+	dvb->attached = 0x20;
+
+	if (input->port->dev->ns_num) {
+		ret = netstream_init(input);
+		if (ret < 0)
+			return ret;
+		dvb->attached = 0x21;
+	}
+	dvb->fe = dvb->fe2 = 0;
+	switch (port->type) {
+	case DDB_TUNER_MXL5XX:
+		fe_attach_mxl5xx(input);
+		break;
+	case DDB_TUNER_DVBS_ST:
+		if (demod_attach_stv0900(input, 0) < 0)
+			return -ENODEV;
+		if (tuner_attach_stv6110(input, 0) < 0)
+			return -ENODEV;
+		break;
+	case DDB_TUNER_DVBS_STV0910:
+	case DDB_TUNER_DVBS_STV0910_P:
+		if (demod_attach_stv0910(input, 0) < 0)
+			return -ENODEV;
+		if (tuner_attach_stv6111(input) < 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;
+		break;
+#ifdef CONFIG_DVB_DRXK
+	case DDB_TUNER_DVBCT_TR:
+		if (demod_attach_drxk(input) < 0)
+			return -ENODEV;
+		if (tuner_attach_tda18271(input) < 0)
+			return -ENODEV;
+		break;
+#endif
+	case DDB_TUNER_DVBCT_ST:
+		if (demod_attach_stv0367dd(input) < 0)
+			return -ENODEV;
+		if (tuner_attach_tda18212dd(input) < 0)
+			return -ENODEV;
+		break;
+	case DDB_TUNER_DVBCT2_SONY:
+	case DDB_TUNER_DVBC2T2_SONY:
+	case DDB_TUNER_ISDBT_SONY:
+		if (demod_attach_cxd2843(input, 0) < 0)
+			return -ENODEV;
+		if (tuner_attach_tda18212dd(input) < 0)
+			return -ENODEV;
+		break;
+	case DDB_TUNER_DVBCT2_SONY_P:
+	case DDB_TUNER_DVBC2T2_SONY_P:
+	case DDB_TUNER_ISDBT_SONY_P:
+		if (demod_attach_cxd2843(input, 1) < 0)
+			return -ENODEV;
+		if (tuner_attach_tda18212dd(input) < 0)
+			return -ENODEV;
+		break;
+	default:
+		return 0;
+	}
+	dvb->attached = 0x30;
+	if (dvb->fe) {
+		if (dvb_register_frontend(adap, dvb->fe) < 0)
+			return -ENODEV;
+	}
+	if (dvb->fe2) {
+		if (dvb_register_frontend(adap, dvb->fe2) < 0)
+			return -ENODEV;
+		dvb->fe2->tuner_priv = dvb->fe->tuner_priv;
+		memcpy(&dvb->fe2->ops.tuner_ops,
+		       &dvb->fe->ops.tuner_ops,
+		       sizeof(struct dvb_tuner_ops));
+	}
+	dvb->attached = 0x31;
+	return 0;
+}
+
+
+static int port_has_encti(struct ddb_port *port)
+{
+	u8 val;
+	int ret = i2c_read_reg(&port->i2c->adap, 0x20, 0, &val);
+
+	if (!ret)
+		pr_info("[0x20]=0x%02x\n", val);
+	return ret ? 0 : 1;
+}
+
+static int port_has_cxd(struct ddb_port *port, u8 *type)
+{
+	u8 val;
+	u8 probe[4] = { 0xe0, 0x00, 0x00, 0x00 }, data[4];
+	struct i2c_msg msgs[2] = {{ .addr = 0x40,  .flags = 0,
+				    .buf  = probe, .len   = 4 },
+				  { .addr = 0x40,  .flags = I2C_M_RD,
+				    .buf  = data,  .len   = 4 } };
+	val = i2c_transfer(&port->i2c->adap, msgs, 2);
+	if (val != 2)
+		return 0;
+
+	if (data[0] == 0x02 && data[1] == 0x2b && data[3] == 0x43)
+		*type = 2;
+	else
+		*type = 1;
+	return 1;
+}
+
+static int port_has_xo2(struct ddb_port *port, u8 *id)
+{
+	u8 val;
+	u8 probe[1] = { 0x00 }, data[4];
+	struct i2c_msg msgs[2] = {{ .addr = 0x10,  .flags = 0,
+				    .buf  = probe, .len   = 1 },
+				  { .addr = 0x10,  .flags = I2C_M_RD,
+				    .buf  = data,  .len   = 4 } };
+	val = i2c_transfer(&port->i2c->adap, msgs, 2);
+	if (val != 2)
+		return 0;
+
+	if (data[0] != 'D' || data[1] != 'F')
+		return 0;
+
+	*id = data[2];
+	return 1;
+}
+
+static int port_has_stv0900(struct ddb_port *port)
+{
+	u8 val;
+	if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
+		return 0;
+	return 1;
+}
+
+static int port_has_stv0900_aa(struct ddb_port *port, u8 *id)
+{
+	if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, id) < 0)
+		return 0;
+	return 1;
+}
+
+static int port_has_drxks(struct ddb_port *port)
+{
+	u8 val;
+	if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
+		return 0;
+	if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
+		return 0;
+	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;
+}
+
+#if 0
+static int init_xo2_old(struct ddb_port *port)
+{
+	struct i2c_adapter *i2c = &port->i2c->adap;
+	u8 val;
+	int res;
+
+	res = i2c_read_reg(i2c, 0x10, 0x04, &val);
+	if (res < 0)
+		return res;
+
+	if (val != 0x02)  {
+		pr_info("Port %d: invalid XO2\n", port->nr);
+		return -1;
+	}
+	i2c_write_reg(i2c, 0x10, 0xc0, 0x00); /* Disable XO2 I2C master */
+
+	i2c_read_reg(i2c, 0x10, 0x08, &val);
+	if (val != 0) {
+		i2c_write_reg(i2c, 0x10, 0x08, 0x00);
+		msleep(100);
+	}
+	/* Enable tuner power, disable pll, reset demods */
+	i2c_write_reg(i2c, 0x10, 0x08, 0x04);
+	usleep_range(2000, 3000);
+	/* Release demod resets */
+	i2c_write_reg(i2c, 0x10, 0x08, 0x07);
+	usleep_range(2000, 3000);
+	/* Start XO2 PLL */
+	i2c_write_reg(i2c, 0x10, 0x08, 0x87);
+
+	return 0;
+}
+#endif
+
+static int init_xo2(struct ddb_port *port)
+{
+	struct i2c_adapter *i2c = &port->i2c->adap;
+	u8 val, data[2];
+	int res;
+
+	res = i2c_read_regs(i2c, 0x10, 0x04, data, 2);
+	if (res < 0)
+		return res;
+
+	if (data[0] != 0x01)  {
+		pr_info("Port %d: invalid XO2\n", port->nr);
+		return -1;
+	}
+
+	i2c_read_reg(i2c, 0x10, 0x08, &val);
+	if (val != 0) {
+		i2c_write_reg(i2c, 0x10, 0x08, 0x00);
+		msleep(100);
+	}
+	/* Enable tuner power, disable pll, reset demods */
+	i2c_write_reg(i2c, 0x10, 0x08, 0x04);
+	usleep_range(2000, 3000);
+	/* Release demod resets */
+	i2c_write_reg(i2c, 0x10, 0x08, 0x07);
+	usleep_range(2000, 3000);
+	/* Start XO2 PLL */
+	i2c_write_reg(i2c, 0x10, 0x08, 0x87);
+
+	return 0;
+}
+
+static int port_has_cxd28xx(struct ddb_port *port, u8 *id)
+{
+	struct i2c_adapter *i2c = &port->i2c->adap;
+	int status;
+
+	status = i2c_write_reg(&port->i2c->adap, 0x6e, 0, 0);
+	if (status)
+		return 0;
+	status = i2c_read_reg(i2c, 0x6e, 0xfd, id);
+	if (status)
+		return 0;
+	return 1;
+}
+
+static char *xo2names[] = {
+	"DUAL DVB-S2", "DUAL DVB-C/T/T2",
+	"DUAL DVB-ISDBT", "DUAL DVB-C/C2/T/T2",
+	"DUAL ATSC", "DUAL DVB-C/C2/T/T2",
+	"", ""
+};
+
+static void ddb_port_probe(struct ddb_port *port)
+{
+	struct ddb *dev = port->dev;
+	u8 id;
+
+	port->name = "NO MODULE";
+	port->class = DDB_PORT_NONE;
+
+	if (dev->info->type == DDB_MOD) {
+		port->name = "MOD";
+		port->class = DDB_PORT_MOD;
+		return;
+	}
+
+	if (dev->info->type == DDB_OCTOPUS_MAX) {
+		port->name = "DUAL DVB-S2 MX";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_MXL5XX;
+		if (port->i2c)
+			ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+		return;
+	}
+
+	if (port->nr > 1 && dev->info->type == DDB_OCTOPUS_CI) {
+		port->name = "CI internal";
+		port->class = DDB_PORT_CI;
+		port->type = DDB_CI_INTERNAL;
+	} else if (port_has_cxd(port, &id)) {
+		if (id == 1) {
+			port->name = "CI";
+			port->class = DDB_PORT_CI;
+			port->type = DDB_CI_EXTERNAL_SONY;
+			ddbwritel(dev, I2C_SPEED_400,
+				  port->i2c->regs + I2C_TIMING);
+		} else {
+			pr_info(KERN_INFO "Port %d: Uninitialized DuoFlex\n",
+			       port->nr);
+			return;
+		}
+	} else if (port_has_xo2(port, &id)) {
+		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+		id >>= 2;
+		if (id > 5) {
+			port->name = "unknown XO2 DuoFlex";
+		} else {
+			port->class = DDB_PORT_TUNER;
+			port->type = DDB_TUNER_XO2 + id;
+			port->name = xo2names[id];
+			init_xo2(port);
+		}
+	} else if (port_has_cxd28xx(port, &id)) {
+		switch (id) {
+		case 0xa4:
+			port->name = "DUAL DVB-CT2 CXD2843";
+			port->type = DDB_TUNER_DVBC2T2_SONY_P;
+			break;
+		case 0xb1:
+			port->name = "DUAL DVB-CT2 CXD2837";
+			port->type = DDB_TUNER_DVBCT2_SONY_P;
+			break;
+		case 0xb0:
+			port->name = "DUAL ISDB-T CXD2838";
+			port->type = DDB_TUNER_ISDBT_SONY_P;
+			break;
+		default:
+			return;
+		}
+		port->class = DDB_PORT_TUNER;
+		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_stv0900(port)) {
+		port->name = "DUAL DVB-S2";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBS_ST;
+		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_stv0900_aa(port, &id)) {
+		port->name = "DUAL DVB-S2";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBS_ST_AA;
+		if (id == 0x51)
+			port->type = DDB_TUNER_DVBS_STV0910_P;
+		else
+			port->type = DDB_TUNER_DVBS_ST_AA;
+		ddbwritel(dev, I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_drxks(port)) {
+		port->name = "DUAL DVB-C/T";
+		port->class = DDB_PORT_TUNER;
+		port->type = DDB_TUNER_DVBCT_TR;
+		ddbwritel(dev, I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
+	} else if (port_has_stv0367(port)) {
+		port->name = "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_has_encti(port)) {
+		port->name = "ENCTI";
+		port->class = DDB_PORT_LOOP;
+	} else if (port->nr == ts_loop) {
+		port->name = "TS LOOP";
+		port->class = DDB_PORT_LOOP;
+	}
+}
+
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static int wait_ci_ready(struct ddb_ci *ci)
+{
+	u32 count = 10;
+
+	ndelay(500);
+	do {
+		if (ddbreadl(ci->port->dev,
+			     CI_CONTROL(ci->nr)) & CI_READY)
+			break;
+		usleep_range(1, 2);
+		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);
+	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));
+	ndelay(500);
+	do {
+		res = ddbreadl(ci->port->dev, CI_READDATA(ci->nr));
+		if (res & CI_READY)
+			break;
+		usleep_range(1, 2);
+		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;
+
+	ddbwritel(ci->port->dev, CI_POWER_ON,
+		  CI_CONTROL(ci->nr));
+	msleep(100);
+	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;
+
+	ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr));
+	msleep(300);
+	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 =  72000,
+	.adr     =  0x40,
+	.polarity = 1,
+	.clock_mode = 1,
+};
+
+static int ddb_ci_attach(struct ddb_port *port)
+{
+	if (port->type == DDB_CI_EXTERNAL_SONY) {
+		cxd_cfg.bitrate = ci_bitrate;
+		port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
+		if (!port->en)
+			return -ENODEV;
+		dvb_ca_en50221_init(port->dvb[0].adap,
+				    port->en, 0, 1);
+	}
+	if (port->type == DDB_CI_INTERNAL) {
+		ci_attach(port);
+		if (!port->en)
+			return -ENODEV;
+		dvb_ca_en50221_init(port->dvb[0].adap, port->en, 0, 1);
+	}
+	return 0;
+}
+
+static int ddb_port_attach(struct ddb_port *port)
+{
+	int ret = 0;
+
+	switch (port->class) {
+	case DDB_PORT_TUNER:
+		ret = dvb_input_attach(port->input[0]);
+		if (ret < 0)
+			break;
+		ret = dvb_input_attach(port->input[1]);
+		if (ret < 0)
+			break;
+		port->input[0]->redi = port->input[0];
+		port->input[1]->redi = port->input[1];
+		break;
+	case DDB_PORT_CI:
+		ret = ddb_ci_attach(port);
+		if (ret < 0)
+			break;
+	case DDB_PORT_LOOP:
+		ret = dvb_register_device(port->dvb[0].adap,
+					  &port->dvb[0].dev,
+					  &dvbdev_ci, (void *) port->output,
+					  DVB_DEVICE_CI);
+		break;
+	case DDB_PORT_MOD:
+		ret = dvb_register_device(port->dvb[0].adap,
+					  &port->dvb[0].dev,
+					  &dvbdev_mod, (void *) port->output,
+					  DVB_DEVICE_MOD);
+		break;
+	default:
+		break;
+	}
+	if (ret < 0)
+		pr_err("port_attach on port %d failed\n", port->nr);
+	return ret;
+}
+
+static int ddb_ports_attach(struct ddb *dev)
+{
+	int i, ret = 0;
+	struct ddb_port *port;
+
+	if (dev->ids.devid == 0x0301dd01)
+		dev->ns_num = 15;
+	else
+		dev->ns_num = dev->info->ns_num;
+	for (i = 0; i < dev->ns_num; i++)
+		dev->ns[i].nr = i;
+	pr_info("%d netstream channels\n", dev->ns_num);
+
+	if (dev->info->port_num) {
+		ret = dvb_register_adapters(dev);
+		if (ret < 0) {
+			pr_err("Registering adapters failed. Check DVB_MAX_ADAPTERS in config.\n");
+			return ret;
+		}
+	}
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		ret = ddb_port_attach(port);
+		if (ret < 0)
+			break;
+	}
+	return ret;
+}
+
+static void ddb_ports_detach(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+
+		switch (port->class) {
+		case DDB_PORT_TUNER:
+			dvb_input_detach(port->input[0]);
+			dvb_input_detach(port->input[1]);
+			break;
+		case DDB_PORT_CI:
+		case DDB_PORT_LOOP:
+			if (port->dvb[0].dev)
+				dvb_unregister_device(port->dvb[0].dev);
+			if (port->en) {
+				dvb_ca_en50221_release(port->en);
+				kfree(port->en);
+				port->en = 0;
+			}
+			break;
+		case DDB_PORT_MOD:
+			if (port->dvb[0].dev)
+				dvb_unregister_device(port->dvb[0].dev);
+			break;
+		}
+	}
+	dvb_unregister_adapters(dev);
+}
+
+
+/* Copy input DMA pointers to output DMA and ACK. */
+
+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));
+	output->dma->cbuf = (input->dma->stat >> 11) & 0x1f;
+	output->dma->coff = (input->dma->stat & 0x7ff) << 7;
+}
+
+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_input *input2)
+{
+	struct ddb_dvb *dvb = &input2->port->dvb[input2->nr & 1];
+	struct ddb_dma *dma, *dma2;
+	struct ddb *dev = input->port->dev;
+	int noack = 0;
+
+	dma = dma2 = input->dma;
+	/* if there also is an output connected, do not ACK.
+	   input_write_output will ACK. */
+	if (input->redo) {
+		dma2 = input->redo->dma;
+		noack = 1;
+	}
+	while (dma->cbuf != ((dma->stat >> 11) & 0x1f)
+	       || (4 & dma->ctrl)) {
+		if (4 & dma->ctrl) {
+			/*pr_err("Overflow dma %d\n", dma->nr);*/
+			if (noack)
+				noack = 0;
+		}
+#ifdef DDB_ALT_DMA
+		dma_sync_single_for_cpu(dev->dev, dma2->pbuf[dma->cbuf],
+					dma2->size, DMA_FROM_DEVICE);
+#endif
+		dvb_dmx_swfilter_packets(&dvb->demux,
+					 dma2->vbuf[dma->cbuf],
+					 dma2->size / 188);
+		dma->cbuf = (dma->cbuf + 1) % dma2->num;
+		if (!noack)
+			ddbwritel(dev, (dma->cbuf << 11),
+				  DMA_BUFFER_ACK(dma->nr));
+		dma->stat = ddbreadl(dev, DMA_BUFFER_CURRENT(dma->nr));
+		dma->ctrl = ddbreadl(dev, DMA_BUFFER_CONTROL(dma->nr));
+	}
+}
+
+#ifdef DDB_USE_WORK
+static void input_work(struct work_struct *work)
+{
+	struct ddb_dma *dma = container_of(work, struct ddb_dma, work);
+	struct ddb_input *input = (struct ddb_input *) dma->io;
+#else
+static void input_tasklet(unsigned long data)
+{
+	struct ddb_input *input = (struct ddb_input *) data;
+	struct ddb_dma *dma = input->dma;
+#endif
+	struct ddb *dev = input->port->dev;
+
+	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 0
+	if (4 & dma->ctrl)
+		pr_err("Overflow dma %d\n", dma->nr);
+#endif
+	if (input->redi)
+		input_write_dvb(input, input->redi);
+	if (input->redo)
+		input_write_output(input, input->redo);
+	wake_up(&dma->wq);
+	spin_unlock(&dma->lock);
+}
+
+static void input_handler(unsigned long data)
+{
+	struct ddb_input *input = (struct ddb_input *) data;
+	struct ddb_dma *dma = input->dma;
+
+
+	/* If there is no input connected, input_tasklet() will
+	   just copy pointers and ACK. So, there is no need to go
+	   through the tasklet scheduler. */
+#ifdef DDB_USE_WORK
+	if (input->redi)
+		queue_work(ddb_wq, &dma->work);
+	else
+		input_work(&dma->work);
+#else
+	if (input->redi)
+		tasklet_schedule(&dma->tasklet);
+	else
+		input_tasklet(data);
+#endif
+}
+
+/* hmm, don't really need this anymore.
+   The output IRQ just copies some pointers, acks and wakes. */
+
+#ifdef DDB_USE_WORK
+static void output_work(struct work_struct *work)
+{
+}
+#else
+static void output_tasklet(unsigned long data)
+{
+}
+#endif
+
+static void output_handler(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(&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 (output->redi)
+		output_ack_input(output, output->redi);
+	wake_up(&dma->wq);
+	spin_unlock(&dma->lock);
+}
+
+
+/****************************************************************************/
+/****************************************************************************/
+
+
+static void ddb_dma_init(struct ddb_dma *dma, int nr, void *io, int out)
+{
+#ifndef DDB_USE_WORK
+	unsigned long priv = (unsigned long) io;
+#endif
+
+	dma->io = io;
+	dma->nr = nr;
+	spin_lock_init(&dma->lock);
+	init_waitqueue_head(&dma->wq);
+	if (out) {
+#ifdef DDB_USE_WORK
+		INIT_WORK(&dma->work, output_work);
+#else
+		tasklet_init(&dma->tasklet, output_tasklet, priv);
+#endif
+		dma->num = OUTPUT_DMA_BUFS;
+		dma->size = OUTPUT_DMA_SIZE;
+		dma->div = OUTPUT_DMA_IRQ_DIV;
+	} else {
+#ifdef DDB_USE_WORK
+		INIT_WORK(&dma->work, input_work);
+#else
+		tasklet_init(&dma->tasklet, input_tasklet, priv);
+#endif
+		dma->num = INPUT_DMA_BUFS;
+		dma->size = INPUT_DMA_SIZE;
+		dma->div = INPUT_DMA_IRQ_DIV;
+	}
+}
+
+static void ddb_input_init(struct ddb_port *port, int nr, int pnr, int dma_nr)
+{
+	struct ddb *dev = port->dev;
+	struct ddb_input *input = &dev->input[nr];
+
+	if (dev->has_dma) {
+		dev->handler[dma_nr + 8] = input_handler;
+		dev->handler_data[dma_nr + 8] = (unsigned long) input;
+	}
+	port->input[pnr] = input;
+	input->nr = nr;
+	input->port = port;
+	if (dev->has_dma) {
+		input->dma = &dev->dma[dma_nr];
+		ddb_dma_init(input->dma, dma_nr, (void *) input, 0);
+	}
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
+	ddbwritel(dev, 2, TS_INPUT_CONTROL(nr));
+	ddbwritel(dev, 0, TS_INPUT_CONTROL(nr));
+	if (dev->has_dma)
+		ddbwritel(dev, 0, DMA_BUFFER_ACK(input->dma->nr));
+}
+
+static void ddb_output_init(struct ddb_port *port, int nr, int dma_nr)
+{
+	struct ddb *dev = port->dev;
+	struct ddb_output *output = &dev->output[nr];
+
+	if (dev->has_dma) {
+		dev->handler[dma_nr + 8] = output_handler;
+		dev->handler_data[dma_nr + 8] = (unsigned long) output;
+	}
+	port->output = output;
+	output->nr = nr;
+	output->port = port;
+	if (dev->has_dma) {
+		output->dma = &dev->dma[dma_nr];
+		ddb_dma_init(output->dma, dma_nr, (void *) output, 1);
+	}
+	if (output->port->class == DDB_PORT_MOD) {
+		/*ddbwritel(dev, 0, CHANNEL_CONTROL(output->nr));*/
+	} else {
+		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
+		ddbwritel(dev, 2, TS_OUTPUT_CONTROL(nr));
+		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(nr));
+	}
+	if (dev->has_dma)
+		ddbwritel(dev, 0, DMA_BUFFER_ACK(output->dma->nr));
+}
+
+static void ddb_ports_init(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	if (dev->info->board_control) {
+		ddbwritel(dev, 0, BOARD_CONTROL);
+		msleep(100);
+		ddbwritel(dev, 4, BOARD_CONTROL);
+		usleep_range(2000, 3000);
+		ddbwritel(dev, 4 | dev->info->board_control, BOARD_CONTROL);
+		usleep_range(2000, 3000);
+	}
+
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+		port->dev = dev;
+		port->nr = i;
+		if (dev->info->i2c_num > i)
+			port->i2c = &dev->i2c[i];
+		port->gap = 4;
+		port->obr = ci_bitrate;
+		mutex_init(&port->i2c_gate_lock);
+		ddb_port_probe(port);
+		pr_info("Port %d (TAB %d): %s\n",
+			port->nr, port->nr + 1, port->name);
+
+		port->dvb[0].adap = &dev->adap[2 * i];
+		port->dvb[1].adap = &dev->adap[2 * i + 1];
+
+		if ((dev->info->type == DDB_OCTOPUS_CI) ||
+		    (dev->info->type == DDB_OCTONET) ||
+		    (dev->info->type == DDB_OCTOPUS)) {
+			if (i >= 2 && dev->info->type == DDB_OCTOPUS_CI) {
+				ddb_input_init(port, 2 + i, 0, 2 + i);
+				ddb_input_init(port, 4 + i, 1, 4 + i);
+			} else {
+				ddb_input_init(port, 2 * i, 0, 2 * i);
+				ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1);
+			}
+			ddb_output_init(port, i, i + 8);
+		}
+		if (dev->info->type == DDB_OCTOPUS_MAX) {
+			ddb_input_init(port, 2 * i, 0, 2 * i);
+			ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1);
+		}
+		if (dev->info->type == DDB_MOD) {
+			ddb_output_init(port, i, i);
+			dev->handler[i + 18] = ddbridge_mod_rate_handler;
+			dev->handler_data[i + 18] =
+				(unsigned long) &dev->output[i];
+		}
+	}
+}
+
+static void ddb_ports_release(struct ddb *dev)
+{
+	int i;
+	struct ddb_port *port;
+
+	if (!dev->has_dma)
+		return;
+	for (i = 0; i < dev->info->port_num; i++) {
+		port = &dev->port[i];
+#ifdef DDB_USE_WORK
+		if (port->input[0])
+			cancel_work_sync(&port->input[0]->dma->work);
+		if (port->input[1])
+			cancel_work_sync(&port->input[1]->dma->work);
+		if (port->output)
+			cancel_work_sync(&port->output->dma->work);
+#else
+		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);
+#endif
+	}
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+#define IRQ_HANDLE(_nr) \
+	do { if ((s & (1UL << _nr)) && dev->handler[_nr]) \
+		dev->handler[_nr](dev->handler_data[_nr]); } \
+	while (0)
+
+static void irq_handle_msg(struct ddb *dev, u32 s)
+{
+	dev->i2c_irq++;
+	IRQ_HANDLE(0);
+	IRQ_HANDLE(1);
+	IRQ_HANDLE(2);
+	IRQ_HANDLE(3);
+}
+
+static void irq_handle_io(struct ddb *dev, u32 s)
+{
+	dev->ts_irq++;
+	IRQ_HANDLE(8);
+	IRQ_HANDLE(9);
+	IRQ_HANDLE(10);
+	IRQ_HANDLE(11);
+	IRQ_HANDLE(12);
+	IRQ_HANDLE(13);
+	IRQ_HANDLE(14);
+	IRQ_HANDLE(15);
+	IRQ_HANDLE(16);
+	IRQ_HANDLE(17);
+	IRQ_HANDLE(18);
+	IRQ_HANDLE(19);
+	if (dev->info->type != DDB_MOD)
+		return;
+	IRQ_HANDLE(20);
+	IRQ_HANDLE(21);
+	IRQ_HANDLE(22);
+	IRQ_HANDLE(23);
+	IRQ_HANDLE(24);
+	IRQ_HANDLE(25);
+	IRQ_HANDLE(26);
+	IRQ_HANDLE(27);
+}
+
+static irqreturn_t irq_handler0(int irq, void *dev_id)
+{
+	struct ddb *dev = (struct ddb *) dev_id;
+	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
+
+	do {
+		if (s & 0x80000000)
+			return IRQ_NONE;
+		if (!(s & 0xfff00))
+			return IRQ_NONE;
+		ddbwritel(dev, s, INTERRUPT_ACK);
+		irq_handle_io(dev, s);
+	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t irq_handler1(int irq, void *dev_id)
+{
+	struct ddb *dev = (struct ddb *) dev_id;
+	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
+
+	do {
+		if (s & 0x80000000)
+			return IRQ_NONE;
+		if (!(s & 0x0000f))
+			return IRQ_NONE;
+		ddbwritel(dev, s, INTERRUPT_ACK);
+		irq_handle_msg(dev, s);
+	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t irq_handler(int irq, void *dev_id)
+{
+	struct ddb *dev = (struct ddb *) dev_id;
+	u32 s = ddbreadl(dev, INTERRUPT_STATUS);
+	int ret = IRQ_HANDLED;
+
+	if (!s)
+		return IRQ_NONE;
+	do {
+		if (s & 0x80000000)
+			return IRQ_NONE;
+		ddbwritel(dev, s, INTERRUPT_ACK);
+
+		if (s & 0x0000000f)
+			irq_handle_msg(dev, s);
+		if (s & 0x0fffff00) {
+			irq_handle_io(dev, s);
+#ifdef DDB_TEST_THREADED
+			ret = IRQ_WAKE_THREAD;
+#endif
+		}
+	} while ((s = ddbreadl(dev, INTERRUPT_STATUS)));
+
+	return ret;
+}
+
+#ifdef DDB_TEST_THREADED
+static irqreturn_t irq_thread(int irq, void *dev_id)
+{
+	/* struct ddb *dev = (struct ddb *) dev_id; */
+
+	/*pr_info("%s\n", __func__);*/
+
+	return IRQ_HANDLED;
+}
+#endif
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+#ifdef DVB_NSD
+
+static ssize_t nsd_read(struct file *file, char *buf,
+			size_t count, loff_t *ppos)
+{
+	return 0;
+}
+
+static unsigned int nsd_poll(struct file *file, poll_table *wait)
+{
+	return 0;
+}
+
+static int nsd_release(struct inode *inode, struct file *file)
+{
+	return dvb_generic_release(inode, file);
+}
+
+static int nsd_open(struct inode *inode, struct file *file)
+{
+	return dvb_generic_open(inode, file);
+}
+
+static int nsd_do_ioctl(struct file *file, unsigned int cmd, void *parg)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ddb *dev = dvbdev->priv;
+
+	/* unsigned long arg = (unsigned long) parg; */
+	int ret = 0;
+
+	switch (cmd) {
+	case NSD_START_GET_TS:
+	{
+		struct dvb_nsd_ts *ts = parg;
+		u32 ctrl = ((ts->input & 7) << 8) |
+			((ts->filter_mask & 3) << 2);
+		u32 to;
+
+		if (ddbreadl(dev, TS_CAPTURE_CONTROL) & 1) {
+			pr_info("ts capture busy\n");
+			return -EBUSY;
+		}
+		ddb_dvb_input_start(&dev->input[ts->input & 7]);
+
+		ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL);
+		ddbwritel(dev, ts->pid, TS_CAPTURE_PID);
+		ddbwritel(dev, (ts->section_id << 16) |
+			  (ts->table << 8) | ts->section,
+			  TS_CAPTURE_TABLESECTION);
+		/* 1024 ms default timeout if timeout set to 0 */
+		if (ts->timeout)
+			to = ts->timeout;
+		else
+			to = 1024;
+		/* 21 packets default if num set to 0 */
+		if (ts->num)
+			to |= ((u32) ts->num << 16);
+		else
+			to |= (21 << 16);
+		ddbwritel(dev, to, TS_CAPTURE_TIMEOUT);
+		if (ts->mode)
+			ctrl |= 2;
+		ddbwritel(dev, ctrl | 1, TS_CAPTURE_CONTROL);
+		break;
+	}
+	case NSD_POLL_GET_TS:
+	{
+		struct dvb_nsd_ts *ts = parg;
+		u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL);
+
+		if (ctrl & 1)
+			return -EBUSY;
+		if (ctrl & (1 << 14)) {
+			/*pr_info("ts capture timeout\n");*/
+			return -EAGAIN;
+		}
+		ddbcpyfrom(dev, dev->tsbuf, TS_CAPTURE_MEMORY,
+			   TS_CAPTURE_LEN);
+		ts->len = ddbreadl(dev, TS_CAPTURE_RECEIVED) & 0x1fff;
+		if (copy_to_user(ts->ts, dev->tsbuf, ts->len))
+			return -EIO;
+		break;
+	}
+	case NSD_CANCEL_GET_TS:
+	{
+		u32 ctrl = 0;
+		pr_info("cancel ts capture: 0x%x\n", ctrl);
+		ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL);
+		ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL);
+		/*pr_info("control register is 0x%x\n", ctrl);*/
+		break;
+	}
+	case NSD_STOP_GET_TS:
+	{
+		struct dvb_nsd_ts *ts = parg;
+		u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL);
+
+		if (ctrl & 1) {
+			pr_info("cannot stop ts capture, while it was neither finished not canceled\n");
+			return -EBUSY;
+		}
+		/*pr_info("ts capture stopped\n");*/
+		ddb_dvb_input_stop(&dev->input[ts->input & 7]);
+		break;
+	}
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static long nsd_ioctl(struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	return dvb_usercopy(file, cmd, arg, nsd_do_ioctl);
+}
+
+static const struct file_operations nsd_fops = {
+	.owner   = THIS_MODULE,
+	.read    = nsd_read,
+	.open    = nsd_open,
+	.release = nsd_release,
+	.poll    = nsd_poll,
+	.unlocked_ioctl = nsd_ioctl,
+};
+
+static struct dvb_device dvbdev_nsd = {
+	.priv    = 0,
+	.readers = 1,
+	.writers = 1,
+	.users   = 1,
+	.fops    = &nsd_fops,
+};
+
+static int ddb_nsd_attach(struct ddb *dev)
+{
+	int ret;
+
+	ret = dvb_register_device(&dev->adap[0],
+				  &dev->nsd_dev,
+				  &dvbdev_nsd, (void *) dev,
+				  DVB_DEVICE_NSD);
+	return ret;
+}
+
+static void ddb_nsd_detach(struct ddb *dev)
+{
+	if (dev->nsd_dev->users > 2) {
+		wait_event(dev->nsd_dev->wait_queue,
+			   dev->nsd_dev->users == 2);
+	}
+	dvb_unregister_device(dev->nsd_dev);
+}
+
+#endif
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
+{
+	u32 data, shift;
+
+	if (wlen > 4)
+		ddbwritel(dev, 1, SPI_CONTROL);
+	while (wlen > 4) {
+		/* FIXME: check for big-endian */
+		data = swab32(*(u32 *)wbuf);
+		wbuf += 4;
+		wlen -= 4;
+		ddbwritel(dev, data, SPI_DATA);
+		while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
+			;
+	}
+
+	if (rlen)
+		ddbwritel(dev, 0x0001 | ((wlen << (8 + 3)) & 0x1f00),
+			  SPI_CONTROL);
+	else
+		ddbwritel(dev, 0x0003 | ((wlen << (8 + 3)) & 0x1f00),
+			  SPI_CONTROL);
+
+	data = 0;
+	shift = ((4 - wlen) * 8);
+	while (wlen) {
+		data <<= 8;
+		data |= *wbuf;
+		wlen--;
+		wbuf++;
+	}
+	if (shift)
+		data <<= shift;
+	ddbwritel(dev, data, SPI_DATA);
+	while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
+		;
+
+	if (!rlen) {
+		ddbwritel(dev, 0, SPI_CONTROL);
+		return 0;
+	}
+	if (rlen > 4)
+		ddbwritel(dev, 1, SPI_CONTROL);
+
+	while (rlen > 4) {
+		ddbwritel(dev, 0xffffffff, SPI_DATA);
+		while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
+			;
+		data = ddbreadl(dev, SPI_DATA);
+		*(u32 *) rbuf = swab32(data);
+		rbuf += 4;
+		rlen -= 4;
+	}
+	ddbwritel(dev, 0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
+	ddbwritel(dev, 0xffffffff, SPI_DATA);
+	while (ddbreadl(dev, SPI_CONTROL) & 0x0004)
+		;
+
+	data = ddbreadl(dev, SPI_DATA);
+	ddbwritel(dev, 0, SPI_CONTROL);
+
+	if (rlen < 4)
+		data <<= ((4 - rlen) * 8);
+
+	while (rlen > 0) {
+		*rbuf = ((data >> 24) & 0xff);
+		data <<= 8;
+		rbuf++;
+		rlen--;
+	}
+	return 0;
+}
+
+int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len)
+{
+	u8 cmd[4] = {0x03, (addr >> 16) & 0xff,
+		     (addr >> 8) & 0xff, addr & 0xff};
+
+	return flashio(dev, cmd, 4, buf, len);
+}
+
+static int mdio_write(struct ddb *dev, u8 adr, u8 reg, u16 val)
+{
+	ddbwritel(dev, adr, MDIO_ADR);
+	ddbwritel(dev, reg, MDIO_REG);
+	ddbwritel(dev, val, MDIO_VAL);
+	ddbwritel(dev, 0x03, MDIO_CTRL);
+	while (ddbreadl(dev, MDIO_CTRL) & 0x02)
+		ndelay(500);
+	return 0;
+}
+
+static u16 mdio_read(struct ddb *dev, u8 adr, u8 reg)
+{
+	ddbwritel(dev, adr, MDIO_ADR);
+	ddbwritel(dev, reg, MDIO_REG);
+	ddbwritel(dev, 0x07, MDIO_CTRL);
+	while (ddbreadl(dev, MDIO_CTRL) & 0x02)
+		ndelay(500);
+	return ddbreadl(dev, MDIO_VAL);
+}
+
+#define DDB_MAGIC 'd'
+
+struct ddb_flashio {
+	__u8 *write_buf;
+	__u32 write_len;
+	__u8 *read_buf;
+	__u32 read_len;
+};
+
+struct ddb_gpio {
+	__u32 mask;
+	__u32 data;
+};
+
+struct ddb_id {
+	__u16 vendor;
+	__u16 device;
+	__u16 subvendor;
+	__u16 subdevice;
+	__u32 hw;
+	__u32 regmap;
+};
+
+struct ddb_reg {
+	__u32 reg;
+	__u32 val;
+};
+
+struct ddb_mem {
+	__u32  off;
+	__u8  *buf;
+	__u32  len;
+};
+
+struct ddb_mdio {
+	__u8   adr;
+	__u8   reg;
+	__u16  val;
+};
+
+#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 IOCTL_DDB_ID         _IOR(DDB_MAGIC, 0x03, struct ddb_id)
+#define IOCTL_DDB_READ_REG   _IOWR(DDB_MAGIC, 0x04, struct ddb_reg)
+#define IOCTL_DDB_WRITE_REG  _IOW(DDB_MAGIC, 0x05, struct ddb_reg)
+#define IOCTL_DDB_READ_MEM   _IOWR(DDB_MAGIC, 0x06, struct ddb_mem)
+#define IOCTL_DDB_WRITE_MEM  _IOR(DDB_MAGIC, 0x07, struct ddb_mem)
+#define IOCTL_DDB_READ_MDIO  _IOWR(DDB_MAGIC, 0x08, struct ddb_mdio)
+#define IOCTL_DDB_WRITE_MDIO _IOR(DDB_MAGIC, 0x09, struct ddb_mdio)
+
+#define DDB_NAME "ddbridge"
+
+static u32 ddb_num;
+static int ddb_major;
+static DEFINE_MUTEX(ddb_mutex);
+
+static int ddb_release(struct inode *inode, struct file *file)
+{
+	struct ddb *dev = file->private_data;
+
+	dev->ddb_dev_users--;
+	return 0;
+}
+
+static int ddb_open(struct inode *inode, struct file *file)
+{
+	struct ddb *dev = ddbs[iminor(inode)];
+
+	if (dev->ddb_dev_users)
+		return -EBUSY;
+	dev->ddb_dev_users++;
+	file->private_data = dev;
+	return 0;
+}
+
+static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct ddb *dev = file->private_data;
+	void *parg = (void *)arg;
+	int res;
+
+	switch (cmd) {
+	case IOCTL_DDB_FLASHIO:
+	{
+		struct ddb_flashio fio;
+		u8 *rbuf, *wbuf;
+
+		if (copy_from_user(&fio, parg, sizeof(fio)))
+			return -EFAULT;
+		if (fio.write_len > 1028 || fio.read_len > 1028)
+			return -EINVAL;
+		if (fio.write_len + fio.read_len > 1028)
+			return -EINVAL;
+
+		wbuf = &dev->iobuf[0];
+		rbuf = wbuf + fio.write_len;
+
+		if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
+			return -EFAULT;
+		res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
+		if (res)
+			return res;
+		if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_GPIO_OUT:
+	{
+		struct ddb_gpio gpio;
+		if (copy_from_user(&gpio, parg, sizeof(gpio)))
+			return -EFAULT;
+		ddbwritel(dev, gpio.mask, GPIO_DIRECTION);
+		ddbwritel(dev, gpio.data, GPIO_OUTPUT);
+		break;
+	}
+	case IOCTL_DDB_ID:
+	{
+		struct ddb_id ddbid;
+
+		ddbid.vendor = dev->ids.vendor;
+		ddbid.device = dev->ids.device;
+		ddbid.subvendor = dev->ids.subvendor;
+		ddbid.subdevice = dev->ids.subdevice;
+		ddbid.hw = ddbreadl(dev, 0);
+		ddbid.regmap = ddbreadl(dev, 4);
+		if (copy_to_user(parg, &ddbid, sizeof(ddbid)))
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_READ_REG:
+	{
+		struct ddb_reg reg;
+
+		if (copy_from_user(&reg, parg, sizeof(reg)))
+			return -EFAULT;
+		if (reg.reg >= dev->regs_len)
+			return -EINVAL;
+		reg.val = ddbreadl(dev, reg.reg);
+		if (copy_to_user(parg, &reg, sizeof(reg)))
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_WRITE_REG:
+	{
+		struct ddb_reg reg;
+
+		if (copy_from_user(&reg, parg, sizeof(reg)))
+			return -EFAULT;
+		if (reg.reg >= dev->regs_len)
+			return -EINVAL;
+		ddbwritel(dev, reg.val, reg.reg);
+		break;
+	}
+	case IOCTL_DDB_READ_MDIO:
+	{
+		struct ddb_mdio mdio;
+
+		if (!dev->info->mdio_num)
+			return -EIO;
+		if (copy_from_user(&mdio, parg, sizeof(mdio)))
+			return -EFAULT;
+		mdio.val = mdio_read(dev, mdio.adr, mdio.reg);
+		if (copy_to_user(parg, &mdio, sizeof(mdio)))
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_WRITE_MDIO:
+	{
+		struct ddb_mdio mdio;
+
+		if (!dev->info->mdio_num)
+			return -EIO;
+		if (copy_from_user(&mdio, parg, sizeof(mdio)))
+			return -EFAULT;
+		mdio_write(dev, mdio.adr, mdio.reg, mdio.val);
+		break;
+	}
+	case IOCTL_DDB_READ_MEM:
+	{
+		struct ddb_mem mem;
+		u8 *buf = &dev->iobuf[0];
+
+		if (copy_from_user(&mem, parg, sizeof(mem)))
+			return -EFAULT;
+		if ((mem.len + mem.off > dev->regs_len) ||
+		    mem.len > 1024)
+			return -EINVAL;
+		ddbcpyfrom(dev, buf, mem.off, mem.len);
+		if (copy_to_user(mem.buf, buf, mem.len))
+			return -EFAULT;
+		break;
+	}
+	case IOCTL_DDB_WRITE_MEM:
+	{
+		struct ddb_mem mem;
+		u8 *buf = &dev->iobuf[0];
+
+		if (copy_from_user(&mem, parg, sizeof(mem)))
+			return -EFAULT;
+		if ((mem.len + mem.off > dev->regs_len) ||
+		    mem.len > 1024)
+			return -EINVAL;
+		if (copy_from_user(buf, mem.buf, mem.len))
+			return -EFAULT;
+		ddbcpyto(dev, mem.off, buf, mem.len);
+		break;
+	}
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static const struct file_operations ddb_fops = {
+	.unlocked_ioctl = ddb_ioctl,
+	.open           = ddb_open,
+	.release        = ddb_release,
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
+static char *ddb_devnode(struct device *device, mode_t *mode)
+#else
+static char *ddb_devnode(struct device *device, umode_t *mode)
+#endif
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
+}
+
+#define __ATTR_MRO(_name, _show) {				\
+	.attr	= { .name = __stringify(_name), .mode = 0444 },	\
+	.show	= _show,					\
+}
+
+#define __ATTR_MWO(_name, _store) {				\
+	.attr	= { .name = __stringify(_name), .mode = 0222 },	\
+	.store	= _store,					\
+}
+
+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", "TYPE07",
+	"TYPE08", "TYPE09", "TYPE0A", "TYPE0B",
+	"TYPE0C", "TYPE0D", "TYPE0E", "TYPE0F",
+	"DVBS", "DVBCT2_SONY", "ISDBT_SONY", "DVBC2T2_SONY",
+	"ATSC_ST", "DVBC2T2_ST"
+};
+
+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);
+	struct i2c_adapter *adap;
+	int temp, temp2, temp3, i;
+	u8 tmp[2];
+
+	if (dev->info->type == DDB_MOD) {
+		ddbwritel(dev, 1, TEMPMON_CONTROL);
+		for (i = 0; i < 10; i++) {
+			if (0 == (1 & ddbreadl(dev, TEMPMON_CONTROL)))
+				break;
+			usleep_range(1000, 2000);
+		}
+		temp = ddbreadl(dev, TEMPMON_SENSOR1);
+		temp2 = ddbreadl(dev, TEMPMON_SENSOR2);
+		temp = (temp * 1000) >> 8;
+		temp2 = (temp2 * 1000) >> 8;
+		if (ddbreadl(dev, TEMPMON_CONTROL) & 0x8000) {
+			temp3 = ddbreadl(dev, TEMPMON_CORE);
+			temp3 = (temp3 * 1000) >> 8;
+			return sprintf(buf, "%d %d %d\n", temp, temp2, temp3);
+		}
+		return sprintf(buf, "%d %d\n", temp, temp2);
+	}
+	if (!dev->info->temp_num)
+		return sprintf(buf, "no sensor\n");
+	adap = &dev->i2c[dev->info->temp_bus].adap;
+	if (i2c_read_regs(adap, 0x48, 0, tmp, 2) < 0)
+		return sprintf(buf, "read_error\n");
+	temp = (tmp[0] << 3) | (tmp[1] >> 5);
+	temp *= 125;
+	if (dev->info->temp_num == 2) {
+		if (i2c_read_regs(adap, 0x49, 0, tmp, 2) < 0)
+			return sprintf(buf, "read_error\n");
+		temp2 = (tmp[0] << 3) | (tmp[1] >> 5);
+		temp2 *= 125;
+		return sprintf(buf, "%d %d\n", temp, temp2);
+	}
+	return sprintf(buf, "%d\n", temp);
+}
+
+#if 0
+static ssize_t qam_show(struct device *device,
+			struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	struct i2c_adapter *adap;
+	u8 tmp[4];
+	s16 i, q;
+
+	adap = &dev->i2c[1].adap;
+	if (i2c_read_regs16(adap, 0x1f, 0xf480, tmp, 4) < 0)
+		return sprintf(buf, "read_error\n");
+	i = (s16) (((u16) tmp[1]) << 14) | (((u16) tmp[0]) << 6);
+	q = (s16) (((u16) tmp[3]) << 14) | (((u16) tmp[2]) << 6);
+
+	return sprintf(buf, "%d %d\n", i, q);
+}
+#endif
+
+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:
+			i2c_write_reg16(&dev->i2c[num].adap,
+					0x69, 0xf14c, val ? 2 : 0);
+			break;
+		case DDB_TUNER_DVBCT_ST:
+			i2c_write_reg16(&dev->i2c[num].adap,
+					0x1f, 0xf00e, 0);
+			i2c_write_reg16(&dev->i2c[num].adap,
+					0x1f, 0xf00f, val ? 1 : 0);
+			break;
+		case DDB_TUNER_XO2 ... DDB_TUNER_DVBC2T2_ST:
+		{
+			u8 v;
+
+			i2c_read_reg(&dev->i2c[num].adap, 0x10, 0x08, &v);
+			v = (v & ~0x10) | (val ? 0x10 : 0);
+			i2c_write_reg(&dev->i2c[num].adap, 0x10, 0x08, v);
+			break;
+		}
+		default:
+			break;
+		}
+		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;
+
+	if (dev->port[num].type >= DDB_TUNER_XO2) {
+		if (i2c_read_regs(&dev->i2c[num].adap, 0x10, 0x10, snr, 16) < 0)
+			return sprintf(buf, "NO SNR\n");
+		snr[16] = 0;
+	} else {
+		/* serial number at 0x100-0x11f */
+		if (i2c_read_regs16(&dev->i2c[num].adap,
+				    0x50, 0x100, snr, 32) < 0)
+			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;
+	if (dev->port[num].type >= DDB_TUNER_XO2)
+		return -EINVAL;
+	memcpy(snr + 2, buf, count);
+	i2c_write(&dev->i2c[num].adap, 0x57, snr, 34);
+	i2c_write(&dev->i2c[num].adap, 0x50, snr, 34);
+	return count;
+}
+
+static ssize_t bsnr_show(struct device *device,
+			 struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+	char snr[16];
+
+	ddbridge_flashread(dev, snr, 0x10, 15);
+	snr[15] = 0; /* in case it is not terminated on EEPROM */
+	return sprintf(buf, "%s\n", snr);
+}
+
+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;
+	res = ddb_redirect(i, p);
+	if (res < 0)
+		return res;
+	pr_info("redirect: %02x, %02x\n", i, p);
+	return count;
+}
+
+static ssize_t gap_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->port[num].gap);
+
+}
+static ssize_t gap_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 int val;
+
+	if (sscanf(buf, "%u\n", &val) != 1)
+		return -EINVAL;
+	if (val > 20)
+		return -EINVAL;
+	dev->port[num].gap = val;
+	return count;
+}
+
+static ssize_t version_show(struct device *device,
+			    struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "%08x %08x\n",
+		       ddbreadl(dev, 0), ddbreadl(dev, 4));
+}
+
+static ssize_t hwid_show(struct device *device,
+			 struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "0x%08X\n", dev->ids.hwid);
+}
+
+static ssize_t regmap_show(struct device *device,
+			   struct device_attribute *attr, char *buf)
+{
+	struct ddb *dev = dev_get_drvdata(device);
+
+	return sprintf(buf, "0x%08X\n", dev->ids.regmapid);
+}
+
+static struct device_attribute ddb_attrs[] = {
+	__ATTR_RO(version),
+	__ATTR_RO(ports),
+	__ATTR_RO(ts_irq),
+	__ATTR_RO(i2c_irq),
+	__ATTR(gap0, 0666, gap_show, gap_store),
+	__ATTR(gap1, 0666, gap_show, gap_store),
+	__ATTR(gap2, 0666, gap_show, gap_store),
+	__ATTR(gap3, 0666, gap_show, gap_store),
+	__ATTR_RO(hwid),
+	__ATTR_RO(regmap),
+#if 0
+	__ATTR_RO(qam),
+#endif
+	__ATTR(redirect, 0666, redirect_show, redirect_store),
+	__ATTR_MRO(snr,  bsnr_show),
+	__ATTR_NULL,
+};
+
+static struct device_attribute ddb_attrs_temp[] = {
+	__ATTR_RO(temp),
+};
+
+static struct device_attribute ddb_attrs_mod[] = {
+	__ATTR_MRO(mod0, mod_show),
+	__ATTR_MRO(mod1, mod_show),
+	__ATTR_MRO(mod2, mod_show),
+	__ATTR_MRO(mod3, mod_show),
+	__ATTR_MRO(mod4, mod_show),
+	__ATTR_MRO(mod5, mod_show),
+	__ATTR_MRO(mod6, mod_show),
+	__ATTR_MRO(mod7, mod_show),
+	__ATTR_MRO(mod8, mod_show),
+	__ATTR_MRO(mod9, mod_show),
+};
+
+static struct device_attribute ddb_attrs_fan[] = {
+	__ATTR(fan, 0666, fan_show, fan_store),
+};
+
+static struct device_attribute ddb_attrs_snr[] = {
+	__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),
+};
+
+static struct device_attribute ddb_attrs_led[] = {
+	__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),
+};
+
+static struct class ddb_class = {
+	.name		= "ddbridge",
+	.owner          = THIS_MODULE,
+#if 0
+	.dev_attrs	= ddb_attrs,
+#endif
+	.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;
+	if (class_register(&ddb_class) < 0)
+		return -1;
+	return 0;
+}
+
+static void ddb_class_destroy(void)
+{
+	class_unregister(&ddb_class);
+	unregister_chrdev(ddb_major, DDB_NAME);
+}
+
+static void ddb_device_attrs_del(struct ddb *dev)
+{
+	int i;
+
+	for (i = 0; i < dev->info->temp_num; i++)
+		device_remove_file(dev->ddb_dev, &ddb_attrs_temp[i]);
+	for (i = 0; i < dev->info->port_num; i++)
+		device_remove_file(dev->ddb_dev, &ddb_attrs_mod[i]);
+	for (i = 0; i < dev->info->fan_num; i++)
+		device_remove_file(dev->ddb_dev, &ddb_attrs_fan[i]);
+	for (i = 0; i < dev->info->i2c_num; i++) {
+		if (dev->info->led_num)
+			device_remove_file(dev->ddb_dev, &ddb_attrs_led[i]);
+		device_remove_file(dev->ddb_dev, &ddb_attrs_snr[i]);
+	}
+	for (i = 0; ddb_attrs[i].attr.name; i++)
+		device_remove_file(dev->ddb_dev, &ddb_attrs[i]);
+}
+
+static int ddb_device_attrs_add(struct ddb *dev)
+{
+	int i;
+
+	for (i = 0; ddb_attrs[i].attr.name; i++)
+		if (device_create_file(dev->ddb_dev, &ddb_attrs[i]))
+			goto fail;
+	for (i = 0; i < dev->info->temp_num; i++)
+		if (device_create_file(dev->ddb_dev, &ddb_attrs_temp[i]))
+			goto fail;
+	for (i = 0; i < dev->info->port_num; i++)
+		if (device_create_file(dev->ddb_dev, &ddb_attrs_mod[i]))
+			goto fail;
+	for (i = 0; i < dev->info->fan_num; i++)
+		if (device_create_file(dev->ddb_dev, &ddb_attrs_fan[i]))
+			goto fail;
+	for (i = 0; i < dev->info->i2c_num; i++) {
+		if (device_create_file(dev->ddb_dev, &ddb_attrs_snr[i]))
+			goto fail;
+		if (dev->info->led_num)
+			if (device_create_file(dev->ddb_dev,
+					       &ddb_attrs_led[i]))
+				goto fail;
+	}
+	return 0;
+fail:
+	return -1;
+}
+
+static int ddb_device_create(struct ddb *dev)
+{
+	int res = 0;
+
+	if (ddb_num == DDB_MAX_ADAPTER)
+		return -ENOMEM;
+	mutex_lock(&ddb_mutex);
+	dev->nr = ddb_num;
+	ddbs[dev->nr] = dev;
+	dev->ddb_dev = device_create(&ddb_class, dev->dev,
+				     MKDEV(ddb_major, dev->nr),
+				     dev, "ddbridge%d", dev->nr);
+	if (IS_ERR(dev->ddb_dev)) {
+		res = PTR_ERR(dev->ddb_dev);
+		pr_info("Could not create ddbridge%d\n", dev->nr);
+		goto fail;
+	}
+	res = ddb_device_attrs_add(dev);
+	if (res) {
+		ddb_device_attrs_del(dev);
+		device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr));
+		ddbs[dev->nr] = 0;
+		dev->ddb_dev = ERR_PTR(-ENODEV);
+	} else
+		ddb_num++;
+fail:
+	mutex_unlock(&ddb_mutex);
+	return res;
+}
+
+static void ddb_device_destroy(struct ddb *dev)
+{
+	if (IS_ERR(dev->ddb_dev))
+		return;
+	ddb_device_attrs_del(dev);
+	device_destroy(&ddb_class, MKDEV(ddb_major, dev->nr));
+}
diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c
new file mode 100644
index 0000000..bd0d9b1
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c
@@ -0,0 +1,257 @@
+/*
+ * ddbridge-i2c.c: Digital Devices bridge i2c driver
+ *
+ * Copyright (C) 2010-2014 Digital Devices GmbH
+ *                         Ralph Metzler <rmetzler@digitaldevices.de>
+ *
+ * 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
+ */
+
+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,
+				   .buf  = val,  .len   = 1 } };
+	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  = 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},
+				  {.addr = adr,  .flags = I2C_M_RD,
+				   .buf  = val,  .len   = 1 } };
+	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
+}
+
+static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
+			  u16 reg, u8 *val)
+{
+	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 } };
+	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 i2c_write_reg(struct i2c_adapter *adap, u8 adr,
+			 u8 reg, u8 val)
+{
+	u8 msg[2] = {reg, val};
+
+	return i2c_write(adap, adr, msg, 2);
+}
+
+static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
+{
+	struct ddb *dev = i2c->dev;
+	int stat;
+	u32 val;
+
+	ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND);
+	stat = wait_for_completion_timeout(&i2c->completion, HZ);
+	if (stat <= 0) {
+		pr_err("DDBridge I2C timeout, card %d, port %d\n",
+		       dev->nr, i2c->nr);
+#ifdef CONFIG_PCI_MSI
+		{ /* MSI debugging*/
+			u32 istat = ddbreadl(dev, INTERRUPT_STATUS);
+			dev_err(dev->dev, "DDBridge IRS %08x\n", istat);
+			ddbwritel(dev, istat, INTERRUPT_ACK);
+		}
+#endif
+		return -EIO;
+	}
+	val = ddbreadl(dev, i2c->regs + I2C_COMMAND);
+	if (val & 0x70000)
+		return -EIO;
+	return 0;
+}
+
+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 *dev = i2c->dev;
+	u8 addr = 0;
+
+	if (num)
+		addr = msg[0].addr;
+	if (num == 2 && msg[1].flags & I2C_M_RD &&
+	    !(msg[0].flags & I2C_M_RD)) {
+		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
+			    msg[0].buf, msg[0].len);
+		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,
+				      msg[1].len);
+			return num;
+		}
+	}
+	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
+		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(dev, msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
+		if (!ddb_i2c_cmd(i2c, addr, 3)) {
+			ddbcpyfrom(dev, msg[0].buf,
+				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
+			return num;
+		}
+	}
+	return -EIO;
+}
+
+#if 0
+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 *dev = i2c->dev;
+	int ret;
+
+	if (dev->info->type != DDB_OCTONET || i2c->nr == 0 || i2c->nr == 3)
+		return ddb_i2c_master_xfer_locked(adapter, msg, num);
+
+	mutex_lock(&dev->octonet_i2c_lock);
+	ret = ddb_i2c_master_xfer_locked(adapter, msg, num);
+	mutex_unlock(&dev->octonet_i2c_lock);
+	return ret;
+}
+#endif
+
+static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL;
+}
+
+struct i2c_algorithm ddb_i2c_algo = {
+	.master_xfer   = ddb_i2c_master_xfer,
+	.functionality = ddb_i2c_functionality,
+};
+
+static void ddb_i2c_release(struct ddb *dev)
+{
+	int i;
+	struct ddb_i2c *i2c;
+	struct i2c_adapter *adap;
+
+	for (i = 0; i < dev->info->i2c_num; i++) {
+		i2c = &dev->i2c[i];
+		adap = &i2c->adap;
+		i2c_del_adapter(adap);
+	}
+}
+
+static void i2c_handler(unsigned long priv)
+{
+	struct ddb_i2c *i2c = (struct ddb_i2c *) priv;
+
+	complete(&i2c->completion);
+}
+
+static int ddb_i2c_init(struct ddb *dev)
+{
+	int i, j, stat = 0;
+	struct ddb_i2c *i2c;
+	struct i2c_adapter *adap;
+
+	for (i = 0; i < dev->info->i2c_num; i++) {
+		i2c = &dev->i2c[i];
+		dev->handler[i] = i2c_handler;
+		dev->handler_data[i] = (unsigned long) i2c;
+		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(dev, I2C_SPEED_100, i2c->regs + I2C_TIMING);
+		ddbwritel(dev, (i2c->rbuf << 16) | i2c->wbuf,
+			  i2c->regs + I2C_TASKADDRESS);
+		init_completion(&i2c->completion);
+
+		adap = &i2c->adap;
+		i2c_set_adapdata(adap, i2c);
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
+#else
+#ifdef I2C_CLASS_TV_ANALOG
+		adap->class = I2C_CLASS_TV_ANALOG;
+#endif
+#endif
+		strcpy(adap->name, "ddbridge");
+		adap->algo = &ddb_i2c_algo;
+		adap->algo_data = (void *)i2c;
+		adap->dev.parent = dev->dev;
+		stat = i2c_add_adapter(adap);
+		if (stat)
+			break;
+	}
+	if (stat)
+		for (j = 0; j < i; j++) {
+			i2c = &dev->i2c[j];
+			adap = &i2c->adap;
+			i2c_del_adapter(adap);
+		}
+	return stat;
+}
+
diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h
new file mode 100644
index 0000000..eca8574
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge-regs.h
@@ -0,0 +1,436 @@
+/*
+ * ddbridge-regs.h: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2014 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
+ */
+
+/* Register Definitions */
+
+#define CUR_REGISTERMAP_VERSION     0x10003
+#define CUR_REGISTERMAP_VERSION_CI  0x10000
+#define CUR_REGISTERMAP_VERSION_MOD 0x10000
+
+#define HARDWARE_VERSION       0x00
+#define REGISTERMAP_VERSION    0x04
+
+/* ------------------------------------------------------------------------- */
+/* SPI Controller */
+
+#define SPI_CONTROL     0x10
+#define SPI_DATA        0x14
+
+/* ------------------------------------------------------------------------- */
+/* GPIO */
+
+#define GPIO_OUTPUT      0x20
+#define GPIO_INPUT       0x24
+#define GPIO_DIRECTION   0x28
+
+/* ------------------------------------------------------------------------- */
+/* MDIO */
+
+#define MDIO_CTRL        0x20
+#define MDIO_ADR         0x24
+#define MDIO_REG         0x28
+#define MDIO_VAL         0x2C
+
+/* ------------------------------------------------------------------------- */
+
+#define BOARD_CONTROL    0x30
+
+/* ------------------------------------------------------------------------- */
+
+/* Interrupt controller
+   How many MSI's are available depends on HW (Min 2 max 8)
+   How many are usable also depends on Host platform
+*/
+
+#define INTERRUPT_BASE   (0x40)
+
+#define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
+#define MSI0_ENABLE      (INTERRUPT_BASE + 0x00)
+#define MSI1_ENABLE      (INTERRUPT_BASE + 0x04)
+#define MSI2_ENABLE      (INTERRUPT_BASE + 0x08)
+#define MSI3_ENABLE      (INTERRUPT_BASE + 0x0C)
+#define MSI4_ENABLE      (INTERRUPT_BASE + 0x10)
+#define MSI5_ENABLE      (INTERRUPT_BASE + 0x14)
+#define MSI6_ENABLE      (INTERRUPT_BASE + 0x18)
+#define MSI7_ENABLE      (INTERRUPT_BASE + 0x1C)
+
+#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
+#define INTERRUPT_ACK    (INTERRUPT_BASE + 0x20)
+
+#define INTMASK_CLOCKGEN    (0x00000001)
+#define INTMASK_TEMPMON     (0x00000002)
+
+#define INTMASK_I2C1        (0x00000001)
+#define INTMASK_I2C2        (0x00000002)
+#define INTMASK_I2C3        (0x00000004)
+#define INTMASK_I2C4        (0x00000008)
+
+#define INTMASK_CIRQ1       (0x00000010)
+#define INTMASK_CIRQ2       (0x00000020)
+#define INTMASK_CIRQ3       (0x00000040)
+#define INTMASK_CIRQ4       (0x00000080)
+
+#define INTMASK_TSINPUT1    (0x00000100)
+#define INTMASK_TSINPUT2    (0x00000200)
+#define INTMASK_TSINPUT3    (0x00000400)
+#define INTMASK_TSINPUT4    (0x00000800)
+#define INTMASK_TSINPUT5    (0x00001000)
+#define INTMASK_TSINPUT6    (0x00002000)
+#define INTMASK_TSINPUT7    (0x00004000)
+#define INTMASK_TSINPUT8    (0x00008000)
+
+#define INTMASK_TSOUTPUT1   (0x00010000)
+#define INTMASK_TSOUTPUT2   (0x00020000)
+#define INTMASK_TSOUTPUT3   (0x00040000)
+#define INTMASK_TSOUTPUT4   (0x00080000)
+
+
+/*  Clock Generator ( Sil598 @ 0xAA I2c ) */
+#define CLOCKGEN_BASE       (0x80)
+#define CLOCKGEN_CONTROL    (CLOCKGEN_BASE + 0x00)
+#define CLOCKGEN_INDEX      (CLOCKGEN_BASE + 0x04)
+#define CLOCKGEN_WRITEDATA  (CLOCKGEN_BASE + 0x08)
+#define CLOCKGEN_READDATA   (CLOCKGEN_BASE + 0x0C)
+
+/* DAC ( AD9781/AD9783 SPI ) */
+#define DAC_BASE            (0x090)
+#define DAC_CONTROL         (DAC_BASE)
+#define DAC_WRITE_DATA      (DAC_BASE+4)
+#define DAC_READ_DATA       (DAC_BASE+8)
+
+#define DAC_CONTROL_INSTRUCTION_REG (0xFF)
+#define DAC_CONTROL_STARTIO         (0x100)
+#define DAC_CONTROL_RESET           (0x200)
+
+/* Temperature Monitor ( 2x LM75A @ 0x90,0x92 I2c ) */
+#define TEMPMON_BASE        (0xA0)
+#define TEMPMON_CONTROL    (TEMPMON_BASE + 0x00)
+/* SHORT Temperature in °C x 256 */
+#define TEMPMON_CORE       (TEMPMON_BASE + 0x04)
+#define TEMPMON_SENSOR1    (TEMPMON_BASE + 0x08)
+#define TEMPMON_SENSOR2    (TEMPMON_BASE + 0x0C)
+
+/* ------------------------------------------------------------------------- */
+/* I2C Master Controller */
+
+#define I2C_BASE        (0x80)  /* Byte offset */
+
+#define I2C_COMMAND     (0x00)
+#define I2C_TIMING      (0x04)
+#define I2C_TASKLENGTH  (0x08)     /* High read, low write */
+#define I2C_TASKADDRESS (0x0C)     /* High read, low write */
+#define I2C_MONITOR     (0x1C)
+
+#define I2C_BASE_N(i)   (I2C_BASE + (i) * 0x20)
+
+#define I2C_TASKMEM_BASE    (0x1000)    /* Byte offset */
+#define I2C_TASKMEM_SIZE    (0x0800)
+
+#define I2C_SPEED_666   (0x02010202)
+#define I2C_SPEED_400   (0x04030404)
+#define I2C_SPEED_200   (0x09080909)
+#define I2C_SPEED_154   (0x0C0B0C0C)
+#define I2C_SPEED_100   (0x13121313)
+#define I2C_SPEED_77    (0x19181919)
+#define I2C_SPEED_50    (0x27262727)
+
+
+/* ------------------------------------------------------------------------- */
+/* DMA  Controller */
+
+#define DMA_BASE_WRITE        (0x100)
+#define DMA_BASE_READ         (0x140)
+
+#define DMA_CONTROL     (0x00)
+#define DMA_ERROR       (0x04)
+
+#define DMA_DIAG_CONTROL                (0x1C)
+#define DMA_DIAG_PACKETCOUNTER_LOW      (0x20)
+#define DMA_DIAG_PACKETCOUNTER_HIGH     (0x24)
+#define DMA_DIAG_TIMECOUNTER_LOW        (0x28)
+#define DMA_DIAG_TIMECOUNTER_HIGH       (0x2C)
+#define DMA_DIAG_RECHECKCOUNTER         (0x30)
+#define DMA_DIAG_WAITTIMEOUTINIT        (0x34)
+#define DMA_DIAG_WAITOVERFLOWCOUNTER    (0x38)
+#define DMA_DIAG_WAITCOUNTER            (0x3C)
+
+/* ------------------------------------------------------------------------- */
+/* DMA  Buffer */
+
+#define TS_INPUT_BASE       (0x200)
+#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 0x10 + 0x00)
+#define TS_INPUT_CONTROL2(i)        (TS_INPUT_BASE + (i) * 0x10 + 0x04)
+
+#define TS_OUTPUT_BASE       (0x280)
+#define TS_OUTPUT_CONTROL(i)        (TS_OUTPUT_BASE + (i) * 0x10 + 0x00)
+#define TS_OUTPUT_CONTROL2(i)       (TS_OUTPUT_BASE + (i) * 0x10 + 0x04)
+
+#define DMA_BUFFER_BASE     (0x300)
+
+#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 0x10 + 0x00)
+#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 0x10 + 0x04)
+#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 0x10 + 0x08)
+#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 0x10 + 0x0c)
+
+#define DMA_BASE_ADDRESS_TABLE  (0x2000)
+#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
+
+
+/* ------------------------------------------------------------------------- */
+
+#define LNB_BASE                     (0x400)
+#define LNB_CONTROL(i)               (LNB_BASE + (i) * 0x20 + 0x00)
+#define LNB_CMD   (7ULL <<  0)
+#define LNB_CMD_NOP    0
+#define LNB_CMD_INIT   1
+#define LNB_CMD_STATUS 2
+#define LNB_CMD_LOW    3
+#define LNB_CMD_HIGH   4
+#define LNB_CMD_OFF    5
+#define LNB_CMD_DISEQC 6
+#define LNB_CMD_UNI    7
+
+#define LNB_BUSY  (1ULL <<  4)
+#define LNB_TONE  (1ULL << 15)
+
+#define LNB_STATUS(i)                (LNB_BASE + (i) * 0x20 + 0x04)
+#define LNB_VOLTAGE(i)               (LNB_BASE + (i) * 0x20 + 0x08)
+#define LNB_CONFIG(i)                (LNB_BASE + (i) * 0x20 + 0x0c)
+#define LNB_BUF_LEVEL(i)             (LNB_BASE + (i) * 0x20 + 0x10)
+#define LNB_BUF_WRITE(i)             (LNB_BASE + (i) * 0x20 + 0x14)
+
+/* ------------------------------------------------------------------------- */
+/* 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)
+
+#define VCO1_BASE           (0xC0)
+#define VCO1_CONTROL        (VCO1_BASE + 0x00)
+#define VCO1_DATA           (VCO1_BASE + 0x04)  /* 24 Bit */
+/* 1 = Trigger write, resets when done */
+#define VCO1_CONTROL_WRITE  (0x00000001)
+/* 0 = Put VCO into power down */
+#define VCO1_CONTROL_CE     (0x00000002)
+/* Muxout from VCO (usually = Lock) */
+#define VCO1_CONTROL_MUXOUT (0x00000004)
+
+#define VCO2_BASE           (0xC8)
+#define VCO2_CONTROL        (VCO2_BASE + 0x00)
+#define VCO2_DATA           (VCO2_BASE + 0x04)  /* 24 Bit */
+/* 1 = Trigger write, resets when done */
+#define VCO2_CONTROL_WRITE  (0x00000001)
+/* 0 = Put VCO into power down */
+#define VCO2_CONTROL_CE     (0x00000002)
+/* Muxout from VCO (usually = Lock) */
+#define VCO2_CONTROL_MUXOUT (0x00000004)
+
+#define VCO3_BASE           (0xD0)
+#define VCO3_CONTROL        (VCO3_BASE + 0x00)
+#define VCO3_DATA           (VCO3_BASE + 0x04)  /* 32 Bit */
+/* 1 = Trigger write, resets when done */
+#define VCO3_CONTROL_WRITE  (0x00000001)
+/* 0 = Put VCO into power down */
+#define VCO3_CONTROL_CE     (0x00000002)
+/* Muxout from VCO (usually = Lock) */
+#define VCO3_CONTROL_MUXOUT (0x00000004)
+
+#define RF_ATTENUATOR   (0xD8)
+/*  0x00 =  0 dB
+    0x01 =  1 dB
+      ...
+    0x1F = 31 dB
+*/
+
+#define RF_POWER        (0xE0)
+#define RF_POWER_BASE       (0xE0)
+#define RF_POWER_CONTROL    (RF_POWER_BASE + 0x00)
+#define RF_POWER_DATA       (RF_POWER_BASE + 0x04)
+
+#define RF_POWER_CONTROL_START     (0x00000001)
+#define RF_POWER_CONTROL_DONE      (0x00000002)
+#define RF_POWER_CONTROL_VALIDMASK (0x00000700)
+#define RF_POWER_CONTROL_VALID     (0x00000500)
+
+
+/* --------------------------------------------------------------------------
+   Output control
+*/
+
+#define IQOUTPUT_BASE           (0x240)
+#define IQOUTPUT_CONTROL        (IQOUTPUT_BASE + 0x00)
+#define IQOUTPUT_CONTROL2       (IQOUTPUT_BASE + 0x04)
+#define IQOUTPUT_PEAK_DETECTOR  (IQOUTPUT_BASE + 0x08)
+#define IQOUTPUT_POSTSCALER     (IQOUTPUT_BASE + 0x0C)
+#define IQOUTPUT_PRESCALER      (IQOUTPUT_BASE + 0x10)
+
+#define IQOUTPUT_EQUALIZER_0    (IQOUTPUT_BASE + 0x14)
+#define IQOUTPUT_EQUALIZER_1    (IQOUTPUT_BASE + 0x18)
+#define IQOUTPUT_EQUALIZER_2    (IQOUTPUT_BASE + 0x1C)
+#define IQOUTPUT_EQUALIZER_3    (IQOUTPUT_BASE + 0x20)
+#define IQOUTPUT_EQUALIZER_4    (IQOUTPUT_BASE + 0x24)
+#define IQOUTPUT_EQUALIZER_5    (IQOUTPUT_BASE + 0x28)
+#define IQOUTPUT_EQUALIZER_6    (IQOUTPUT_BASE + 0x2C)
+#define IQOUTPUT_EQUALIZER_7    (IQOUTPUT_BASE + 0x30)
+#define IQOUTPUT_EQUALIZER_8    (IQOUTPUT_BASE + 0x34)
+#define IQOUTPUT_EQUALIZER_9    (IQOUTPUT_BASE + 0x38)
+#define IQOUTPUT_EQUALIZER_10   (IQOUTPUT_BASE + 0x3C)
+
+#define IQOUTPUT_EQUALIZER(i)   (IQOUTPUT_EQUALIZER_0 + (i) * 4)
+
+#define IQOUTPUT_CONTROL_RESET              (0x00000001)
+#define IQOUTPUT_CONTROL_ENABLE             (0x00000002)
+#define IQOUTPUT_CONTROL_RESET_PEAK         (0x00000004)
+#define IQOUTPUT_CONTROL_ENABLE_PEAK        (0x00000008)
+#define IQOUTPUT_CONTROL_BYPASS_EQUALIZER   (0x00000010)
+
+
+/* Modulator Base */
+
+#define MODULATOR_BASE          (0x200)
+#define MODULATOR_CONTROL         (MODULATOR_BASE)
+#define MODULATOR_IQTABLE_END     (MODULATOR_BASE+4)
+#define MODULATOR_IQTABLE_INDEX   (MODULATOR_BASE+8)
+#define MODULATOR_IQTABLE_DATA    (MODULATOR_BASE+12)
+
+#define MODULATOR_IQTABLE_INDEX_CHANNEL_MASK  (0x000F0000)
+#define MODULATOR_IQTABLE_INDEX_IQ_MASK       (0x00008000)
+#define MODULATOR_IQTABLE_INDEX_ADDRESS_MASK  (0x000007FF)
+#define MODULATOR_IQTABLE_INDEX_SEL_I         (0x00000000)
+#define MODULATOR_IQTABLE_INDEX_SEL_Q     (MODULATOR_IQTABLE_INDEX_IQ_MASK)
+#define MODULATOR_IQTABLE_SIZE    (2048)
+
+
+/* Modulator Channels */
+
+#define CHANNEL_BASE                (0x400)
+#define CHANNEL_CONTROL(i)          (CHANNEL_BASE + (i) * 64 + 0x00)
+#define CHANNEL_SETTINGS(i)         (CHANNEL_BASE + (i) * 64 + 0x04)
+#define CHANNEL_RATE_INCR(i)        (CHANNEL_BASE + (i) * 64 + 0x0C)
+#define CHANNEL_PCR_ADJUST_OUTL(i)  (CHANNEL_BASE + (i) * 64 + 0x10)
+#define CHANNEL_PCR_ADJUST_OUTH(i)  (CHANNEL_BASE + (i) * 64 + 0x14)
+#define CHANNEL_PCR_ADJUST_INL(i)   (CHANNEL_BASE + (i) * 64 + 0x18)
+#define CHANNEL_PCR_ADJUST_INH(i)   (CHANNEL_BASE + (i) * 64 + 0x1C)
+#define CHANNEL_PCR_ADJUST_ACCUL(i) (CHANNEL_BASE + (i) * 64 + 0x20)
+#define CHANNEL_PCR_ADJUST_ACCUH(i) (CHANNEL_BASE + (i) * 64 + 0x24)
+#define CHANNEL_PKT_COUNT_OUT(i)    (CHANNEL_BASE + (i) * 64 + 0x28)
+#define CHANNEL_PKT_COUNT_IN(i)     (CHANNEL_BASE + (i) * 64 + 0x2C)
+
+#define CHANNEL_CONTROL_RESET               (0x00000001)
+#define CHANNEL_CONTROL_ENABLE_DVB          (0x00000002)
+#define CHANNEL_CONTROL_ENABLE_IQ           (0x00000004)
+#define CHANNEL_CONTROL_ENABLE_SOURCE       (0x00000008)
+#define CHANNEL_CONTROL_ENABLE_PCRADJUST    (0x00000010)
+#define CHANNEL_CONTROL_FREEZE_STATUS       (0x00000100)
+
+#define CHANNEL_CONTROL_RESET_ERROR         (0x00010000)
+#define CHANNEL_CONTROL_BUSY                (0x01000000)
+#define CHANNEL_CONTROL_ERROR_SYNC          (0x20000000)
+#define CHANNEL_CONTROL_ERROR_UNDERRUN      (0x40000000)
+#define CHANNEL_CONTROL_ERROR_FATAL         (0x80000000)
+
+#define CHANNEL_SETTINGS_QAM_MASK           (0x00000007)
+#define CHANNEL_SETTINGS_QAM16              (0x00000000)
+#define CHANNEL_SETTINGS_QAM32              (0x00000001)
+#define CHANNEL_SETTINGS_QAM64              (0x00000002)
+#define CHANNEL_SETTINGS_QAM128             (0x00000003)
+#define CHANNEL_SETTINGS_QAM256             (0x00000004)
+
+
+/* OCTONET */
+
+#define ETHER_BASE       (0x100)
+#define ETHER_CONTROL    (ETHER_BASE + 0x00)
+#define ETHER_LENGTH     (ETHER_BASE + 0x04)
+
+#define RTP_MASTER_BASE      (0x120)
+#define RTP_MASTER_CONTROL          (RTP_MASTER_BASE + 0x00)
+#define RTP_RTCP_INTERRUPT          (RTP_MASTER_BASE + 0x04)
+#define RTP_MASTER_RTCP_SETTINGS    (RTP_MASTER_BASE + 0x0c)
+
+#define STREAM_BASE       (0x400)
+#define STREAM_CONTROL(i)        (STREAM_BASE + (i) * 0x20 + 0x00)
+#define STREAM_RTP_PACKET(i)        (STREAM_BASE + (i) * 0x20 + 0x04)
+#define STREAM_RTCP_PACKET(i)       (STREAM_BASE + (i) * 0x20 + 0x08)
+#define STREAM_RTP_SETTINGS(i)      (STREAM_BASE + (i) * 0x20 + 0x0c)
+#define STREAM_INSERT_PACKET(i)     (STREAM_BASE + (i) * 0x20 + 0x10)
+
+#define STREAM_PACKET_OFF(i) ((i) * 0x200)
+#define STREAM_PACKET_ADR(i) (0x2000 + (STREAM_PACKET_OFF(i)))
+
+#define STREAM_PIDS(i) (0x4000 + (i) * 0x400)
+
+#define TS_CAPTURE_BASE (0x0140)
+#define TS_CAPTURE_CONTROL       (TS_CAPTURE_BASE + 0x00)
+#define TS_CAPTURE_PID           (TS_CAPTURE_BASE + 0x04)
+#define TS_CAPTURE_RECEIVED      (TS_CAPTURE_BASE + 0x08)
+#define TS_CAPTURE_TIMEOUT       (TS_CAPTURE_BASE + 0x0c)
+#define TS_CAPTURE_TABLESECTION  (TS_CAPTURE_BASE + 0x10)
+
+#define TS_CAPTURE_MEMORY (0x7000)
+
+#define PID_FILTER_BASE       (0x800)
+#define PID_FILTER_SYSTEM_PIDS(i)     (PID_FILTER_BASE + (i) * 0x20)
+#define PID_FILTER_PID(i, j)     (PID_FILTER_BASE + (i) * 0x20 + (j) * 4)
+
+
+
diff --git a/drivers/media/pci/ddbridge/ddbridge.c b/drivers/media/pci/ddbridge/ddbridge.c
new file mode 100644
index 0000000..70c7ef0
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge.c
@@ -0,0 +1,460 @@
+/*
+ * ddbridge.c: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2013 Digital Devices GmbH
+ *                         Ralph Metzler <rmetzler@digitaldevices.de>
+ *                         Marcus Metzler <mmetzler@digitaldevices.de>
+ *
+ * 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
+ */
+
+/*#define DDB_ALT_DMA*/
+#define DDB_USE_WORK
+/*#define DDB_TEST_THREADED*/
+
+#include "ddbridge.h"
+#include "ddbridge-regs.h"
+
+static struct workqueue_struct *ddb_wq;
+
+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");
+
+#ifdef CONFIG_PCI_MSI
+static int msi = 1;
+module_param(msi, int, 0444);
+MODULE_PARM_DESC(msi,
+		 " Control MSI interrupts: 0-disable, 1-enable (default)");
+#endif
+
+#include "ddbridge-core.c"
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static void ddb_unmap(struct ddb *dev)
+{
+	if (dev->regs)
+		iounmap(dev->regs);
+	vfree(dev);
+}
+
+
+static void __devexit ddb_remove(struct pci_dev *pdev)
+{
+	struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
+
+	ddb_ports_detach(dev);
+	ddb_i2c_release(dev);
+
+	ddbwritel(dev, 0, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0, MSI1_ENABLE);
+	if (dev->msi == 2)
+		free_irq(dev->pdev->irq + 1, dev);
+	free_irq(dev->pdev->irq, dev);
+#ifdef CONFIG_PCI_MSI
+	if (dev->msi)
+		pci_disable_msi(dev->pdev);
+#endif
+	ddb_ports_release(dev);
+	ddb_buffers_free(dev);
+	ddb_device_destroy(dev);
+
+	ddb_unmap(dev);
+	pci_set_drvdata(pdev, 0);
+	pci_disable_device(pdev);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#define __devinit
+#define __devinitdata
+#endif
+
+static int __devinit ddb_probe(struct pci_dev *pdev,
+			       const struct pci_device_id *id)
+{
+	struct ddb *dev;
+	int stat = 0;
+	int irq_flag = IRQF_SHARED;
+
+	if (pci_enable_device(pdev) < 0)
+		return -ENODEV;
+
+	dev = vzalloc(sizeof(struct ddb));
+	if (dev == NULL)
+		return -ENOMEM;
+
+	dev->has_dma = 1;
+	dev->pdev = pdev;
+	dev->dev = &pdev->dev;
+	pci_set_drvdata(pdev, dev);
+
+	dev->ids.vendor = id->vendor;
+	dev->ids.device = id->device;
+	dev->ids.subvendor = id->subvendor;
+	dev->ids.subdevice = id->subdevice;
+
+	dev->info = (struct ddb_info *) id->driver_data;
+	pr_info("DDBridge driver detected: %s\n", dev->info->name);
+
+	dev->regs_len = pci_resource_len(dev->pdev, 0);
+	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
+			    pci_resource_len(dev->pdev, 0));
+	if (!dev->regs) {
+		pr_err("DDBridge: not enough memory for register map\n");
+		stat = -ENOMEM;
+		goto fail;
+	}
+	if (ddbreadl(dev, 0) == 0xffffffff) {
+		pr_err("DDBridge: cannot read registers\n");
+		stat = -ENODEV;
+		goto fail;
+	}
+
+	dev->ids.hwid = ddbreadl(dev, 0);
+	dev->ids.regmapid = ddbreadl(dev, 4);
+
+	pr_info("HW %08x REGMAP %08x\n",
+		dev->ids.hwid, dev->ids.regmapid);
+
+	ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI1_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI2_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI3_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI4_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI5_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI6_ENABLE);
+	ddbwritel(dev, 0x00000000, MSI7_ENABLE);
+
+#ifdef CONFIG_PCI_MSI
+	if (msi && pci_msi_enabled()) {
+		stat = pci_enable_msi_block(dev->pdev, 2);
+		if (stat == 0) {
+			dev->msi = 1;
+			pr_info("DDBrige using 2 MSI interrupts\n");
+		}
+		if (stat == 1)
+			stat = pci_enable_msi(dev->pdev);
+		if (stat < 0) {
+			pr_info(": MSI not available.\n");
+		} else {
+			irq_flag = 0;
+			dev->msi++;
+		}
+	}
+	if (dev->msi == 2) {
+		stat = request_irq(dev->pdev->irq, irq_handler0,
+				   irq_flag, "ddbridge", (void *) dev);
+		if (stat < 0)
+			goto fail0;
+		stat = request_irq(dev->pdev->irq + 1, irq_handler1,
+				   irq_flag, "ddbridge", (void *) dev);
+		if (stat < 0) {
+			free_irq(dev->pdev->irq, dev);
+			goto fail0;
+		}
+	} else
+#endif
+	{
+#ifdef DDB_TEST_THREADED
+		stat = request_threaded_irq(dev->pdev->irq, irq_handler,
+					    irq_thread,
+					    irq_flag,
+					    "ddbridge", (void *) dev);
+#else
+		stat = request_irq(dev->pdev->irq, irq_handler,
+				   irq_flag, "ddbridge", (void *) dev);
+#endif
+		if (stat < 0)
+			goto fail0;
+	}
+	ddbwritel(dev, 0, DMA_BASE_READ);
+	if (dev->info->type != DDB_MOD)
+		ddbwritel(dev, 0, DMA_BASE_WRITE);
+
+	/*ddbwritel(dev, 0xffffffff, INTERRUPT_ACK);*/
+	if (dev->msi == 2) {
+		ddbwritel(dev, 0x0fffff00, INTERRUPT_ENABLE);
+		ddbwritel(dev, 0x0000000f, MSI1_ENABLE);
+	} else {
+		ddbwritel(dev, 0x0fffff0f, INTERRUPT_ENABLE);
+		ddbwritel(dev, 0x00000000, MSI1_ENABLE);
+	}
+	mutex_init(&dev->lnb_lock);
+	if (ddb_i2c_init(dev) < 0)
+		goto fail1;
+	ddb_ports_init(dev);
+	if (ddb_buffers_alloc(dev) < 0) {
+		pr_info(": Could not allocate buffer memory\n");
+		goto fail2;
+	}
+	if (ddb_ports_attach(dev) < 0)
+		goto fail3;
+
+	/* ignore if this fails */
+	ddb_device_create(dev);
+
+	if (dev->info->fan_num)	{
+		ddbwritel(dev, 1, GPIO_DIRECTION);
+		ddbwritel(dev, 1, GPIO_OUTPUT);
+	}
+	if (dev->info->type == DDB_MOD)
+		ddbridge_mod_init(dev);
+
+	return 0;
+
+fail3:
+	ddb_ports_detach(dev);
+	pr_err("fail3\n");
+	ddb_ports_release(dev);
+fail2:
+	pr_err("fail2\n");
+	ddb_buffers_free(dev);
+	ddb_i2c_release(dev);
+fail1:
+	pr_err("fail1\n");
+	ddbwritel(dev, 0, INTERRUPT_ENABLE);
+	ddbwritel(dev, 0, MSI1_ENABLE);
+	free_irq(dev->pdev->irq, dev);
+	if (dev->msi == 2)
+		free_irq(dev->pdev->irq + 1, dev);
+fail0:
+	pr_err("fail0\n");
+	if (dev->msi)
+		pci_disable_msi(dev->pdev);
+fail:
+	pr_err("fail\n");
+	ddb_unmap(dev);
+	pci_set_drvdata(pdev, 0);
+	pci_disable_device(pdev);
+	return -1;
+}
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+static struct ddb_regset octopus_i2c = {
+	.base = 0x80,
+	.num  = 0x04,
+	.size = 0x20,
+};
+
+static struct ddb_regmap octopus_map = {
+	.i2c = &octopus_i2c,
+};
+
+static struct ddb_info ddb_none = {
+	.type     = DDB_NONE,
+	.name     = "unknown Digital Devices PCIe card, install newer driver",
+	.regmap   = &octopus_map,
+};
+
+static struct ddb_info ddb_octopus = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus DVB adapter",
+	.port_num = 4,
+	.i2c_num  = 4,
+};
+
+static struct ddb_info ddb_octopusv3 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Octopus V3 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,
+	.temp_bus = 0,
+};
+
+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_v6_5 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Cine S2 V6.5 DVB adapter",
+	.port_num = 4,
+	.i2c_num  = 4,
+};
+
+static struct ddb_info ddb_v7 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Cine S2 V7 DVB adapter",
+	.port_num = 4,
+	.i2c_num  = 4,
+	.board_control = 2,
+};
+
+static struct ddb_info ddb_s2_48 = {
+	.type     = DDB_OCTOPUS_MAX,
+	.name     = "Digital Devices Cine S2 4/8",
+	.port_num = 4,
+	.i2c_num  = 1,
+	.board_control = 1,
+};
+
+static struct ddb_info ddb_ctv7 = {
+	.type     = DDB_OCTOPUS,
+	.name     = "Digital Devices Cine CT V7 DVB adapter",
+	.port_num = 4,
+	.i2c_num  = 4,
+	.board_control = 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,
+};
+
+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_mod = {
+	.type     = DDB_MOD,
+	.name     = "Digital Devices DVB-C modulator",
+	.port_num = 10,
+	.temp_num = 1,
+};
+
+#define DDVID 0xdd01 /* Digital Devices Vendor ID */
+
+#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) { \
+	.vendor      = _vend,    .device    = _dev, \
+	.subvendor   = _subvend, .subdevice = _subdev, \
+	.driver_data = (unsigned long)&_driverdata }
+
+static const struct pci_device_id ddb_id_tbl[] __devinitconst = {
+	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
+	DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
+	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, 0x0021, ddb_v6_5),
+	DDB_ID(DDVID, 0x0006, DDVID, 0x0022, ddb_v7),
+	DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
+	DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
+	DDB_ID(DDVID, 0x0006, DDVID, 0x0031, ddb_ctv7),
+	DDB_ID(DDVID, 0x0006, DDVID, 0x0032, ddb_ctv7),
+	DDB_ID(DDVID, 0x0006, DDVID, 0x0033, ddb_ctv7),
+	DDB_ID(DDVID, 0x0007, DDVID, 0x0023, ddb_s2_48),
+	DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci),
+	DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis),
+	DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod),
+	/* in case sub-ids got deleted in flash */
+	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
+	DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
+	DDB_ID(DDVID, 0x0201, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
+	{0}
+};
+MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
+
+static struct pci_driver ddb_pci_driver = {
+	.name        = "ddbridge",
+	.id_table    = ddb_id_tbl,
+	.probe       = ddb_probe,
+	.remove      = ddb_remove,
+};
+
+static __init int module_init_ddbridge(void)
+{
+	int stat = -1;
+
+	pr_info("Digital Devices PCIE bridge driver "
+		DDBRIDGE_VERSION
+		", Copyright (C) 2010-14 Digital Devices GmbH\n");
+	if (ddb_class_create() < 0)
+		return -1;
+	ddb_wq = create_workqueue("ddbridge");
+	if (ddb_wq == NULL)
+		goto exit1;
+	stat = pci_register_driver(&ddb_pci_driver);
+	if (stat < 0)
+		goto exit2;
+	return stat;
+exit2:
+	destroy_workqueue(ddb_wq);
+exit1:
+	ddb_class_destroy();
+	return stat;
+}
+
+static __exit void module_exit_ddbridge(void)
+{
+	pci_unregister_driver(&ddb_pci_driver);
+	destroy_workqueue(ddb_wq);
+	ddb_class_destroy();
+}
+
+module_init(module_init_ddbridge);
+module_exit(module_exit_ddbridge);
+
+MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
+MODULE_AUTHOR("Ralph Metzler, Metzler Brothers Systementwicklung");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DDBRIDGE_VERSION); 
diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
new file mode 100644
index 0000000..1d028cf
--- /dev/null
+++ b/drivers/media/pci/ddbridge/ddbridge.h
@@ -0,0 +1,499 @@
+/*
+ * ddbridge.h: Digital Devices PCIe bridge driver
+ *
+ * Copyright (C) 2010-2014 Digital Devices GmbH
+ *                         Ralph Metzler <rmetzler@digitaldevices.de>
+ *
+ * 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
+ */
+
+#ifndef _DDBRIDGE_H_
+#define _DDBRIDGE_H_
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#define __devexit
+#define __devinit
+#define __devinitconst
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/timer.h>
+#include <linux/i2c.h>
+#include <linux/swab.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <linux/kthread.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <linux/completion.h>
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <linux/dvb/ca.h>
+#include <linux/socket.h>
+#include <linux/device.h>
+#include <linux/io.h>
+
+#include "dvb_netstream.h"
+#include "dmxdev.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_ringbuffer.h"
+#include "dvb_ca_en50221.h"
+#include "dvb_net.h"
+
+#include "tda18271c2dd.h"
+#include "stv6110x.h"
+#include "stv090x.h"
+#include "lnbh24.h"
+#include "drxk.h"
+#include "stv0367.h"
+#include "stv0367dd.h"
+#include "tda18212.h"
+#include "tda18212dd.h"
+#include "cxd2843.h"
+#include "cxd2099.h"
+#include "stv0910.h"
+#include "stv6111.h"
+#include "lnbh25.h"
+#include "mxl5xx.h"
+
+#define DDB_MAX_I2C     4
+#define DDB_MAX_PORT   10
+#define DDB_MAX_INPUT   8
+#define DDB_MAX_OUTPUT 10
+
+struct ddb_regset {
+	u32 base;
+	u32 num;
+	u32 size;
+};
+
+struct ddb_regmap {
+	struct ddb_regset *i2c;
+	struct ddb_regset *i2c_buf;
+	struct ddb_regset *dma;
+	struct ddb_regset *dma_buf;
+	struct ddb_regset *input;
+	struct ddb_regset *output;
+	struct ddb_regset *channel;
+	struct ddb_regset *ci;
+	struct ddb_regset *pid_filter;
+	struct ddb_regset *ns;
+};
+
+struct ddb_ids {
+	u16 vendor;
+	u16 device;
+	u16 subvendor;
+	u16 subdevice;
+
+	u32 hwid;
+	u32 regmapid;
+	u32 devid;
+	u32 mac;
+};
+
+struct ddb_info {
+	int   type;
+#define DDB_NONE         0
+#define DDB_OCTOPUS      1
+#define DDB_OCTOPUS_CI   2
+#define DDB_MOD          3
+#define DDB_OCTONET      4
+#define DDB_OCTOPUS_MAX  5
+	char *name;
+	u8    port_num;
+	u8    i2c_num;
+	u8    led_num;
+	u8    fan_num;
+	u8    temp_num;
+	u8    temp_bus;
+	u8    board_control;
+	u8    ns_num;
+	u8    mdio_num;
+	struct ddb_regmap *regmap;
+};
+
+
+/* DMA_SIZE MUST be smaller than 256k and
+   MUST be divisible by 188 and 128 !!! */
+
+#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_BUFS 8
+#define OUTPUT_DMA_SIZE (128*47*21)
+#define OUTPUT_DMA_IRQ_DIV 1
+
+struct ddb;
+struct ddb_port;
+
+struct ddb_dma {
+	void                  *io;
+	u32                    nr;
+	dma_addr_t             pbuf[DMA_MAX_BUFS];
+	u8                    *vbuf[DMA_MAX_BUFS];
+	u32                    num;
+	u32                    size;
+	u32                    div;
+	u32                    bufreg;
+
+#ifdef DDB_USE_WORK
+	struct work_struct     work;
+#else
+	struct tasklet_struct  tasklet;
+#endif
+	spinlock_t             lock;
+	wait_queue_head_t      wq;
+	int                    running;
+	u32                    stat;
+	u32                    ctrl;
+	u32                    cbuf;
+	u32                    coff;
+};
+
+struct ddb_dvb {
+	struct dvb_adapter    *adap;
+	int                    adap_registered;
+	struct dvb_device     *dev;
+	struct dvb_frontend   *fe;
+	struct dvb_frontend   *fe2;
+	struct dmxdev          dmxdev;
+	struct dvb_demux       demux;
+	struct dvb_net         dvbnet;
+	struct dvb_netstream   dvbns;
+	struct dmx_frontend    hw_frontend;
+	struct dmx_frontend    mem_frontend;
+	int                    users;
+	u32                    attached;
+	u8                     input;
+
+	int (*i2c_gate_ctrl)(struct dvb_frontend *, int);
+	int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
+	int (*set_input)(struct dvb_frontend *fe);
+};
+
+struct ddb_ci {
+	struct dvb_ca_en50221  en;
+	struct ddb_port       *port;
+	u32                    nr;
+	struct mutex           lock;
+};
+
+struct ddb_io {
+	struct ddb_port       *port;
+	u32                    nr;
+	struct ddb_dma        *dma;
+	struct ddb_io         *redo;
+	struct ddb_io         *redi;
+};
+
+#define ddb_output ddb_io
+#define ddb_input ddb_io
+
+struct ddb_i2c {
+	struct ddb            *dev;
+	u32                    nr;
+	struct i2c_adapter     adap;
+	u32                    regs;
+	u32                    rbuf;
+	u32                    wbuf;
+	struct completion      completion;
+};
+
+struct ddb_port {
+	struct ddb            *dev;
+	u32                    nr;
+	struct ddb_i2c        *i2c;
+	struct mutex           i2c_gate_lock;
+	u32                    class;
+#define DDB_PORT_NONE           0
+#define DDB_PORT_CI             1
+#define DDB_PORT_TUNER          2
+#define DDB_PORT_LOOP           3
+#define DDB_PORT_MOD            4
+	char                   *name;
+	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       3
+#define DDB_TUNER_DVBCT_ST       4
+#define DDB_CI_INTERNAL          5
+#define DDB_CI_EXTERNAL_SONY     6
+#define DDB_TUNER_DVBCT2_SONY_P  7
+#define DDB_TUNER_DVBC2T2_SONY_P 8
+#define DDB_TUNER_ISDBT_SONY_P   9
+#define DDB_TUNER_DVBS_STV0910_P 10
+#define DDB_TUNER_MXL5XX         11
+
+#define DDB_TUNER_XO2           16
+#define DDB_TUNER_DVBS_STV0910  16
+#define DDB_TUNER_DVBCT2_SONY   17
+#define DDB_TUNER_ISDBT_SONY    18
+#define DDB_TUNER_DVBC2T2_SONY  19
+#define DDB_TUNER_ATSC_ST       20
+#define DDB_TUNER_DVBC2T2_ST    21
+
+	/*u32                    adr;*/
+	struct ddb_input      *input[2];
+	struct ddb_output     *output;
+	struct dvb_ca_en50221 *en;
+	struct ddb_dvb         dvb[2];
+	u32                    gap;
+	u32                    obr;
+};
+
+
+struct mod_base {
+	u32                    frequency;
+
+	u32                    flat_start;
+	u32                    flat_end;
+};
+
+struct mod_state {
+	u32                    modulation;
+	u64                    obitrate;
+	u64                    ibitrate;
+	u32                    pcr_correction;
+
+	u32                    rate_inc;
+	u32                    Control;
+	u32                    State;
+	u32                    StateCounter;
+	s32                    LastPCRAdjust;
+	s32                    PCRAdjustSum;
+	s32                    InPacketsSum;
+	s32                    OutPacketsSum;
+	s64                    PCRIncrement;
+	s64                    PCRDecrement;
+	s32                    PCRRunningCorr;
+	u32                    OutOverflowPacketCount;
+	u32                    InOverflowPacketCount;
+	u32                    LastOutPacketCount;
+	u32                    LastInPacketCount;
+	u64                    LastOutPackets;
+	u64                    LastInPackets;
+	u32                    MinInputPackets;
+};
+
+#define CM_STARTUP_DELAY 2
+#define CM_AVERAGE  20
+#define CM_GAIN     10
+
+#define HW_LSB_SHIFT    12
+#define HW_LSB_MASK     0x1000
+
+#define CM_IDLE    0
+#define CM_STARTUP 1
+#define CM_ADJUST  2
+
+#define TS_CAPTURE_LEN  (4096)
+
+/* net streaming hardware block */
+
+#define DDB_NS_MAX 15
+
+struct ddb_ns {
+	struct ddb_input      *input;
+	int                    nr;
+	int                    fe;
+	u32                    rtcp_udplen;
+	u32                    rtcp_len;
+	u32                    ts_offset;
+	u32                    udplen;
+	u8                     p[512];
+};
+
+struct ddb {
+	struct pci_dev        *pdev;
+	struct platform_device *pfdev;
+	struct device         *dev;
+	struct ddb_ids         ids;
+	struct ddb_info       *info;
+	int                    msi;
+	struct workqueue_struct *wq;
+	u32                    has_dma;
+	u32                    has_ns;
+
+	struct ddb_regmap      regmap;
+	unsigned char         *regs;
+	u32                    regs_len;
+	struct ddb_port        port[DDB_MAX_PORT];
+	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];
+
+	void                   (*handler[32])(unsigned long);
+	unsigned long          handler_data[32];
+
+	struct device         *ddb_dev;
+	u32                    ddb_dev_users;
+	u32                    nr;
+	u8                     iobuf[1028];
+
+	u8                     leds;
+	u32                    ts_irq;
+	u32                    i2c_irq;
+
+	int                    ns_num;
+	struct ddb_ns          ns[DDB_NS_MAX];
+	struct mutex           mutex;
+
+	struct dvb_device     *nsd_dev;
+	u8                     tsbuf[TS_CAPTURE_LEN];
+
+	struct mod_base        mod_base;
+	struct mod_state       mod[10];
+
+	struct mutex           octonet_i2c_lock;
+	struct mutex           lnb_lock;
+	u32                    lnb_tone;
+};
+
+
+/****************************************************************************/
+
+static inline void ddbwriteb(struct ddb *dev, u32 val, u32 adr)
+{
+	writeb(val, (char *) (dev->regs+(adr)));
+}
+
+static inline void ddbwritel(struct ddb *dev, u32 val, u32 adr)
+{
+	writel(val, (char *) (dev->regs+(adr)));
+}
+
+static inline void ddbwritew(struct ddb *dev, u16 val, u32 adr)
+{
+	writew(val, (char *) (dev->regs+(adr)));
+}
+
+static inline u32 ddbreadl(struct ddb *dev, u32 adr)
+{
+	return readl((char *) (dev->regs+(adr)));
+}
+
+static inline u32 ddbreadb(struct ddb *dev, u32 adr)
+{
+	return readb((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))
+
+#define ddbmemset(_dev, _adr, _val, _count) \
+	memset_io((char *) (_dev->regs + (_adr)), (_val), (_count))
+
+
+/****************************************************************************/
+/****************************************************************************/
+/****************************************************************************/
+
+#define dd_uint8    u8
+#define dd_uint16   u16
+#define dd_int16    s16
+#define dd_uint32   u32
+#define dd_int32    s32
+#define dd_uint64   u64
+#define dd_int64    s64
+
+#define DDMOD_FLASH_START  0x1000
+
+struct DDMOD_FLASH_DS {
+	dd_uint32   Symbolrate;             /* kSymbols/s */
+	dd_uint32   DACFrequency;           /* kHz        */
+	dd_uint16   FrequencyResolution;    /* kHz        */
+	dd_uint16   IQTableLength;
+	dd_uint16   FrequencyFactor;
+	dd_int16    PhaseCorr;              /* TBD        */
+	dd_uint32   Control2;
+	dd_uint16   PostScaleI;
+	dd_uint16   PostScaleQ;
+	dd_uint16   PreScale;
+	dd_int16    EQTap[11];
+	dd_uint16   FlatStart;
+	dd_uint16   FlatEnd;
+	dd_uint32   FlashOffsetPrecalculatedIQTables;       /* 0 = none */
+	dd_uint8    Reserved[28];
+
+};
+
+struct DDMOD_FLASH {
+	dd_uint32   Magic;
+	dd_uint16   Version;
+	dd_uint16   DataSets;
+
+	dd_uint16   VCORefFrequency;    /* MHz */
+	dd_uint16   VCO1Frequency;      /* MHz */
+	dd_uint16   VCO2Frequency;      /* MHz */
+
+	dd_uint16   DACAux1;    /* TBD */
+	dd_uint16   DACAux2;    /* TBD */
+
+	dd_uint8    Reserved1[238];
+
+	struct DDMOD_FLASH_DS DataSet[1];
+};
+
+#define DDMOD_FLASH_MAGIC   0x5F564d5F
+
+
+int ddbridge_mod_do_ioctl(struct file *file, unsigned int cmd, void *parg);
+int ddbridge_mod_init(struct ddb *dev);
+void ddbridge_mod_output_stop(struct ddb_output *output);
+void ddbridge_mod_output_start(struct ddb_output *output);
+void ddbridge_mod_rate_handler(unsigned long data);
+
+
+int ddbridge_flashread(struct ddb *dev, u8 *buf, u32 addr, u32 len);
+
+#define DDBRIDGE_VERSION "0.9.15"
+
+#endif
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/5] ddbridge: clean up driver for release
  2014-08-02  3:48 [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Antti Palosaari
                   ` (3 preceding siblings ...)
  2014-08-02  3:48 ` [PATCH 4/5] ddbridge: add needed files from manufacturer driver 0.9.15a Antti Palosaari
@ 2014-08-02  3:48 ` Antti Palosaari
  2014-08-23 11:50 ` [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Bjoern
  2014-09-23  8:42 ` Guy Martin
  6 siblings, 0 replies; 11+ messages in thread
From: Antti Palosaari @ 2014-08-02  3:48 UTC (permalink / raw)
  To: linux-media; +Cc: Antti Palosaari

Enable driver compilation. Clean up driver.
Remove network streaming and modulator functionality - needs API
first.

Remove few receivers which are not supported due to missing DTV
frontend chipset drivers or due to lack of correct device profile
(+ I don't have hw to implement profile). Those removed receivers
are based of following DTV chipsets:
MaxLinear MxL5xx
STMicroelectronics STV0910
STMicroelectronics STV0367

Signed-off-by: Antti Palosaari <crope@iki.fi>
---
 drivers/media/pci/ddbridge/Makefile        |   5 +-
 drivers/media/pci/ddbridge/ddbridge-core.c | 813 ++---------------------------
 drivers/media/pci/ddbridge/ddbridge-i2c.c  |  25 -
 drivers/media/pci/ddbridge/ddbridge.c      |  20 +-
 drivers/media/pci/ddbridge/ddbridge.h      |  16 -
 5 files changed, 65 insertions(+), 814 deletions(-)

diff --git a/drivers/media/pci/ddbridge/Makefile b/drivers/media/pci/ddbridge/Makefile
index 39e922c..2610161 100644
--- a/drivers/media/pci/ddbridge/Makefile
+++ b/drivers/media/pci/ddbridge/Makefile
@@ -2,10 +2,7 @@
 # Makefile for the ddbridge device driver
 #
 
-ddbridge-objs := ddbridge-core.o
-
-#obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
-obj-$() += ddbridge.o
+obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
 
 ccflags-y += -Idrivers/media/dvb-core/
 ccflags-y += -Idrivers/media/dvb-frontends/
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index a301be6..c66b1b3 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -45,10 +45,7 @@ static struct ddb *ddbs[DDB_MAX_ADAPTER];
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-#include "ddbridge-mod.c"
 #include "ddbridge-i2c.c"
-#include "ddbridge-ns.c"
-
 
 static void ddb_set_dma_table(struct ddb *dev, struct ddb_dma *dma)
 {
@@ -281,9 +278,8 @@ static int ddb_buffers_alloc(struct ddb *dev)
 			if (dma_alloc(dev->pdev, port->input[0]->dma, 0) < 0)
 				return -1;
 		case DDB_PORT_MOD:
-			if (dma_alloc(dev->pdev, port->output->dma, 1) < 0)
-				return -1;
-			break;
+			/* TODO: modulator not supported */
+			return -1;
 		default:
 			break;
 		}
@@ -324,9 +320,9 @@ static void ddb_output_start(struct ddb_output *output)
 		output->dma->stat = 0;
 		ddbwritel(dev, 0, DMA_BUFFER_CONTROL(output->dma->nr));
 	}
-	if (output->port->class == DDB_PORT_MOD)
-		ddbridge_mod_output_start(output);
-	else {
+	if (output->port->class == DDB_PORT_MOD) {
+		/* TODO: modulator not supported */
+	} else {
 		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
 		ddbwritel(dev, 2, TS_OUTPUT_CONTROL(output->nr));
 		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
@@ -363,7 +359,8 @@ static void ddb_output_stop(struct ddb_output *output)
 	if (output->dma)
 		spin_lock_irq(&output->dma->lock);
 	if (output->port->class == DDB_PORT_MOD)
-		ddbridge_mod_output_stop(output);
+		/* TODO: modulator not supported */
+		;
 	else
 		ddbwritel(dev, 0, TS_OUTPUT_CONTROL(output->nr));
 	if (output->dma) {
@@ -422,28 +419,6 @@ static void ddb_input_start(struct ddb_input *input)
 	/*pr_info("input_start %d.%d\n", dev->nr, input->nr);*/
 }
 
-
-static int ddb_dvb_input_start(struct ddb_input *input)
-{
-	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-
-	if (!dvb->users)
-		ddb_input_start(input);
-
-	return ++dvb->users;
-}
-
-static int ddb_dvb_input_stop(struct ddb_input *input)
-{
-	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-
-	if (--dvb->users)
-		return dvb->users;
-
-	ddb_input_stop(input);
-	return 0;
-}
-
 static void ddb_input_start_all(struct ddb_input *input)
 {
 	struct ddb_input *i = input;
@@ -496,25 +471,6 @@ static u32 ddb_output_free(struct ddb_output *output)
 	return 0;
 }
 
-#if 0
-static u32 ddb_dma_free(struct ddb_dma *dma)
-{
-	u32 idx, off, stat = dma->stat;
-	s32 p1, p2, diff;
-
-	idx = (stat >> 11) & 0x1f;
-	off = (stat & 0x7ff) << 7;
-
-	p1 = idx * dma->size + off;
-	p2 = dma->cbuf * dma->size + dma->coff;
-
-	diff = p1 - p2;
-	if (diff <= 0)
-		diff += dma->num * dma->size;
-	return diff;
-}
-#endif
-
 static ssize_t ddb_output_write(struct ddb_output *output,
 				const u8 *buf, size_t count)
 {
@@ -570,81 +526,6 @@ static ssize_t ddb_output_write(struct ddb_output *output,
 	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;
@@ -826,36 +707,6 @@ static int ts_open(struct inode *inode, struct file *file)
 	return err;
 }
 
-static int mod_release(struct inode *inode, struct file *file)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-
-	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
-		if (!output)
-			return -EINVAL;
-		ddb_output_stop(output);
-	}
-	return dvb_generic_release(inode, file);
-}
-
-static int mod_open(struct inode *inode, struct file *file)
-{
-	int err;
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb_output *output = dvbdev->priv;
-
-	if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
-		if (!output)
-			return -EINVAL;
-	}
-	err = dvb_generic_open(inode, file);
-	if (err < 0)
-		return err;
-	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
-		ddb_output_start(output);
-	return err;
-}
 static const struct file_operations ci_fops = {
 	.owner   = THIS_MODULE,
 	.read    = ts_read,
@@ -878,44 +729,10 @@ static struct dvb_device dvbdev_ci = {
 /****************************************************************************/
 /****************************************************************************/
 
-static long mod_ioctl(struct file *file,
-		      unsigned int cmd, unsigned long arg)
-{
-	return dvb_usercopy(file, cmd, arg, ddbridge_mod_do_ioctl);
-}
-
-static const struct file_operations mod_fops = {
-	.owner   = THIS_MODULE,
-	.read    = ts_read,
-	.write   = ts_write,
-	.open    = mod_open,
-	.release = mod_release,
-	.poll    = ts_poll,
-	.mmap    = 0,
-	.unlocked_ioctl = mod_ioctl,
-};
-
-static struct dvb_device dvbdev_mod = {
-	.priv    = 0,
-	.readers = 1,
-	.writers = 1,
-	.users   = 2,
-	.fops    = &mod_fops,
-};
-
 
-#if 0
-static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
-{
-	int i;
 
-	for (i = 0; i < dev->info->port_num * 2; i++) {
-		if (dev->input[i].fe == fe)
-			return &dev->input[i];
-	}
-	return NULL;
-}
-#endif
+/****************************************************************************/
+/****************************************************************************/
 
 static int locked_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
@@ -934,16 +751,19 @@ static int locked_gate_ctrl(struct dvb_frontend *fe, int enable)
 	return status;
 }
 
-#ifdef CONFIG_DVB_DRXK
 static int demod_attach_drxk(struct ddb_input *input)
 {
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
 	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 	struct dvb_frontend *fe;
+	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);
 
-	fe = dvb->fe = dvb_attach(drxk_attach,
-				  i2c, 0x29 + (input->nr&1),
-				  &dvb->fe2);
+	fe = dvb->fe = dvb_attach(drxk_attach, &config, i2c);
 	if (!fe) {
 		pr_err("No DRXK found!\n");
 		return -ENODEV;
@@ -953,47 +773,6 @@ static int demod_attach_drxk(struct ddb_input *input)
 	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
 	return 0;
 }
-#endif
-
-#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 ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-	struct dvb_frontend *fe;
-
-	fe = dvb->fe = dvb_attach(stv0367ter_attach,
-				  (input->nr & 1) ? &stv0367_1 : &stv0367_0,
-				  i2c);
-	if (!dvb->fe) {
-		pr_err("No stv0367 found!\n");
-		return -ENODEV;
-	}
-	fe->sec_priv = input;
-	dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl;
-	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
-	return 0;
-}
-#endif
 
 struct cxd2843_cfg cxd2843_0 = {
 	.adr = 0x6c,
@@ -1037,36 +816,6 @@ static int demod_attach_cxd2843(struct ddb_input *input, int par)
 	return 0;
 }
 
-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 ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-	struct dvb_frontend *fe;
-
-	fe = dvb->fe = dvb_attach(stv0367_attach, i2c,
-				  (input->nr & 1) ?
-				  &stv0367dd_1 : &stv0367dd_0,
-				  &dvb->fe2);
-	if (!dvb->fe) {
-		pr_err("No stv0367 found!\n");
-		return -ENODEV;
-	}
-	fe->sec_priv = input;
-	dvb->i2c_gate_ctrl = fe->ops.i2c_gate_ctrl;
-	fe->ops.i2c_gate_ctrl = locked_gate_ctrl;
-	return 0;
-}
-
 static int tuner_attach_tda18271(struct ddb_input *input)
 {
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
@@ -1085,28 +834,26 @@ static int tuner_attach_tda18271(struct ddb_input *input)
 	return 0;
 }
 
-static int tuner_attach_tda18212dd(struct ddb_input *input)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-	struct dvb_frontend *fe;
-
-	fe = dvb_attach(tda18212dd_attach, dvb->fe, i2c,
-			(input->nr & 1) ? 0x63 : 0x60);
-	if (!fe) {
-		pr_err("No TDA18212 found!\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-#ifdef CONFIG_DVB_TDA18212
-struct tda18212_config tda18212_0 = {
+static struct tda18212_config tda18212_config_60 = {
 	.i2c_address = 0x60,
+	.if_dvbt_6 = 3550,
+	.if_dvbt_7 = 3700,
+	.if_dvbt_8 = 4150,
+	.if_dvbt2_6 = 3250,
+	.if_dvbt2_7 = 4000,
+	.if_dvbt2_8 = 4000,
+	.if_dvbc = 5000,
 };
 
-struct tda18212_config tda18212_1 = {
+static struct tda18212_config tda18212_config_63 = {
 	.i2c_address = 0x63,
+	.if_dvbt_6 = 3550,
+	.if_dvbt_7 = 3700,
+	.if_dvbt_8 = 4150,
+	.if_dvbt2_6 = 3250,
+	.if_dvbt2_7 = 4000,
+	.if_dvbt2_8 = 4000,
+	.if_dvbc = 5000,
 };
 
 static int tuner_attach_tda18212(struct ddb_input *input)
@@ -1114,17 +861,20 @@ static int tuner_attach_tda18212(struct ddb_input *input)
 	struct i2c_adapter *i2c = &input->port->i2c->adap;
 	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
 	struct dvb_frontend *fe;
-	struct tda18212_config *cfg;
+	struct tda18212_config *config;
+
+	if (input->nr & 1)
+		config = &tda18212_config_63;
+	else
+		config = &tda18212_config_60;
 
-	cfg = (input->nr & 1) ? &tda18212_1 : &tda18212_0;
-	fe = dvb_attach(tda18212_attach, dvb->fe, i2c, cfg);
+	fe = dvb_attach(tda18212_attach, dvb->fe, i2c, config);
 	if (!fe) {
 		pr_err("No TDA18212 found!\n");
 		return -ENODEV;
 	}
 	return 0;
 }
-#endif
 
 /****************************************************************************/
 /****************************************************************************/
@@ -1240,181 +990,6 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type)
 	return 0;
 }
 
-static struct stv0910_cfg stv0910 = {
-	.adr      = 0x68,
-	.parallel = 1,
-	.rptlvl   = 4,
-	.clk      = 30000000,
-};
-
-static int demod_attach_stv0910(struct ddb_input *input, int type)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-
-	dvb->fe = dvb_attach(stv0910_attach, i2c, &stv0910, (input->nr & 1));
-	if (!dvb->fe) {
-		pr_err("No STV0910 found!\n");
-		return -ENODEV;
-	}
-	if (!dvb_attach(lnbh25_attach, dvb->fe, i2c,
-			(input->nr & 1) ? 0x09 : 0x08)) {
-		pr_err("No LNBH25 found!\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static int tuner_attach_stv6111(struct ddb_input *input)
-{
-	struct i2c_adapter *i2c = &input->port->i2c->adap;
-	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-	struct dvb_frontend *fe;
-
-	fe = dvb_attach(stv6111_attach, dvb->fe, i2c,
-			(input->nr & 1) ? 0x63 : 0x60);
-	if (!fe) {
-		pr_err("No STV6111 found!\n");
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static struct mxl5xx_cfg mxl5xx = {
-	.adr      = 0x60,
-	.type     = 0x01,
-	.clk      = 27000000,
-	.cap      = 12,
-};
-
-static int lnb_command(struct ddb *dev, u32 lnb, u32 cmd)
-{
-	u32 c, v = 0;
-
-	v = LNB_TONE & (dev->lnb_tone << (15 - lnb));
-	pr_info("lnb_control[%u] = %08x\n", lnb, cmd | v);
-	ddbwritel(dev, cmd | v, LNB_CONTROL(lnb));
-	for (c = 0; c < 10; c++) {
-		v = ddbreadl(dev, LNB_CONTROL(lnb));
-		pr_info("ctrl = %08x\n", v);
-		if ((v & LNB_BUSY) == 0)
-			break;
-		msleep(20);
-	}
-	return 0;
-}
-
-static int dd_send_master_cmd(struct dvb_frontend *fe,
-			      struct dvb_diseqc_master_cmd *cmd)
-{
-	struct ddb_input *input = fe->sec_priv;
-	struct ddb_port *port = input->port;
-	struct ddb *dev = port->dev;
-	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
-	int i;
-
-	mutex_lock(&dev->lnb_lock);
-	ddbwritel(dev, 0, LNB_BUF_LEVEL(dvb->input));
-	for (i = 0; i < cmd->msg_len; i++)
-		ddbwritel(dev, cmd->msg[i], LNB_BUF_WRITE(dvb->input));
-	lnb_command(dev, dvb->input, LNB_CMD_DISEQC);
-	mutex_unlock(&dev->lnb_lock);
-	return 0;
-}
-
-static int dd_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
-{
-	struct ddb_input *input = fe->sec_priv;
-	struct ddb_port *port = input->port;
-	struct ddb *dev = port->dev;
-	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
-	int s = 0;
-
-	mutex_lock(&dev->lnb_lock);
-	switch (tone) {
-	case SEC_TONE_OFF:
-		dev->lnb_tone &= ~(1ULL << dvb->input);
-		break;
-	case SEC_TONE_ON:
-		dev->lnb_tone |= (1ULL << dvb->input);
-		break;
-	default:
-		s = -EINVAL;
-		break;
-	};
-	if (!s)
-		s = lnb_command(dev, dvb->input, LNB_CMD_NOP);
-	mutex_unlock(&dev->lnb_lock);
-	return 0;
-}
-
-static int dd_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
-{
-
-	return 0;
-}
-
-static int dd_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct ddb_input *input = fe->sec_priv;
-	struct ddb_port *port = input->port;
-	struct ddb *dev = port->dev;
-	struct ddb_dvb *dvb = &port->dvb[input->nr & 1];
-	int s = 0;
-
-	mutex_lock(&dev->lnb_lock);
-	switch (voltage) {
-	case SEC_VOLTAGE_OFF:
-		lnb_command(dev, dvb->input, LNB_CMD_OFF);
-		break;
-	case SEC_VOLTAGE_13:
-		lnb_command(dev, dvb->input, LNB_CMD_LOW);
-		break;
-	case SEC_VOLTAGE_18:
-		lnb_command(dev, dvb->input, LNB_CMD_HIGH);
-		break;
-	default:
-		s = -EINVAL;
-		break;
-	};
-	mutex_unlock(&dev->lnb_lock);
-	return s;
-}
-
-static int dd_set_input(struct dvb_frontend *fe)
-{
-	
-	return 0;
-}
-
-static int fe_attach_mxl5xx(struct ddb_input *input)
-{
-	struct ddb *dev = input->port->dev;
-	struct i2c_adapter *i2c = &dev->i2c[0].adap;
-	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-	int demod, tuner;
-
-	demod = input->nr;
-	tuner = demod & 3;
-	dvb->fe = dvb_attach(mxl5xx_attach, i2c, &mxl5xx,
-			     demod, tuner);
-	if (!dvb->fe) {
-		pr_err("No MXL5XX found!\n");
-		return -ENODEV;
-	}
-	if (input->nr < 4) 
-		lnb_command(dev, input->nr, LNB_CMD_INIT);
-	dvb->fe->ops.set_voltage = dd_set_voltage;
-	dvb->fe->ops.enable_high_lnb_voltage = dd_enable_high_lnb_voltage;
-	dvb->fe->ops.set_tone = dd_set_tone;
-	dvb->fe->ops.diseqc_send_master_cmd = dd_send_master_cmd;
-	dvb->fe->sec_priv = input;
-	dvb->set_input = dvb->fe->ops.set_input;
-	dvb->fe->ops.set_input = dd_set_input;
-	dvb->input = tuner;
-	return 0;
-}
-
 static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
 				   int (*start_feed)(struct dvb_demux_feed *),
 				   int (*stop_feed)(struct dvb_demux_feed *),
@@ -1455,29 +1030,6 @@ static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
 	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
 }
 
-#if 0
-static int start_input(struct ddb_input *input)
-{
-	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-
-	if (!dvb->users)
-		ddb_input_start_all(input);
-
-	return ++dvb->users;
-}
-
-static int stop_input(struct ddb_input *input)
-{
-	struct ddb_dvb *dvb = &input->port->dvb[input->nr & 1];
-
-	if (--dvb->users)
-		return dvb->users;
-
-	ddb_input_stop_all(input);
-	return 0;
-}
-#endif
-
 static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
 {
 	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
@@ -1520,8 +1072,7 @@ static void dvb_input_detach(struct ddb_input *input)
 		dvb->fe = dvb->fe2 = NULL;
 		/* fallthrough */
 	case 0x21:
-		if (input->port->dev->ns_num)
-			dvb_netstream_release(&dvb->dvbns);
+		/* netstream release */
 		/* fallthrough */
 	case 0x20:
 		dvb_net_release(&dvb->dvbnet);
@@ -1673,16 +1224,14 @@ static int dvb_input_attach(struct ddb_input *input)
 	dvb->attached = 0x20;
 
 	if (input->port->dev->ns_num) {
-		ret = netstream_init(input);
-		if (ret < 0)
-			return ret;
+		/* netstream init */
 		dvb->attached = 0x21;
 	}
 	dvb->fe = dvb->fe2 = 0;
 	switch (port->type) {
 	case DDB_TUNER_MXL5XX:
-		fe_attach_mxl5xx(input);
-		break;
+		dev_notice(port->dev->dev, "MaxLinear MxL5xx not supported\n");
+		return -ENODEV;
 	case DDB_TUNER_DVBS_ST:
 		if (demod_attach_stv0900(input, 0) < 0)
 			return -ENODEV;
@@ -1691,37 +1240,29 @@ static int dvb_input_attach(struct ddb_input *input)
 		break;
 	case DDB_TUNER_DVBS_STV0910:
 	case DDB_TUNER_DVBS_STV0910_P:
-		if (demod_attach_stv0910(input, 0) < 0)
-			return -ENODEV;
-		if (tuner_attach_stv6111(input) < 0)
-			return -ENODEV;
-		break;
+		dev_notice(port->dev->dev, "STMicroelectronics STV0910 not supported\n");
+		return -ENODEV;
 	case DDB_TUNER_DVBS_ST_AA:
 		if (demod_attach_stv0900(input, 1) < 0)
 			return -ENODEV;
 		if (tuner_attach_stv6110(input, 1) < 0)
 			return -ENODEV;
 		break;
-#ifdef CONFIG_DVB_DRXK
 	case DDB_TUNER_DVBCT_TR:
 		if (demod_attach_drxk(input) < 0)
 			return -ENODEV;
 		if (tuner_attach_tda18271(input) < 0)
 			return -ENODEV;
 		break;
-#endif
 	case DDB_TUNER_DVBCT_ST:
-		if (demod_attach_stv0367dd(input) < 0)
-			return -ENODEV;
-		if (tuner_attach_tda18212dd(input) < 0)
-			return -ENODEV;
-		break;
+		dev_notice(port->dev->dev, "STMicroelectronics STV0367 not supported\n");
+		return -ENODEV;
 	case DDB_TUNER_DVBCT2_SONY:
 	case DDB_TUNER_DVBC2T2_SONY:
 	case DDB_TUNER_ISDBT_SONY:
 		if (demod_attach_cxd2843(input, 0) < 0)
 			return -ENODEV;
-		if (tuner_attach_tda18212dd(input) < 0)
+		if (tuner_attach_tda18212(input) < 0)
 			return -ENODEV;
 		break;
 	case DDB_TUNER_DVBCT2_SONY_P:
@@ -1729,7 +1270,7 @@ static int dvb_input_attach(struct ddb_input *input)
 	case DDB_TUNER_ISDBT_SONY_P:
 		if (demod_attach_cxd2843(input, 1) < 0)
 			return -ENODEV;
-		if (tuner_attach_tda18212dd(input) < 0)
+		if (tuner_attach_tda18212(input) < 0)
 			return -ENODEV;
 		break;
 	default:
@@ -1752,7 +1293,6 @@ static int dvb_input_attach(struct ddb_input *input)
 	return 0;
 }
 
-
 static int port_has_encti(struct ddb_port *port)
 {
 	u8 val;
@@ -1841,41 +1381,6 @@ static int port_has_stv0367(struct ddb_port *port)
 	return 1;
 }
 
-#if 0
-static int init_xo2_old(struct ddb_port *port)
-{
-	struct i2c_adapter *i2c = &port->i2c->adap;
-	u8 val;
-	int res;
-
-	res = i2c_read_reg(i2c, 0x10, 0x04, &val);
-	if (res < 0)
-		return res;
-
-	if (val != 0x02)  {
-		pr_info("Port %d: invalid XO2\n", port->nr);
-		return -1;
-	}
-	i2c_write_reg(i2c, 0x10, 0xc0, 0x00); /* Disable XO2 I2C master */
-
-	i2c_read_reg(i2c, 0x10, 0x08, &val);
-	if (val != 0) {
-		i2c_write_reg(i2c, 0x10, 0x08, 0x00);
-		msleep(100);
-	}
-	/* Enable tuner power, disable pll, reset demods */
-	i2c_write_reg(i2c, 0x10, 0x08, 0x04);
-	usleep_range(2000, 3000);
-	/* Release demod resets */
-	i2c_write_reg(i2c, 0x10, 0x08, 0x07);
-	usleep_range(2000, 3000);
-	/* Start XO2 PLL */
-	i2c_write_reg(i2c, 0x10, 0x08, 0x87);
-
-	return 0;
-}
-#endif
-
 static int init_xo2(struct ddb_port *port)
 {
 	struct i2c_adapter *i2c = &port->i2c->adap;
@@ -2235,16 +1740,14 @@ static int ddb_port_attach(struct ddb_port *port)
 		if (ret < 0)
 			break;
 	case DDB_PORT_LOOP:
+		/* XXX: we abuse SEC for CI */
 		ret = dvb_register_device(port->dvb[0].adap,
 					  &port->dvb[0].dev,
 					  &dvbdev_ci, (void *) port->output,
-					  DVB_DEVICE_CI);
+					  DVB_DEVICE_SEC);
 		break;
 	case DDB_PORT_MOD:
-		ret = dvb_register_device(port->dvb[0].adap,
-					  &port->dvb[0].dev,
-					  &dvbdev_mod, (void *) port->output,
-					  DVB_DEVICE_MOD);
+		dev_notice(port->dev->dev, "modulator not supported\n");
 		break;
 	default:
 		break;
@@ -2307,8 +1810,7 @@ static void ddb_ports_detach(struct ddb *dev)
 			}
 			break;
 		case DDB_PORT_MOD:
-			if (port->dvb[0].dev)
-				dvb_unregister_device(port->dvb[0].dev);
+			/* TODO: modulator not supported */
 			break;
 		}
 	}
@@ -2592,10 +2094,7 @@ static void ddb_ports_init(struct ddb *dev)
 			ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1);
 		}
 		if (dev->info->type == DDB_MOD) {
-			ddb_output_init(port, i, i);
-			dev->handler[i + 18] = ddbridge_mod_rate_handler;
-			dev->handler_data[i + 18] =
-				(unsigned long) &dev->output[i];
+			/* TODO: modulator not supported */
 		}
 	}
 }
@@ -2747,168 +2246,6 @@ static irqreturn_t irq_thread(int irq, void *dev_id)
 /****************************************************************************/
 /****************************************************************************/
 
-#ifdef DVB_NSD
-
-static ssize_t nsd_read(struct file *file, char *buf,
-			size_t count, loff_t *ppos)
-{
-	return 0;
-}
-
-static unsigned int nsd_poll(struct file *file, poll_table *wait)
-{
-	return 0;
-}
-
-static int nsd_release(struct inode *inode, struct file *file)
-{
-	return dvb_generic_release(inode, file);
-}
-
-static int nsd_open(struct inode *inode, struct file *file)
-{
-	return dvb_generic_open(inode, file);
-}
-
-static int nsd_do_ioctl(struct file *file, unsigned int cmd, void *parg)
-{
-	struct dvb_device *dvbdev = file->private_data;
-	struct ddb *dev = dvbdev->priv;
-
-	/* unsigned long arg = (unsigned long) parg; */
-	int ret = 0;
-
-	switch (cmd) {
-	case NSD_START_GET_TS:
-	{
-		struct dvb_nsd_ts *ts = parg;
-		u32 ctrl = ((ts->input & 7) << 8) |
-			((ts->filter_mask & 3) << 2);
-		u32 to;
-
-		if (ddbreadl(dev, TS_CAPTURE_CONTROL) & 1) {
-			pr_info("ts capture busy\n");
-			return -EBUSY;
-		}
-		ddb_dvb_input_start(&dev->input[ts->input & 7]);
-
-		ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL);
-		ddbwritel(dev, ts->pid, TS_CAPTURE_PID);
-		ddbwritel(dev, (ts->section_id << 16) |
-			  (ts->table << 8) | ts->section,
-			  TS_CAPTURE_TABLESECTION);
-		/* 1024 ms default timeout if timeout set to 0 */
-		if (ts->timeout)
-			to = ts->timeout;
-		else
-			to = 1024;
-		/* 21 packets default if num set to 0 */
-		if (ts->num)
-			to |= ((u32) ts->num << 16);
-		else
-			to |= (21 << 16);
-		ddbwritel(dev, to, TS_CAPTURE_TIMEOUT);
-		if (ts->mode)
-			ctrl |= 2;
-		ddbwritel(dev, ctrl | 1, TS_CAPTURE_CONTROL);
-		break;
-	}
-	case NSD_POLL_GET_TS:
-	{
-		struct dvb_nsd_ts *ts = parg;
-		u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL);
-
-		if (ctrl & 1)
-			return -EBUSY;
-		if (ctrl & (1 << 14)) {
-			/*pr_info("ts capture timeout\n");*/
-			return -EAGAIN;
-		}
-		ddbcpyfrom(dev, dev->tsbuf, TS_CAPTURE_MEMORY,
-			   TS_CAPTURE_LEN);
-		ts->len = ddbreadl(dev, TS_CAPTURE_RECEIVED) & 0x1fff;
-		if (copy_to_user(ts->ts, dev->tsbuf, ts->len))
-			return -EIO;
-		break;
-	}
-	case NSD_CANCEL_GET_TS:
-	{
-		u32 ctrl = 0;
-		pr_info("cancel ts capture: 0x%x\n", ctrl);
-		ddbwritel(dev, ctrl, TS_CAPTURE_CONTROL);
-		ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL);
-		/*pr_info("control register is 0x%x\n", ctrl);*/
-		break;
-	}
-	case NSD_STOP_GET_TS:
-	{
-		struct dvb_nsd_ts *ts = parg;
-		u32 ctrl = ddbreadl(dev, TS_CAPTURE_CONTROL);
-
-		if (ctrl & 1) {
-			pr_info("cannot stop ts capture, while it was neither finished not canceled\n");
-			return -EBUSY;
-		}
-		/*pr_info("ts capture stopped\n");*/
-		ddb_dvb_input_stop(&dev->input[ts->input & 7]);
-		break;
-	}
-	default:
-		ret = -EINVAL;
-		break;
-	}
-	return ret;
-}
-
-static long nsd_ioctl(struct file *file,
-		      unsigned int cmd, unsigned long arg)
-{
-	return dvb_usercopy(file, cmd, arg, nsd_do_ioctl);
-}
-
-static const struct file_operations nsd_fops = {
-	.owner   = THIS_MODULE,
-	.read    = nsd_read,
-	.open    = nsd_open,
-	.release = nsd_release,
-	.poll    = nsd_poll,
-	.unlocked_ioctl = nsd_ioctl,
-};
-
-static struct dvb_device dvbdev_nsd = {
-	.priv    = 0,
-	.readers = 1,
-	.writers = 1,
-	.users   = 1,
-	.fops    = &nsd_fops,
-};
-
-static int ddb_nsd_attach(struct ddb *dev)
-{
-	int ret;
-
-	ret = dvb_register_device(&dev->adap[0],
-				  &dev->nsd_dev,
-				  &dvbdev_nsd, (void *) dev,
-				  DVB_DEVICE_NSD);
-	return ret;
-}
-
-static void ddb_nsd_detach(struct ddb *dev)
-{
-	if (dev->nsd_dev->users > 2) {
-		wait_event(dev->nsd_dev->wait_queue,
-			   dev->nsd_dev->users == 2);
-	}
-	dvb_unregister_device(dev->nsd_dev);
-}
-
-#endif
-
-/****************************************************************************/
-/****************************************************************************/
-/****************************************************************************/
-
 static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
 {
 	u32 data, shift;
@@ -3231,11 +2568,7 @@ static const struct file_operations ddb_fops = {
 	.release        = ddb_release,
 };
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
-static char *ddb_devnode(struct device *device, mode_t *mode)
-#else
 static char *ddb_devnode(struct device *device, umode_t *mode)
-#endif
 {
 	struct ddb *dev = dev_get_drvdata(device);
 
@@ -3317,26 +2650,11 @@ static ssize_t temp_show(struct device *device,
 {
 	struct ddb *dev = dev_get_drvdata(device);
 	struct i2c_adapter *adap;
-	int temp, temp2, temp3, i;
+	int temp, temp2;
 	u8 tmp[2];
 
 	if (dev->info->type == DDB_MOD) {
-		ddbwritel(dev, 1, TEMPMON_CONTROL);
-		for (i = 0; i < 10; i++) {
-			if (0 == (1 & ddbreadl(dev, TEMPMON_CONTROL)))
-				break;
-			usleep_range(1000, 2000);
-		}
-		temp = ddbreadl(dev, TEMPMON_SENSOR1);
-		temp2 = ddbreadl(dev, TEMPMON_SENSOR2);
-		temp = (temp * 1000) >> 8;
-		temp2 = (temp2 * 1000) >> 8;
-		if (ddbreadl(dev, TEMPMON_CONTROL) & 0x8000) {
-			temp3 = ddbreadl(dev, TEMPMON_CORE);
-			temp3 = (temp3 * 1000) >> 8;
-			return sprintf(buf, "%d %d %d\n", temp, temp2, temp3);
-		}
-		return sprintf(buf, "%d %d\n", temp, temp2);
+		/* TODO: modulator not supported */
 	}
 	if (!dev->info->temp_num)
 		return sprintf(buf, "no sensor\n");
@@ -3355,25 +2673,6 @@ static ssize_t temp_show(struct device *device,
 	return sprintf(buf, "%d\n", temp);
 }
 
-#if 0
-static ssize_t qam_show(struct device *device,
-			struct device_attribute *attr, char *buf)
-{
-	struct ddb *dev = dev_get_drvdata(device);
-	struct i2c_adapter *adap;
-	u8 tmp[4];
-	s16 i, q;
-
-	adap = &dev->i2c[1].adap;
-	if (i2c_read_regs16(adap, 0x1f, 0xf480, tmp, 4) < 0)
-		return sprintf(buf, "read_error\n");
-	i = (s16) (((u16) tmp[1]) << 14) | (((u16) tmp[0]) << 6);
-	q = (s16) (((u16) tmp[3]) << 14) | (((u16) tmp[2]) << 6);
-
-	return sprintf(buf, "%d %d\n", i, q);
-}
-#endif
-
 static ssize_t mod_show(struct device *device,
 			struct device_attribute *attr, char *buf)
 {
diff --git a/drivers/media/pci/ddbridge/ddbridge-i2c.c b/drivers/media/pci/ddbridge/ddbridge-i2c.c
index bd0d9b1..6845d2a 100644
--- a/drivers/media/pci/ddbridge/ddbridge-i2c.c
+++ b/drivers/media/pci/ddbridge/ddbridge-i2c.c
@@ -161,24 +161,6 @@ static int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
 	return -EIO;
 }
 
-#if 0
-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 *dev = i2c->dev;
-	int ret;
-
-	if (dev->info->type != DDB_OCTONET || i2c->nr == 0 || i2c->nr == 3)
-		return ddb_i2c_master_xfer_locked(adapter, msg, num);
-
-	mutex_lock(&dev->octonet_i2c_lock);
-	ret = ddb_i2c_master_xfer_locked(adapter, msg, num);
-	mutex_unlock(&dev->octonet_i2c_lock);
-	return ret;
-}
-#endif
-
 static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_SMBUS_EMUL;
@@ -231,13 +213,6 @@ static int ddb_i2c_init(struct ddb *dev)
 
 		adap = &i2c->adap;
 		i2c_set_adapdata(adap, i2c);
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
-		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
-#else
-#ifdef I2C_CLASS_TV_ANALOG
-		adap->class = I2C_CLASS_TV_ANALOG;
-#endif
-#endif
 		strcpy(adap->name, "ddbridge");
 		adap->algo = &ddb_i2c_algo;
 		adap->algo_data = (void *)i2c;
diff --git a/drivers/media/pci/ddbridge/ddbridge.c b/drivers/media/pci/ddbridge/ddbridge.c
index 70c7ef0..fbd7e4f 100644
--- a/drivers/media/pci/ddbridge/ddbridge.c
+++ b/drivers/media/pci/ddbridge/ddbridge.c
@@ -58,7 +58,7 @@ static void ddb_unmap(struct ddb *dev)
 }
 
 
-static void __devexit ddb_remove(struct pci_dev *pdev)
+static void ddb_remove(struct pci_dev *pdev)
 {
 	struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
 
@@ -83,13 +83,7 @@ static void __devexit ddb_remove(struct pci_dev *pdev)
 	pci_disable_device(pdev);
 }
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-#define __devinit
-#define __devinitdata
-#endif
-
-static int __devinit ddb_probe(struct pci_dev *pdev,
-			       const struct pci_device_id *id)
+static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct ddb *dev;
 	int stat = 0;
@@ -146,6 +140,7 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
 
 #ifdef CONFIG_PCI_MSI
 	if (msi && pci_msi_enabled()) {
+#define pci_enable_msi_block pci_enable_msi_exact
 		stat = pci_enable_msi_block(dev->pdev, 2);
 		if (stat == 0) {
 			dev->msi = 1;
@@ -216,8 +211,6 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
 		ddbwritel(dev, 1, GPIO_DIRECTION);
 		ddbwritel(dev, 1, GPIO_OUTPUT);
 	}
-	if (dev->info->type == DDB_MOD)
-		ddbridge_mod_init(dev);
 
 	return 0;
 
@@ -373,12 +366,15 @@ static struct ddb_info ddb_dvbct = {
 	.i2c_num  = 3,
 };
 
+/*
+ * TODO: modulator not supported
 static struct ddb_info ddb_mod = {
 	.type     = DDB_MOD,
 	.name     = "Digital Devices DVB-C modulator",
 	.port_num = 10,
 	.temp_num = 1,
 };
+ */
 
 #define DDVID 0xdd01 /* Digital Devices Vendor ID */
 
@@ -387,7 +383,7 @@ static struct ddb_info ddb_mod = {
 	.subvendor   = _subvend, .subdevice = _subdev, \
 	.driver_data = (unsigned long)&_driverdata }
 
-static const struct pci_device_id ddb_id_tbl[] __devinitconst = {
+static const struct pci_device_id ddb_id_tbl[] = {
 	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
 	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
 	DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
@@ -405,7 +401,7 @@ static const struct pci_device_id ddb_id_tbl[] __devinitconst = {
 	DDB_ID(DDVID, 0x0007, DDVID, 0x0023, ddb_s2_48),
 	DDB_ID(DDVID, 0x0011, DDVID, 0x0040, ddb_ci),
 	DDB_ID(DDVID, 0x0011, DDVID, 0x0041, ddb_cis),
-	DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod),
+/*	DDB_ID(DDVID, 0x0201, DDVID, 0x0001, ddb_mod), */
 	/* in case sub-ids got deleted in flash */
 	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
 	DDB_ID(DDVID, 0x0011, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
index 1d028cf..601cf24 100644
--- a/drivers/media/pci/ddbridge/ddbridge.h
+++ b/drivers/media/pci/ddbridge/ddbridge.h
@@ -26,13 +26,6 @@
 #define _DDBRIDGE_H_
 
 #include <linux/version.h>
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-#define __devexit
-#define __devinit
-#define __devinitconst
-#endif
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -69,7 +62,6 @@
 #include <linux/device.h>
 #include <linux/io.h>
 
-#include "dvb_netstream.h"
 #include "dmxdev.h"
 #include "dvbdev.h"
 #include "dvb_demux.h"
@@ -83,16 +75,9 @@
 #include "stv090x.h"
 #include "lnbh24.h"
 #include "drxk.h"
-#include "stv0367.h"
-#include "stv0367dd.h"
 #include "tda18212.h"
-#include "tda18212dd.h"
 #include "cxd2843.h"
 #include "cxd2099.h"
-#include "stv0910.h"
-#include "stv6111.h"
-#include "lnbh25.h"
-#include "mxl5xx.h"
 
 #define DDB_MAX_I2C     4
 #define DDB_MAX_PORT   10
@@ -201,7 +186,6 @@ struct ddb_dvb {
 	struct dmxdev          dmxdev;
 	struct dvb_demux       demux;
 	struct dvb_net         dvbnet;
-	struct dvb_netstream   dvbns;
 	struct dmx_frontend    hw_frontend;
 	struct dmx_frontend    mem_frontend;
 	int                    users;
-- 
http://palosaari.fi/


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a
  2014-08-02  3:48 [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Antti Palosaari
                   ` (4 preceding siblings ...)
  2014-08-02  3:48 ` [PATCH 5/5] ddbridge: clean up driver for release Antti Palosaari
@ 2014-08-23 11:50 ` Bjoern
  2014-08-23 14:05   ` Antti Palosaari
  2014-09-23  8:42 ` Guy Martin
  6 siblings, 1 reply; 11+ messages in thread
From: Bjoern @ 2014-08-23 11:50 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

Hi all,

It's been 3 weeks since these patches were submitted - have they been
merged yet? If not - what's the problem? Who has to check this?

I'm not the only one longing for driver updated support of ddbridge "by
default", and it would really be nice if there was some "progress" here.
Antti did a lot of work here for all us ddbridge users.

Regards,
Bjoern

On Sa, 2014-08-02 at 06:48 +0300, Antti Palosaari wrote:
> After cold power-on, my device wasn't able to find DuoFlex C/C2/T/T2
> Expansion card, which I added yesterday. I looked old and new drivers
> and tried many things, but no success. Old kernel driver was ages,
> many years, behind manufacturer current Linux driver and there has
> been a tons of changes. So I ended up upgrading Linux kernel driver
> to 0.9.15a (it was 0.5).
> 
> Now it is very near Digital Devices official driver, only modulator
> and network streaming stuff is removed and CI is abusing SEC like
> earlier also.
> 
> Few device models are not supported due to missing kernel driver or
> missing device profile. Those devices are based of following DTV
> frontend chipsets:
> MaxLinear MxL5xx
> STMicroelectronics STV0910
> STMicroelectronics STV0367
> 
> 
> Tree for testing is here:
> http://git.linuxtv.org/cgit.cgi/anttip/media_tree.git/log/?h=digitaldevices
> 
> regards
> Antti
> 
> 
> Antti Palosaari (5):
>   cxd2843: do not call get_if_frequency() when it is NULL
>   ddbridge: disable driver building
>   ddbridge: remove driver temporarily
>   ddbridge: add needed files from manufacturer driver 0.9.15a
>   ddbridge: clean up driver for release
> 
>  drivers/media/dvb-frontends/cxd2843.c      |    3 +-
>  drivers/media/pci/ddbridge/Makefile        |    2 -
>  drivers/media/pci/ddbridge/ddbridge-core.c | 3175 +++++++++++++++++++---------
>  drivers/media/pci/ddbridge/ddbridge-i2c.c  |  232 ++
>  drivers/media/pci/ddbridge/ddbridge-regs.h |  347 ++-
>  drivers/media/pci/ddbridge/ddbridge.c      |  456 ++++
>  drivers/media/pci/ddbridge/ddbridge.h      |  407 +++-
>  7 files changed, 3518 insertions(+), 1104 deletions(-)
>  create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c
>  create mode 100644 drivers/media/pci/ddbridge/ddbridge.c
> 



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a
  2014-08-23 11:50 ` [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Bjoern
@ 2014-08-23 14:05   ` Antti Palosaari
  2014-08-23 21:10     ` Bjoern
  0 siblings, 1 reply; 11+ messages in thread
From: Antti Palosaari @ 2014-08-23 14:05 UTC (permalink / raw)
  To: Bjoern; +Cc: linux-media

Moikka
That patchset is simply far away from merge. Tons of issues to be fixed. 
It is huge amount of work to get that all in. I could estimate one month 
full time work even my experience is not enough. And I simply don't want 
to waste that much money from my pockets, it is many thousand euros. So 
I do it, if I do, on my schedule.

There is many separate issues which needs to be done. It is not 
something one people should do all. For example mainlining that 
DVB-T/T2/C/C2 demod driver. Another thing is DVB-C2 API, which is not 
much coding, but a lot of specification. You need to read and 
*understand* DVB-C2 spec and on some level other specs (mostly DVB-T2) 
in order to add missing pieces correctly to DVB API. If you are not 
coder, start here.


Antti



On 08/23/2014 02:50 PM, Bjoern wrote:
> Hi all,
>
> It's been 3 weeks since these patches were submitted - have they been
> merged yet? If not - what's the problem? Who has to check this?
>
> I'm not the only one longing for driver updated support of ddbridge "by
> default", and it would really be nice if there was some "progress" here.
> Antti did a lot of work here for all us ddbridge users.
>
> Regards,
> Bjoern
>
> On Sa, 2014-08-02 at 06:48 +0300, Antti Palosaari wrote:
>> After cold power-on, my device wasn't able to find DuoFlex C/C2/T/T2
>> Expansion card, which I added yesterday. I looked old and new drivers
>> and tried many things, but no success. Old kernel driver was ages,
>> many years, behind manufacturer current Linux driver and there has
>> been a tons of changes. So I ended up upgrading Linux kernel driver
>> to 0.9.15a (it was 0.5).
>>
>> Now it is very near Digital Devices official driver, only modulator
>> and network streaming stuff is removed and CI is abusing SEC like
>> earlier also.
>>
>> Few device models are not supported due to missing kernel driver or
>> missing device profile. Those devices are based of following DTV
>> frontend chipsets:
>> MaxLinear MxL5xx
>> STMicroelectronics STV0910
>> STMicroelectronics STV0367
>>
>>
>> Tree for testing is here:
>> http://git.linuxtv.org/cgit.cgi/anttip/media_tree.git/log/?h=digitaldevices
>>
>> regards
>> Antti
>>
>>
>> Antti Palosaari (5):
>>    cxd2843: do not call get_if_frequency() when it is NULL
>>    ddbridge: disable driver building
>>    ddbridge: remove driver temporarily
>>    ddbridge: add needed files from manufacturer driver 0.9.15a
>>    ddbridge: clean up driver for release
>>
>>   drivers/media/dvb-frontends/cxd2843.c      |    3 +-
>>   drivers/media/pci/ddbridge/Makefile        |    2 -
>>   drivers/media/pci/ddbridge/ddbridge-core.c | 3175 +++++++++++++++++++---------
>>   drivers/media/pci/ddbridge/ddbridge-i2c.c  |  232 ++
>>   drivers/media/pci/ddbridge/ddbridge-regs.h |  347 ++-
>>   drivers/media/pci/ddbridge/ddbridge.c      |  456 ++++
>>   drivers/media/pci/ddbridge/ddbridge.h      |  407 +++-
>>   7 files changed, 3518 insertions(+), 1104 deletions(-)
>>   create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c
>>   create mode 100644 drivers/media/pci/ddbridge/ddbridge.c
>>
>
>

-- 
http://palosaari.fi/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a
  2014-08-23 14:05   ` Antti Palosaari
@ 2014-08-23 21:10     ` Bjoern
  0 siblings, 0 replies; 11+ messages in thread
From: Bjoern @ 2014-08-23 21:10 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

Ok, got it. I just thought it was replacing the current driver with the
new one - and that seemed to be it. Didn't know there was such a lot of
work left before it's merged :o

Sorry and good luck!

-Bjoern


On Sa, 2014-08-23 at 17:05 +0300, Antti Palosaari wrote:
> Moikka
> That patchset is simply far away from merge. Tons of issues to be fixed. 
> It is huge amount of work to get that all in. I could estimate one month 
> full time work even my experience is not enough. And I simply don't want 
> to waste that much money from my pockets, it is many thousand euros. So 
> I do it, if I do, on my schedule.
> 
> There is many separate issues which needs to be done. It is not 
> something one people should do all. For example mainlining that 
> DVB-T/T2/C/C2 demod driver. Another thing is DVB-C2 API, which is not 
> much coding, but a lot of specification. You need to read and 
> *understand* DVB-C2 spec and on some level other specs (mostly DVB-T2) 
> in order to add missing pieces correctly to DVB API. If you are not 
> coder, start here.
> 
> 
> Antti
> 
> 
> 
> On 08/23/2014 02:50 PM, Bjoern wrote:
> > Hi all,
> >
> > It's been 3 weeks since these patches were submitted - have they been
> > merged yet? If not - what's the problem? Who has to check this?
> >
> > I'm not the only one longing for driver updated support of ddbridge "by
> > default", and it would really be nice if there was some "progress" here.
> > Antti did a lot of work here for all us ddbridge users.
> >
> > Regards,
> > Bjoern
> >
> > On Sa, 2014-08-02 at 06:48 +0300, Antti Palosaari wrote:
> >> After cold power-on, my device wasn't able to find DuoFlex C/C2/T/T2
> >> Expansion card, which I added yesterday. I looked old and new drivers
> >> and tried many things, but no success. Old kernel driver was ages,
> >> many years, behind manufacturer current Linux driver and there has
> >> been a tons of changes. So I ended up upgrading Linux kernel driver
> >> to 0.9.15a (it was 0.5).
> >>
> >> Now it is very near Digital Devices official driver, only modulator
> >> and network streaming stuff is removed and CI is abusing SEC like
> >> earlier also.
> >>
> >> Few device models are not supported due to missing kernel driver or
> >> missing device profile. Those devices are based of following DTV
> >> frontend chipsets:
> >> MaxLinear MxL5xx
> >> STMicroelectronics STV0910
> >> STMicroelectronics STV0367
> >>
> >>
> >> Tree for testing is here:
> >> http://git.linuxtv.org/cgit.cgi/anttip/media_tree.git/log/?h=digitaldevices
> >>
> >> regards
> >> Antti
> >>
> >>
> >> Antti Palosaari (5):
> >>    cxd2843: do not call get_if_frequency() when it is NULL
> >>    ddbridge: disable driver building
> >>    ddbridge: remove driver temporarily
> >>    ddbridge: add needed files from manufacturer driver 0.9.15a
> >>    ddbridge: clean up driver for release
> >>
> >>   drivers/media/dvb-frontends/cxd2843.c      |    3 +-
> >>   drivers/media/pci/ddbridge/Makefile        |    2 -
> >>   drivers/media/pci/ddbridge/ddbridge-core.c | 3175 +++++++++++++++++++---------
> >>   drivers/media/pci/ddbridge/ddbridge-i2c.c  |  232 ++
> >>   drivers/media/pci/ddbridge/ddbridge-regs.h |  347 ++-
> >>   drivers/media/pci/ddbridge/ddbridge.c      |  456 ++++
> >>   drivers/media/pci/ddbridge/ddbridge.h      |  407 +++-
> >>   7 files changed, 3518 insertions(+), 1104 deletions(-)
> >>   create mode 100644 drivers/media/pci/ddbridge/ddbridge-i2c.c
> >>   create mode 100644 drivers/media/pci/ddbridge/ddbridge.c
> >>
> >
> >
> 



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a
  2014-08-02  3:48 [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Antti Palosaari
                   ` (5 preceding siblings ...)
  2014-08-23 11:50 ` [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Bjoern
@ 2014-09-23  8:42 ` Guy Martin
  6 siblings, 0 replies; 11+ messages in thread
From: Guy Martin @ 2014-09-23  8:42 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media


On 2014-08-02 05:48, Antti Palosaari wrote:

> 
> Tree for testing is here:
> http://git.linuxtv.org/cgit.cgi/anttip/media_tree.git/log/?h=digitaldevices
> 


Hi Antti,

I tried your digitaldevices branch but it does not work for me.

Using w_scan, I'm not able to find any DVB-C transponder.
The very same command works fine with the official drivers.

There is no indication of what is wrong. Everything seems fine, I just 
don't get a lock.

See the relevant output below.

Regards,
   Guy

02:00.0 Multimedia controller: Digital Devices GmbH Device 0005
         Subsystem: Digital Devices GmbH Device 0004
         Flags: bus master, fast devsel, latency 0, IRQ 17
         Memory at d0500000 (64-bit, non-prefetchable) [size=64K]
         Capabilities: [50] Power Management version 3
         Capabilities: [70] MSI: Enable- Count=1/2 Maskable- 64bit+
         Capabilities: [90] Express Endpoint, MSI 00
         Capabilities: [100] Vendor Specific Information: ID=0000 Rev=0 
Len=00c <?>
         Kernel driver in use: ddbridge
         Kernel modules: ddbridge


[40396.241811] Digital Devices PCIE bridge driver 0.9.15, Copyright (C) 
2010-14 Digital Devices GmbH
[40396.242318] DDBridge driver detected: Digital Devices Octopus V3 DVB 
adapter
[40396.242358] HW 00010000 REGMAP 00010004
[40396.352992] Port 0 (TAB 1): DUAL DVB-C/T/T2
[40396.354460] Port 1 (TAB 2): NO MODULE
[40396.355691] Port 2 (TAB 3): NO MODULE
[40396.464656] Port 3 (TAB 4): DUAL DVB-C/T/T2
[40396.467376] 0 netstream channels
[40396.467388] DVB: registering new adapter (DDBridge)
[40396.467392] DVB: registering new adapter (DDBridge)
[40396.467396] DVB: registering new adapter (DDBridge)
[40396.467399] DVB: registering new adapter (DDBridge)
[40396.505488] tda18212 0-0060: NXP TDA18212HN/M successfully identified
[40396.505546] ddbridge 0000:02:00.0: DVB: registering adapter 0 
frontend 0 (CXD2837 DVB-C DVB-T/T2)...
[40396.552506] tda18212 0-0063: NXP TDA18212HN/S successfully identified
[40396.552545] ddbridge 0000:02:00.0: DVB: registering adapter 1 
frontend 0 (CXD2837 DVB-C DVB-T/T2)...
[40396.599404] tda18212 3-0060: NXP TDA18212HN/M successfully identified
[40396.599440] ddbridge 0000:02:00.0: DVB: registering adapter 2 
frontend 0 (CXD2837 DVB-C DVB-T/T2)...
[40396.647594] tda18212 3-0063: NXP TDA18212HN/S successfully identified
[40396.647632] ddbridge 0000:02:00.0: DVB: registering adapter 3 
frontend 0 (CXD2837 DVB-C DVB-T/T2)...




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/5] ddbridge: remove driver temporarily
  2014-08-02  3:48 ` [PATCH 3/5] ddbridge: remove driver temporarily Antti Palosaari
@ 2014-09-23 11:33   ` Mauro Carvalho Chehab
  0 siblings, 0 replies; 11+ messages in thread
From: Mauro Carvalho Chehab @ 2014-09-23 11:33 UTC (permalink / raw)
  To: Antti Palosaari; +Cc: linux-media

Em Sat,  2 Aug 2014 06:48:53 +0300
Antti Palosaari <crope@iki.fi> escreveu:

> Remove driver (version 0.5) as we will update driver to latest
> vendor version 0.9.15. Driver has changed too much for normal
> feature by feature update, so better to remove it totally and
> build new one based directly to latest vendor version.

Don't do that. This breaks bisectability for this driver.

Regards,
Mauro

> 
> Signed-off-by: Antti Palosaari <crope@iki.fi>
> ---
>  drivers/media/pci/ddbridge/ddbridge-core.c | 1887 ----------------------------
>  drivers/media/pci/ddbridge/ddbridge-regs.h |  151 ---
>  drivers/media/pci/ddbridge/ddbridge.h      |  188 ---
>  3 files changed, 2226 deletions(-)
>  delete mode 100644 drivers/media/pci/ddbridge/ddbridge-core.c
>  delete mode 100644 drivers/media/pci/ddbridge/ddbridge-regs.h
>  delete mode 100644 drivers/media/pci/ddbridge/ddbridge.h
> 
> diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
> deleted file mode 100644
> index 9f5837f..0000000
> --- a/drivers/media/pci/ddbridge/ddbridge-core.c
> +++ /dev/null
> @@ -1,1887 +0,0 @@
> -/*
> - * ddbridge.c: Digital Devices PCIe bridge driver
> - *
> - * Copyright (C) 2010-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/module.h>
> -#include <linux/init.h>
> -#include <linux/interrupt.h>
> -#include <linux/delay.h>
> -#include <linux/slab.h>
> -#include <linux/poll.h>
> -#include <linux/io.h>
> -#include <linux/pci.h>
> -#include <linux/pci_ids.h>
> -#include <linux/timer.h>
> -#include <linux/i2c.h>
> -#include <linux/swab.h>
> -#include <linux/vmalloc.h>
> -#include "ddbridge.h"
> -
> -#include "ddbridge-regs.h"
> -
> -#include "tda18271c2dd.h"
> -#include "stv6110x.h"
> -#include "stv090x.h"
> -#include "lnbh24.h"
> -#include "drxk.h"
> -#include "cxd2843.h"
> -#include "tda18212.h"
> -
> -DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
> -
> -/* MSI had problems with lost interrupts, fixed but needs testing */
> -#undef CONFIG_PCI_MSI
> -
> -/******************************************************************************/
> -
> -static int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
> -{
> -	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
> -				   .buf  = val,  .len   = 1 } };
> -	return (i2c_transfer(adapter, msgs, 1) == 1) ? 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 },
> -				  {.addr = adr,  .flags = I2C_M_RD,
> -				   .buf  = val,  .len   = 1 } };
> -	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
> -}
> -
> -static int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
> -			  u16 reg, u8 *val)
> -{
> -	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} };
> -	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
> -}
> -
> -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_write_reg(struct i2c_adapter *adap, u8 adr, u8 reg, u8 val)
> -{
> -	u8 msg[2] = {reg, val};
> -
> -	return i2c_write(adap, adr, msg, 2);
> -}
> -
> -static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
> -{
> -	struct ddb *dev = i2c->dev;
> -	int stat;
> -	u32 val;
> -
> -	i2c->done = 0;
> -	ddbwritel((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);
> -			printk(KERN_ERR "IRS %08x\n", istat);
> -			ddbwritel(istat, INTERRUPT_ACK);
> -		}
> -		return -EIO;
> -	}
> -	val = ddbreadl(i2c->regs+I2C_COMMAND);
> -	if (val & 0x70000)
> -		return -EIO;
> -	return 0;
> -}
> -
> -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 *dev = i2c->dev;
> -	u8 addr = 0;
> -
> -	if (num)
> -		addr = msg[0].addr;
> -
> -	if (num == 2 && msg[1].flags & I2C_M_RD &&
> -	    !(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);
> -		if (!ddb_i2c_cmd(i2c, addr, 1)) {
> -			memcpy_fromio(msg[1].buf,
> -				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
> -				      msg[1].len);
> -			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);
> -		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);
> -		if (!ddb_i2c_cmd(i2c, addr, 3)) {
> -			ddbcpyfrom(msg[0].buf,
> -				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
> -			return num;
> -		}
> -	}
> -	return -EIO;
> -}
> -
> -
> -static u32 ddb_i2c_functionality(struct i2c_adapter *adap)
> -{
> -	return I2C_FUNC_SMBUS_EMUL;
> -}
> -
> -struct i2c_algorithm ddb_i2c_algo = {
> -	.master_xfer   = ddb_i2c_master_xfer,
> -	.functionality = ddb_i2c_functionality,
> -};
> -
> -static void ddb_i2c_release(struct ddb *dev)
> -{
> -	int i;
> -	struct ddb_i2c *i2c;
> -	struct i2c_adapter *adap;
> -
> -	for (i = 0; i < dev->info->port_num; i++) {
> -		i2c = &dev->i2c[i];
> -		adap = &i2c->adap;
> -		i2c_del_adapter(adap);
> -	}
> -}
> -
> -static int ddb_i2c_init(struct ddb *dev)
> -{
> -	int i, j, stat = 0;
> -	struct ddb_i2c *i2c;
> -	struct i2c_adapter *adap;
> -
> -	for (i = 0; i < dev->info->port_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,
> -			  i2c->regs + I2C_TASKADDRESS);
> -		init_waitqueue_head(&i2c->wq);
> -
> -		adap = &i2c->adap;
> -		i2c_set_adapdata(adap, i2c);
> -#ifdef I2C_ADAP_CLASS_TV_DIGITAL
> -		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
> -#else
> -#ifdef I2C_CLASS_TV_ANALOG
> -		adap->class = I2C_CLASS_TV_ANALOG;
> -#endif
> -#endif
> -		strcpy(adap->name, "ddbridge");
> -		adap->algo = &ddb_i2c_algo;
> -		adap->algo_data = (void *)i2c;
> -		adap->dev.parent = &dev->pdev->dev;
> -		stat = i2c_add_adapter(adap);
> -		if (stat)
> -			break;
> -	}
> -	if (stat)
> -		for (j = 0; j < i; j++) {
> -			i2c = &dev->i2c[j];
> -			adap = &i2c->adap;
> -			i2c_del_adapter(adap);
> -		}
> -	return stat;
> -}
> -
> -
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> -
> -#if 0
> -static void set_table(struct ddb *dev, u32 off,
> -		      dma_addr_t *pbuf, u32 num)
> -{
> -	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);
> -	}
> -}
> -#endif
> -
> -static void ddb_address_table(struct ddb *dev)
> -{
> -	u32 i, j, base;
> -	u64 mem;
> -	dma_addr_t *pbuf;
> -
> -	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);
> -		}
> -	}
> -}
> -
> -static void io_free(struct pci_dev *pdev, u8 **vbuf,
> -		    dma_addr_t *pbuf, u32 size, int num)
> -{
> -	int i;
> -
> -	for (i = 0; i < num; i++) {
> -		if (vbuf[i]) {
> -			pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
> -			vbuf[i] = 0;
> -		}
> -	}
> -}
> -
> -static int io_alloc(struct pci_dev *pdev, u8 **vbuf,
> -		    dma_addr_t *pbuf, u32 size, int num)
> -{
> -	int i;
> -
> -	for (i = 0; i < num; i++) {
> -		vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
> -		if (!vbuf[i])
> -			return -ENOMEM;
> -	}
> -	return 0;
> -}
> -
> -static int ddb_buffers_alloc(struct ddb *dev)
> -{
> -	int i;
> -	struct ddb_port *port;
> -
> -	for (i = 0; i < dev->info->port_num; i++) {
> -		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)
> -				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)
> -				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)
> -				return -1;
> -			if (io_alloc(dev->pdev, port->output->vbuf,
> -				     port->output->pbuf,
> -				     port->output->dma_buf_size,
> -				     port->output->dma_buf_num) < 0)
> -				return -1;
> -			break;
> -		default:
> -			break;
> -		}
> -	}
> -	ddb_address_table(dev);
> -	return 0;
> -}
> -
> -static void ddb_buffers_free(struct ddb *dev)
> -{
> -	int i;
> -	struct ddb_port *port;
> -
> -	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);
> -	}
> -}
> -
> -static void ddb_input_start(struct ddb_input *input)
> -{
> -	struct ddb *dev = input->port->dev;
> -
> -	spin_lock_irq(&input->lock);
> -	input->cbuf = 0;
> -	input->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);
> -}
> -
> -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);
> -}
> -
> -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);
> -}
> -
> -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);
> -}
> -
> -static u32 ddb_output_free(struct ddb_output *output)
> -{
> -	u32 idx, off, stat = output->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))
> -			return 0;
> -		return 188;
> -	}
> -	diff = off - output->coff;
> -	if (diff <= 0 || diff > 188)
> -		return 188;
> -	return 0;
> -}
> -
> -static ssize_t ddb_output_write(struct ddb_output *output,
> -				const u8 *buf, size_t count)
> -{
> -	struct ddb *dev = output->port->dev;
> -	u32 idx, off, stat = output->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) &&
> -		    (off == 0)) {
> -			if (len <= 188)
> -				break;
> -			len -= 188;
> -		}
> -		if (output->cbuf == idx) {
> -			if (off > output->coff) {
> -#if 1
> -				len = off - output->coff;
> -				len -= (len % 188);
> -				if (len <= 188)
> -
> -#endif
> -					break;
> -				len -= 188;
> -			}
> -		}
> -		if (len > left)
> -			len = left;
> -		if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
> -				   buf, len))
> -			return -EIO;
> -		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);
> -		}
> -		ddbwritel((output->cbuf << 11) | (output->coff >> 7),
> -			  DMA_BUFFER_ACK(output->nr + 8));
> -	}
> -	return count - left;
> -}
> -
> -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));
> -
> -	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));
> -		return 0;
> -	}
> -	if (input->cbuf != idx)
> -		return 188;
> -	return 0;
> -}
> -
> -static ssize_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;
> -	int ret;
> -
> -	idx = (stat >> 11) & 0x1f;
> -
> -	while (left) {
> -		if (input->cbuf == idx)
> -			return count - left;
> -		free = input->dma_buf_size - input->coff;
> -		if (free > left)
> -			free = left;
> -		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
> -				   input->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;
> -		}
> -		left -= free;
> -		ddbwritel((input->cbuf << 11) | (input->coff >> 7),
> -			  DMA_BUFFER_ACK(input->nr));
> -	}
> -	return count;
> -}
> -
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> -
> -#if 0
> -static struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
> -{
> -	int i;
> -
> -	for (i = 0; i < dev->info->port_num * 2; i++) {
> -		if (dev->input[i].fe == fe)
> -			return &dev->input[i];
> -	}
> -	return NULL;
> -}
> -#endif
> -
> -static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
> -{
> -	struct ddb_input *input = fe->sec_priv;
> -	struct ddb_port *port = input->port;
> -	int status;
> -
> -	if (enable) {
> -		mutex_lock(&port->i2c_gate_lock);
> -		status = input->gate_ctrl(fe, 1);
> -	} else {
> -		status = input->gate_ctrl(fe, 0);
> -		mutex_unlock(&port->i2c_gate_lock);
> -	}
> -	return status;
> -}
> -
> -static int demod_attach_drxk(struct ddb_input *input)
> -{
> -	struct i2c_adapter *i2c = &input->port->i2c->adap;
> -	struct dvb_frontend *fe;
> -	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);
> -
> -	fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
> -	if (!input->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;
> -	return 0;
> -}
> -
> -static int demod_attach_cxd2843(struct ddb_input *input)
> -{
> -	struct i2c_adapter *i2c = &input->port->i2c->adap;
> -	struct dvb_frontend *fe;
> -	struct cxd2843_cfg cxd2843_0 = {
> -		.adr = 0x6c,
> -	};
> -	struct cxd2843_cfg cxd2843_1 = {
> -		.adr = 0x6d,
> -	};
> -
> -	fe = input->fe = dvb_attach(cxd2843_attach, i2c,
> -				  (input->nr & 1) ?
> -				  &cxd2843_1 : &cxd2843_0);
> -	if (!input->fe) {
> -		pr_err("No cxd2837/38/43 found!\n");
> -		return -ENODEV;
> -	}
> -	fe->sec_priv = input;
> -	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
> -	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
> -	return 0;
> -}
> -
> -static int tuner_attach_tda18271(struct ddb_input *input)
> -{
> -	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 (!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 struct tda18212_config tda18212_config_60 = {
> -	.i2c_address = 0x60,
> -	.if_dvbt_6 = 3550,
> -	.if_dvbt_7 = 3700,
> -	.if_dvbt_8 = 4150,
> -	.if_dvbt2_6 = 3250,
> -	.if_dvbt2_7 = 4000,
> -	.if_dvbt2_8 = 4000,
> -	.if_dvbc = 5000,
> -};
> -
> -static struct tda18212_config tda18212_config_63 = {
> -	.i2c_address = 0x63,
> -	.if_dvbt_6 = 3550,
> -	.if_dvbt_7 = 3700,
> -	.if_dvbt_8 = 4150,
> -	.if_dvbt2_6 = 3250,
> -	.if_dvbt2_7 = 4000,
> -	.if_dvbt2_8 = 4000,
> -	.if_dvbc = 5000,
> -};
> -
> -static int tuner_attach_tda18212(struct ddb_input *input)
> -{
> -	struct i2c_adapter *i2c = &input->port->i2c->adap;
> -	struct dvb_frontend *fe;
> -	struct tda18212_config *config;
> -
> -	if (input->nr & 1)
> -		config = &tda18212_config_63;
> -	else
> -		config = &tda18212_config_60;
> -
> -	fe = dvb_attach(tda18212_attach, input->fe, i2c, config);
> -	if (!fe) {
> -		pr_err("No TDA18212 found!\n");
> -		return -ENODEV;
> -	}
> -	return 0;
> -}
> -
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> -
> -static struct stv090x_config stv0900 = {
> -	.device         = STV0900,
> -	.demod_mode     = STV090x_DUAL,
> -	.clk_mode       = STV090x_CLK_EXT,
> -
> -	.xtal           = 27000000,
> -	.address        = 0x69,
> -
> -	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
> -	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
> -
> -	.repeater_level = STV090x_RPTLEVEL_16,
> -
> -	.adc1_range	= STV090x_ADC_1Vpp,
> -	.adc2_range	= STV090x_ADC_1Vpp,
> -
> -	.diseqc_envelope_mode = true,
> -};
> -
> -static struct stv090x_config stv0900_aa = {
> -	.device         = STV0900,
> -	.demod_mode     = STV090x_DUAL,
> -	.clk_mode       = STV090x_CLK_EXT,
> -
> -	.xtal           = 27000000,
> -	.address        = 0x68,
> -
> -	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
> -	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
> -
> -	.repeater_level = STV090x_RPTLEVEL_16,
> -
> -	.adc1_range	= STV090x_ADC_1Vpp,
> -	.adc2_range	= STV090x_ADC_1Vpp,
> -
> -	.diseqc_envelope_mode = true,
> -};
> -
> -static struct stv6110x_config stv6110a = {
> -	.addr    = 0x60,
> -	.refclk	 = 27000000,
> -	.clk_div = 1,
> -};
> -
> -static struct stv6110x_config stv6110b = {
> -	.addr    = 0x63,
> -	.refclk	 = 27000000,
> -	.clk_div = 1,
> -};
> -
> -static int demod_attach_stv0900(struct ddb_input *input, int type)
> -{
> -	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->nr & 1) ? STV090x_DEMODULATOR_1
> -			       : STV090x_DEMODULATOR_0);
> -	if (!input->fe) {
> -		printk(KERN_ERR "No STV0900 found!\n");
> -		return -ENODEV;
> -	}
> -	if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
> -			0, (input->nr & 1) ?
> -			(0x09 - type) : (0x0b - type))) {
> -		printk(KERN_ERR "No LNBH24 found!\n");
> -		return -ENODEV;
> -	}
> -	return 0;
> -}
> -
> -static int tuner_attach_stv6110(struct ddb_input *input, int type)
> -{
> -	struct i2c_adapter *i2c = &input->port->i2c->adap;
> -	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
> -	struct stv6110x_config *tunerconf = (input->nr & 1) ?
> -		&stv6110b : &stv6110a;
> -	struct stv6110x_devctl *ctl;
> -
> -	ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
> -	if (!ctl) {
> -		printk(KERN_ERR "No STV6110X found!\n");
> -		return -ENODEV;
> -	}
> -	printk(KERN_INFO "attach tuner input %d adr %02x\n",
> -			 input->nr, tunerconf->addr);
> -
> -	feconf->tuner_init          = ctl->tuner_init;
> -	feconf->tuner_sleep         = ctl->tuner_sleep;
> -	feconf->tuner_set_mode      = ctl->tuner_set_mode;
> -	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
> -	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
> -	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
> -	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
> -	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
> -	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
> -	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
> -	feconf->tuner_get_status    = ctl->tuner_get_status;
> -
> -	return 0;
> -}
> -
> -static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
> -			    int (*start_feed)(struct dvb_demux_feed *),
> -			    int (*stop_feed)(struct dvb_demux_feed *),
> -			    void *priv)
> -{
> -	dvbdemux->priv = priv;
> -
> -	dvbdemux->filternum = 256;
> -	dvbdemux->feednum = 256;
> -	dvbdemux->start_feed = start_feed;
> -	dvbdemux->stop_feed = stop_feed;
> -	dvbdemux->write_to_decoder = NULL;
> -	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
> -				      DMX_SECTION_FILTERING |
> -				      DMX_MEMORY_BASED_FILTERING);
> -	return dvb_dmx_init(dvbdemux);
> -}
> -
> -static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
> -			       struct dvb_demux *dvbdemux,
> -			       struct dmx_frontend *hw_frontend,
> -			       struct dmx_frontend *mem_frontend,
> -			       struct dvb_adapter *dvb_adapter)
> -{
> -	int ret;
> -
> -	dmxdev->filternum = 256;
> -	dmxdev->demux = &dvbdemux->dmx;
> -	dmxdev->capabilities = 0;
> -	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
> -	if (ret < 0)
> -		return ret;
> -
> -	hw_frontend->source = DMX_FRONTEND_0;
> -	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
> -	mem_frontend->source = DMX_MEMORY_FE;
> -	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
> -	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
> -}
> -
> -static int start_feed(struct dvb_demux_feed *dvbdmxfeed)
> -{
> -	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
> -	struct ddb_input *input = dvbdmx->priv;
> -
> -	if (!input->users)
> -		ddb_input_start(input);
> -
> -	return ++input->users;
> -}
> -
> -static int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
> -{
> -	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
> -	struct ddb_input *input = dvbdmx->priv;
> -
> -	if (--input->users)
> -		return input->users;
> -
> -	ddb_input_stop(input);
> -	return 0;
> -}
> -
> -
> -static void dvb_input_detach(struct ddb_input *input)
> -{
> -	struct dvb_adapter *adap = &input->adap;
> -	struct dvb_demux *dvbdemux = &input->demux;
> -
> -	switch (input->attached) {
> -	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;
> -		}
> -	case 4:
> -		dvb_net_release(&input->dvbnet);
> -
> -	case 3:
> -		dvbdemux->dmx.close(&dvbdemux->dmx);
> -		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
> -					      &input->hw_frontend);
> -		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
> -					      &input->mem_frontend);
> -		dvb_dmxdev_release(&input->dmxdev);
> -
> -	case 2:
> -		dvb_dmx_release(&input->demux);
> -
> -	case 1:
> -		dvb_unregister_adapter(adap);
> -	}
> -	input->attached = 0;
> -}
> -
> -static int dvb_input_attach(struct ddb_input *input)
> -{
> -	int ret;
> -	struct ddb_port *port = input->port;
> -	struct dvb_adapter *adap = &input->adap;
> -	struct dvb_demux *dvbdemux = &input->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;
> -
> -	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
> -				      start_feed,
> -				      stop_feed, input);
> -	if (ret < 0)
> -		return ret;
> -	input->attached = 2;
> -
> -	ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
> -					 &input->hw_frontend,
> -					 &input->mem_frontend, adap);
> -	if (ret < 0)
> -		return ret;
> -	input->attached = 3;
> -
> -	ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
> -	if (ret < 0)
> -		return ret;
> -	input->attached = 4;
> -
> -	input->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 (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_DVBCT2_SONY:
> -	case DDB_TUNER_DVBC2T2_SONY:
> -	case DDB_TUNER_ISDBT_SONY:
> -		if (demod_attach_cxd2843(input) < 0)
> -			return -ENODEV;
> -		if (tuner_attach_tda18212(input) < 0)
> -			return -ENODEV;
> -		if (input->fe) {
> -			if (dvb_register_frontend(adap, input->fe) < 0)
> -				return -ENODEV;
> -		}
> -		break;
> -	}
> -	input->attached = 5;
> -	return 0;
> -}
> -
> -/****************************************************************************/
> -/****************************************************************************/
> -
> -static ssize_t ts_write(struct file *file, const char *buf,
> -			size_t count, loff_t *ppos)
> -{
> -	struct dvb_device *dvbdev = file->private_data;
> -	struct ddb_output *output = dvbdev->priv;
> -	size_t left = count;
> -	int stat;
> -
> -	while (left) {
> -		if (ddb_output_free(output) < 188) {
> -			if (file->f_flags & O_NONBLOCK)
> -				break;
> -			if (wait_event_interruptible(
> -				    output->wq, ddb_output_free(output) >= 188) < 0)
> -				break;
> -		}
> -		stat = ddb_output_write(output, buf, left);
> -		if (stat < 0)
> -			break;
> -		buf += stat;
> -		left -= stat;
> -	}
> -	return (left == count) ? -EAGAIN : (count - left);
> -}
> -
> -static ssize_t ts_read(struct file *file, char *buf,
> -		       size_t count, loff_t *ppos)
> -{
> -	struct dvb_device *dvbdev = file->private_data;
> -	struct ddb_output *output = dvbdev->priv;
> -	struct ddb_input *input = output->port->input[0];
> -	int left, read;
> -
> -	count -= count % 188;
> -	left = count;
> -	while (left) {
> -		if (ddb_input_avail(input) < 188) {
> -			if (file->f_flags & O_NONBLOCK)
> -				break;
> -			if (wait_event_interruptible(
> -				    input->wq, ddb_input_avail(input) >= 188) < 0)
> -				break;
> -		}
> -		read = ddb_input_read(input, buf, left);
> -		if (read < 0)
> -			return read;
> -		left -= read;
> -		buf += read;
> -	}
> -	return (left == count) ? -EAGAIN : (count - left);
> -}
> -
> -static unsigned int ts_poll(struct file *file, poll_table *wait)
> -{
> -	/*
> -	struct dvb_device *dvbdev = file->private_data;
> -	struct ddb_output *output = dvbdev->priv;
> -	struct ddb_input *input = output->port->input[0];
> -	*/
> -	unsigned int mask = 0;
> -
> -#if 0
> -	if (data_avail_to_read)
> -		mask |= POLLIN | POLLRDNORM;
> -	if (data_avail_to_write)
> -		mask |= POLLOUT | POLLWRNORM;
> -
> -	poll_wait(file, &read_queue, wait);
> -	poll_wait(file, &write_queue, wait);
> -#endif
> -	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 = {
> -	.priv    = 0,
> -	.readers = -1,
> -	.writers = -1,
> -	.users   = -1,
> -	.fops    = &ci_fops,
> -};
> -
> -/****************************************************************************/
> -/****************************************************************************/
> -/****************************************************************************/
> -
> -static void input_tasklet(unsigned long data)
> -{
> -	struct ddb_input *input = (struct ddb_input *) data;
> -	struct ddb *dev = input->port->dev;
> -
> -	spin_lock(&input->lock);
> -	if (!input->running) {
> -		spin_unlock(&input->lock);
> -		return;
> -	}
> -	input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->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);
> -}
> -
> -static void output_tasklet(unsigned long data)
> -{
> -	struct ddb_output *output = (struct ddb_output *) data;
> -	struct ddb *dev = output->port->dev;
> -
> -	spin_lock(&output->lock);
> -	if (!output->running) {
> -		spin_unlock(&output->lock);
> -		return;
> -	}
> -	output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
> -	wake_up(&output->wq);
> -	spin_unlock(&output->lock);
> -}
> -
> -
> -struct cxd2099_cfg cxd_cfg = {
> -	.bitrate =  62000,
> -	.adr     =  0x40,
> -	.polarity = 1,
> -	.clock_mode = 1,
> -};
> -
> -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;
> -	}
> -	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;
> -}
> -
> -static int ddb_port_attach(struct ddb_port *port)
> -{
> -	int ret = 0;
> -
> -	switch (port->class) {
> -	case DDB_PORT_TUNER:
> -		ret = dvb_input_attach(port->input[0]);
> -		if (ret < 0)
> -			break;
> -		ret = dvb_input_attach(port->input[1]);
> -		break;
> -	case DDB_PORT_CI:
> -		ret = ddb_ci_attach(port);
> -		break;
> -	default:
> -		break;
> -	}
> -	if (ret < 0)
> -		printk(KERN_ERR "port_attach on port %d failed\n", port->nr);
> -	return ret;
> -}
> -
> -static int ddb_ports_attach(struct ddb *dev)
> -{
> -	int i, ret = 0;
> -	struct ddb_port *port;
> -
> -	for (i = 0; i < dev->info->port_num; i++) {
> -		port = &dev->port[i];
> -		ret = ddb_port_attach(port);
> -		if (ret < 0)
> -			break;
> -	}
> -	return ret;
> -}
> -
> -static void ddb_ports_detach(struct ddb *dev)
> -{
> -	int i;
> -	struct ddb_port *port;
> -
> -	for (i = 0; i < dev->info->port_num; i++) {
> -		port = &dev->port[i];
> -		switch (port->class) {
> -		case DDB_PORT_TUNER:
> -			dvb_input_detach(port->input[0]);
> -			dvb_input_detach(port->input[1]);
> -			break;
> -		case DDB_PORT_CI:
> -			if (port->output->dev)
> -				dvb_unregister_device(port->output->dev);
> -			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;
> -		}
> -	}
> -}
> -
> -/****************************************************************************/
> -/****************************************************************************/
> -
> -static int port_has_ci(struct ddb_port *port)
> -{
> -	u8 val;
> -	return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
> -}
> -
> -static int port_has_stv0900(struct ddb_port *port)
> -{
> -	u8 val;
> -	if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
> -		return 0;
> -	return 1;
> -}
> -
> -static int port_has_stv0900_aa(struct ddb_port *port)
> -{
> -	u8 val;
> -	if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
> -		return 0;
> -	return 1;
> -}
> -
> -static int port_has_drxks(struct ddb_port *port)
> -{
> -	u8 val;
> -	if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
> -		return 0;
> -	if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
> -		return 0;
> -	return 1;
> -}
> -
> -static int port_has_cxd28xx(struct ddb_port *port, u8 *id)
> -{
> -	int status;
> -
> -	status = i2c_write_reg(&port->i2c->adap, 0x6e, 0, 0);
> -	if (status)
> -		return 0;
> -	status = i2c_read_reg(&port->i2c->adap, 0x6e, 0xfd, id);
> -	if (status)
> -		return 0;
> -	return 1;
> -}
> -
> -static void ddb_port_probe(struct ddb_port *port)
> -{
> -	struct ddb *dev = port->dev;
> -	char *modname = "NO MODULE";
> -	u8 id;
> -
> -	port->class = DDB_PORT_NONE;
> -
> -	if (port_has_ci(port)) {
> -		modname = "CI";
> -		port->class = DDB_PORT_CI;
> -		ddbwritel(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);
> -	} 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);
> -	} 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);
> -	} else if (port_has_cxd28xx(port, &id)) {
> -		switch (id) {
> -		case 0xa4:
> -			modname = "DUAL DVB-C2T2 CXD2843";
> -			port->type = DDB_TUNER_DVBC2T2_SONY;
> -			break;
> -		case 0xb1:
> -			modname = "DUAL DVB-CT2 CXD2837";
> -			port->type = DDB_TUNER_DVBCT2_SONY;
> -			break;
> -		case 0xb0:
> -			modname = "DUAL ISDB-T CXD2838";
> -			port->type = DDB_TUNER_ISDBT_SONY;
> -			break;
> -		default:
> -			return;
> -		}
> -		port->class = DDB_PORT_TUNER;
> -		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
> -	}
> -	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)
> -{
> -	struct ddb *dev = port->dev;
> -	struct ddb_input *input = &dev->input[nr];
> -
> -	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);
> -}
> -
> -static void ddb_output_init(struct ddb_port *port, int nr)
> -{
> -	struct ddb *dev = port->dev;
> -	struct ddb_output *output = &dev->output[nr];
> -	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);
> -}
> -
> -static void ddb_ports_init(struct ddb *dev)
> -{
> -	int i;
> -	struct ddb_port *port;
> -
> -	for (i = 0; i < dev->info->port_num; i++) {
> -		port = &dev->port[i];
> -		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);
> -		ddb_output_init(port, i);
> -	}
> -}
> -
> -static void ddb_ports_release(struct ddb *dev)
> -{
> -	int i;
> -	struct ddb_port *port;
> -
> -	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);
> -	}
> -}
> -
> -/****************************************************************************/
> -/****************************************************************************/
> -/****************************************************************************/
> -
> -static void irq_handle_i2c(struct ddb *dev, int n)
> -{
> -	struct ddb_i2c *i2c = &dev->i2c[n];
> -
> -	i2c->done = 1;
> -	wake_up(&i2c->wq);
> -}
> -
> -static irqreturn_t irq_handler(int irq, void *dev_id)
> -{
> -	struct ddb *dev = (struct ddb *) dev_id;
> -	u32 s = ddbreadl(INTERRUPT_STATUS);
> -
> -	if (!s)
> -		return IRQ_NONE;
> -
> -	do {
> -		ddbwritel(s, INTERRUPT_ACK);
> -
> -		if (s & 0x00000001)
> -			irq_handle_i2c(dev, 0);
> -		if (s & 0x00000002)
> -			irq_handle_i2c(dev, 1);
> -		if (s & 0x00000004)
> -			irq_handle_i2c(dev, 2);
> -		if (s & 0x00000008)
> -			irq_handle_i2c(dev, 3);
> -
> -		if (s & 0x00000100)
> -			tasklet_schedule(&dev->input[0].tasklet);
> -		if (s & 0x00000200)
> -			tasklet_schedule(&dev->input[1].tasklet);
> -		if (s & 0x00000400)
> -			tasklet_schedule(&dev->input[2].tasklet);
> -		if (s & 0x00000800)
> -			tasklet_schedule(&dev->input[3].tasklet);
> -		if (s & 0x00001000)
> -			tasklet_schedule(&dev->input[4].tasklet);
> -		if (s & 0x00002000)
> -			tasklet_schedule(&dev->input[5].tasklet);
> -		if (s & 0x00004000)
> -			tasklet_schedule(&dev->input[6].tasklet);
> -		if (s & 0x00008000)
> -			tasklet_schedule(&dev->input[7].tasklet);
> -
> -		if (s & 0x00010000)
> -			tasklet_schedule(&dev->output[0].tasklet);
> -		if (s & 0x00020000)
> -			tasklet_schedule(&dev->output[1].tasklet);
> -		if (s & 0x00040000)
> -			tasklet_schedule(&dev->output[2].tasklet);
> -		if (s & 0x00080000)
> -			tasklet_schedule(&dev->output[3].tasklet);
> -
> -		/* if (s & 0x000f0000)	printk(KERN_DEBUG "%08x\n", istat); */
> -	} while ((s = ddbreadl(INTERRUPT_STATUS)));
> -
> -	return IRQ_HANDLED;
> -}
> -
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> -
> -static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
> -{
> -	u32 data, shift;
> -
> -	if (wlen > 4)
> -		ddbwritel(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)
> -			;
> -	}
> -
> -	if (rlen)
> -		ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
> -	else
> -		ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
> -
> -	data = 0;
> -	shift = ((4 - wlen) * 8);
> -	while (wlen) {
> -		data <<= 8;
> -		data |= *wbuf;
> -		wlen--;
> -		wbuf++;
> -	}
> -	if (shift)
> -		data <<= shift;
> -	ddbwritel(data, SPI_DATA);
> -	while (ddbreadl(SPI_CONTROL) & 0x0004)
> -		;
> -
> -	if (!rlen) {
> -		ddbwritel(0, SPI_CONTROL);
> -		return 0;
> -	}
> -	if (rlen > 4)
> -		ddbwritel(1, SPI_CONTROL);
> -
> -	while (rlen > 4) {
> -		ddbwritel(0xffffffff, SPI_DATA);
> -		while (ddbreadl(SPI_CONTROL) & 0x0004)
> -			;
> -		data = ddbreadl(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)
> -		;
> -
> -	data = ddbreadl(SPI_DATA);
> -	ddbwritel(0, SPI_CONTROL);
> -
> -	if (rlen < 4)
> -		data <<= ((4 - rlen) * 8);
> -
> -	while (rlen > 0) {
> -		*rbuf = ((data >> 24) & 0xff);
> -		data <<= 8;
> -		rbuf++;
> -		rlen--;
> -	}
> -	return 0;
> -}
> -
> -#define DDB_MAGIC 'd'
> -
> -struct ddb_flashio {
> -	__u8 *write_buf;
> -	__u32 write_len;
> -	__u8 *read_buf;
> -	__u32 read_len;
> -};
> -
> -#define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
> -
> -#define DDB_NAME "ddbridge"
> -
> -static u32 ddb_num;
> -static struct ddb *ddbs[32];
> -static struct class *ddb_class;
> -static int ddb_major;
> -
> -static int ddb_open(struct inode *inode, struct file *file)
> -{
> -	struct ddb *dev = ddbs[iminor(inode)];
> -
> -	file->private_data = dev;
> -	return 0;
> -}
> -
> -static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> -{
> -	struct ddb *dev = file->private_data;
> -	void *parg = (void *)arg;
> -	int res;
> -
> -	switch (cmd) {
> -	case IOCTL_DDB_FLASHIO:
> -	{
> -		struct ddb_flashio fio;
> -		u8 *rbuf, *wbuf;
> -
> -		if (copy_from_user(&fio, parg, sizeof(fio)))
> -			return -EFAULT;
> -
> -		if (fio.write_len > 1028 || fio.read_len > 1028)
> -			return -EINVAL;
> -		if (fio.write_len + fio.read_len > 1028)
> -			return -EINVAL;
> -
> -		wbuf = &dev->iobuf[0];
> -		rbuf = wbuf + fio.write_len;
> -
> -		if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
> -			return -EFAULT;
> -		res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
> -		if (res)
> -			return res;
> -		if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
> -			return -EFAULT;
> -		break;
> -	}
> -	default:
> -		return -ENOTTY;
> -	}
> -	return 0;
> -}
> -
> -static const struct file_operations ddb_fops = {
> -	.unlocked_ioctl = ddb_ioctl,
> -	.open           = ddb_open,
> -};
> -
> -static char *ddb_devnode(struct device *device, umode_t *mode)
> -{
> -	struct ddb *dev = dev_get_drvdata(device);
> -
> -	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
> -}
> -
> -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);
> -		return PTR_ERR(ddb_class);
> -	}
> -	ddb_class->devnode = ddb_devnode;
> -	return 0;
> -}
> -
> -static void ddb_class_destroy(void)
> -{
> -	class_destroy(ddb_class);
> -	unregister_chrdev(ddb_major, DDB_NAME);
> -}
> -
> -static int ddb_device_create(struct ddb *dev)
> -{
> -	dev->nr = ddb_num++;
> -	dev->ddb_dev = device_create(ddb_class, NULL,
> -				     MKDEV(ddb_major, dev->nr),
> -				     dev, "ddbridge%d", dev->nr);
> -	ddbs[dev->nr] = dev;
> -	if (IS_ERR(dev->ddb_dev))
> -		return -1;
> -	return 0;
> -}
> -
> -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));
> -}
> -
> -
> -/****************************************************************************/
> -/****************************************************************************/
> -/****************************************************************************/
> -
> -static void ddb_unmap(struct ddb *dev)
> -{
> -	if (dev->regs)
> -		iounmap(dev->regs);
> -	vfree(dev);
> -}
> -
> -
> -static void ddb_remove(struct pci_dev *pdev)
> -{
> -	struct ddb *dev = pci_get_drvdata(pdev);
> -
> -	ddb_ports_detach(dev);
> -	ddb_i2c_release(dev);
> -
> -	ddbwritel(0, INTERRUPT_ENABLE);
> -	free_irq(dev->pdev->irq, dev);
> -#ifdef CONFIG_PCI_MSI
> -	if (dev->msi)
> -		pci_disable_msi(dev->pdev);
> -#endif
> -	ddb_ports_release(dev);
> -	ddb_buffers_free(dev);
> -	ddb_device_destroy(dev);
> -
> -	ddb_unmap(dev);
> -	pci_set_drvdata(pdev, 0);
> -	pci_disable_device(pdev);
> -}
> -
> -
> -static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> -{
> -	struct ddb *dev;
> -	int stat = 0;
> -	int irq_flag = IRQF_SHARED;
> -
> -	if (pci_enable_device(pdev) < 0)
> -		return -ENODEV;
> -
> -	dev = vmalloc(sizeof(struct ddb));
> -	if (dev == NULL)
> -		return -ENOMEM;
> -	memset(dev, 0, sizeof(struct ddb));
> -
> -	dev->pdev = pdev;
> -	pci_set_drvdata(pdev, dev);
> -	dev->info = (struct ddb_info *) id->driver_data;
> -	printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name);
> -
> -	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
> -			    pci_resource_len(dev->pdev, 0));
> -	if (!dev->regs) {
> -		stat = -ENOMEM;
> -		goto fail;
> -	}
> -	printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
> -
> -#ifdef CONFIG_PCI_MSI
> -	if (pci_msi_enabled())
> -		stat = pci_enable_msi(dev->pdev);
> -	if (stat) {
> -		printk(KERN_INFO ": MSI not available.\n");
> -	} else {
> -		irq_flag = 0;
> -		dev->msi = 1;
> -	}
> -#endif
> -	stat = request_irq(dev->pdev->irq, irq_handler,
> -			   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);
> -
> -	if (ddb_i2c_init(dev) < 0)
> -		goto fail1;
> -	ddb_ports_init(dev);
> -	if (ddb_buffers_alloc(dev) < 0) {
> -		printk(KERN_INFO ": Could not allocate buffer memory\n");
> -		goto fail2;
> -	}
> -	if (ddb_ports_attach(dev) < 0)
> -		goto fail3;
> -	ddb_device_create(dev);
> -	return 0;
> -
> -fail3:
> -	ddb_ports_detach(dev);
> -	printk(KERN_ERR "fail3\n");
> -	ddb_ports_release(dev);
> -fail2:
> -	printk(KERN_ERR "fail2\n");
> -	ddb_buffers_free(dev);
> -fail1:
> -	printk(KERN_ERR "fail1\n");
> -	if (dev->msi)
> -		pci_disable_msi(dev->pdev);
> -	free_irq(dev->pdev->irq, dev);
> -fail:
> -	printk(KERN_ERR "fail\n");
> -	ddb_unmap(dev);
> -	pci_set_drvdata(pdev, 0);
> -	pci_disable_device(pdev);
> -	return -1;
> -}
> -
> -/******************************************************************************/
> -/******************************************************************************/
> -/******************************************************************************/
> -
> -static struct ddb_info ddb_none = {
> -	.type     = DDB_NONE,
> -	.name     = "Digital Devices PCIe bridge",
> -};
> -
> -static struct ddb_info ddb_octopus = {
> -	.type     = DDB_OCTOPUS,
> -	.name     = "Digital Devices Octopus DVB adapter",
> -	.port_num = 4,
> -};
> -
> -static struct ddb_info ddb_octopus_le = {
> -	.type     = DDB_OCTOPUS,
> -	.name     = "Digital Devices Octopus LE DVB adapter",
> -	.port_num = 2,
> -};
> -
> -static struct ddb_info ddb_octopus_mini = {
> -	.type     = DDB_OCTOPUS,
> -	.name     = "Digital Devices Octopus Mini",
> -	.port_num = 4,
> -};
> -
> -static struct ddb_info ddb_v6 = {
> -	.type     = DDB_OCTOPUS,
> -	.name     = "Digital Devices Cine S2 V6 DVB adapter",
> -	.port_num = 3,
> -};
> -static struct ddb_info ddb_v6_5 = {
> -	.type     = DDB_OCTOPUS,
> -	.name     = "Digital Devices Cine S2 V6.5 DVB adapter",
> -	.port_num = 4,
> -};
> -
> -static struct ddb_info ddb_dvbct = {
> -	.type     = DDB_OCTOPUS,
> -	.name     = "Digital Devices DVBCT V6.1 DVB adapter",
> -	.port_num = 3,
> -};
> -
> -static struct ddb_info ddb_satixS2v3 = {
> -	.type     = DDB_OCTOPUS,
> -	.name     = "Mystique SaTiX-S2 V3 DVB adapter",
> -	.port_num = 3,
> -};
> -
> -static struct ddb_info ddb_octopusv3 = {
> -	.type     = DDB_OCTOPUS,
> -	.name     = "Digital Devices Octopus V3 DVB adapter",
> -	.port_num = 4,
> -};
> -
> -#define DDVID 0xdd01 /* Digital Devices Vendor ID */
> -
> -#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {	\
> -	.vendor      = _vend,    .device    = _dev, \
> -	.subvendor   = _subvend, .subdevice = _subdev, \
> -	.driver_data = (unsigned long)&_driverdata }
> -
> -static const struct pci_device_id ddb_id_tbl[] = {
> -	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_mini),
> -	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
> -	DDB_ID(DDVID, 0x0003, DDVID, 0x0021, ddb_v6_5),
> -	DDB_ID(DDVID, 0x0003, DDVID, 0x0030, ddb_dvbct),
> -	DDB_ID(DDVID, 0x0003, DDVID, 0xdb03, ddb_satixS2v3),
> -	DDB_ID(DDVID, 0x0005, DDVID, 0x0004, ddb_octopusv3),
> -	/* in case sub-ids got deleted in flash */
> -	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
> -	{0}
> -};
> -MODULE_DEVICE_TABLE(pci, ddb_id_tbl);
> -
> -
> -static struct pci_driver ddb_pci_driver = {
> -	.name        = "DDBridge",
> -	.id_table    = ddb_id_tbl,
> -	.probe       = ddb_probe,
> -	.remove      = ddb_remove,
> -};
> -
> -static __init int module_init_ddbridge(void)
> -{
> -	int ret;
> -
> -	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
> -	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
> -
> -	ret = ddb_class_create();
> -	if (ret < 0)
> -		return ret;
> -	ret = pci_register_driver(&ddb_pci_driver);
> -	if (ret < 0)
> -		ddb_class_destroy();
> -	return ret;
> -}
> -
> -static __exit void module_exit_ddbridge(void)
> -{
> -	pci_unregister_driver(&ddb_pci_driver);
> -	ddb_class_destroy();
> -}
> -
> -module_init(module_init_ddbridge);
> -module_exit(module_exit_ddbridge);
> -
> -MODULE_DESCRIPTION("Digital Devices PCIe Bridge");
> -MODULE_AUTHOR("Ralph Metzler");
> -MODULE_LICENSE("GPL");
> -MODULE_VERSION("0.5");
> diff --git a/drivers/media/pci/ddbridge/ddbridge-regs.h b/drivers/media/pci/ddbridge/ddbridge-regs.h
> deleted file mode 100644
> index a3ccb31..0000000
> --- a/drivers/media/pci/ddbridge/ddbridge-regs.h
> +++ /dev/null
> @@ -1,151 +0,0 @@
> -/*
> - * ddbridge-regs.h: Digital Devices PCIe bridge driver
> - *
> - * Copyright (C) 2010-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
> - */
> -
> -/* DD-DVBBridgeV1.h 273 2010-09-17 05:03:16Z manfred */
> -
> -/* Register Definitions */
> -
> -#define CUR_REGISTERMAP_VERSION 0x10000
> -
> -#define HARDWARE_VERSION       0x00
> -#define REGISTERMAP_VERSION    0x04
> -
> -/* ------------------------------------------------------------------------- */
> -/* SPI Controller */
> -
> -#define SPI_CONTROL     0x10
> -#define SPI_DATA        0x14
> -
> -/* ------------------------------------------------------------------------- */
> -
> -/* Interrupt controller                                     */
> -/* How many MSI's are available depends on HW (Min 2 max 8) */
> -/* How many are usable also depends on Host platform        */
> -
> -#define INTERRUPT_BASE   (0x40)
> -
> -#define INTERRUPT_ENABLE (INTERRUPT_BASE + 0x00)
> -#define MSI0_ENABLE      (INTERRUPT_BASE + 0x00)
> -#define MSI1_ENABLE      (INTERRUPT_BASE + 0x04)
> -#define MSI2_ENABLE      (INTERRUPT_BASE + 0x08)
> -#define MSI3_ENABLE      (INTERRUPT_BASE + 0x0C)
> -#define MSI4_ENABLE      (INTERRUPT_BASE + 0x10)
> -#define MSI5_ENABLE      (INTERRUPT_BASE + 0x14)
> -#define MSI6_ENABLE      (INTERRUPT_BASE + 0x18)
> -#define MSI7_ENABLE      (INTERRUPT_BASE + 0x1C)
> -
> -#define INTERRUPT_STATUS (INTERRUPT_BASE + 0x20)
> -#define INTERRUPT_ACK    (INTERRUPT_BASE + 0x20)
> -
> -#define INTMASK_I2C1        (0x00000001)
> -#define INTMASK_I2C2        (0x00000002)
> -#define INTMASK_I2C3        (0x00000004)
> -#define INTMASK_I2C4        (0x00000008)
> -
> -#define INTMASK_CIRQ1       (0x00000010)
> -#define INTMASK_CIRQ2       (0x00000020)
> -#define INTMASK_CIRQ3       (0x00000040)
> -#define INTMASK_CIRQ4       (0x00000080)
> -
> -#define INTMASK_TSINPUT1    (0x00000100)
> -#define INTMASK_TSINPUT2    (0x00000200)
> -#define INTMASK_TSINPUT3    (0x00000400)
> -#define INTMASK_TSINPUT4    (0x00000800)
> -#define INTMASK_TSINPUT5    (0x00001000)
> -#define INTMASK_TSINPUT6    (0x00002000)
> -#define INTMASK_TSINPUT7    (0x00004000)
> -#define INTMASK_TSINPUT8    (0x00008000)
> -
> -#define INTMASK_TSOUTPUT1   (0x00010000)
> -#define INTMASK_TSOUTPUT2   (0x00020000)
> -#define INTMASK_TSOUTPUT3   (0x00040000)
> -#define INTMASK_TSOUTPUT4   (0x00080000)
> -
> -/* ------------------------------------------------------------------------- */
> -/* I2C Master Controller */
> -
> -#define I2C_BASE        (0x80)  /* Byte offset */
> -
> -#define I2C_COMMAND     (0x00)
> -#define I2C_TIMING      (0x04)
> -#define I2C_TASKLENGTH  (0x08)     /* High read, low write */
> -#define I2C_TASKADDRESS (0x0C)     /* High read, low write */
> -
> -#define I2C_MONITOR     (0x1C)
> -
> -#define I2C_BASE_1      (I2C_BASE + 0x00)
> -#define I2C_BASE_2      (I2C_BASE + 0x20)
> -#define I2C_BASE_3      (I2C_BASE + 0x40)
> -#define I2C_BASE_4      (I2C_BASE + 0x60)
> -
> -#define I2C_BASE_N(i)   (I2C_BASE + (i) * 0x20)
> -
> -#define I2C_TASKMEM_BASE    (0x1000)    /* Byte offset */
> -#define I2C_TASKMEM_SIZE    (0x1000)
> -
> -#define I2C_SPEED_400   (0x04030404)
> -#define I2C_SPEED_200   (0x09080909)
> -#define I2C_SPEED_154   (0x0C0B0C0C)
> -#define I2C_SPEED_100   (0x13121313)
> -#define I2C_SPEED_77    (0x19181919)
> -#define I2C_SPEED_50    (0x27262727)
> -
> -
> -/* ------------------------------------------------------------------------- */
> -/* DMA  Controller */
> -
> -#define DMA_BASE_WRITE        (0x100)
> -#define DMA_BASE_READ         (0x140)
> -
> -#define DMA_CONTROL     (0x00)                  /* 64 */
> -#define DMA_ERROR       (0x04)                  /* 65 ( only read instance ) */
> -
> -#define DMA_DIAG_CONTROL                (0x1C)  /* 71 */
> -#define DMA_DIAG_PACKETCOUNTER_LOW      (0x20)  /* 72 */
> -#define DMA_DIAG_PACKETCOUNTER_HIGH     (0x24)  /* 73 */
> -#define DMA_DIAG_TIMECOUNTER_LOW        (0x28)  /* 74 */
> -#define DMA_DIAG_TIMECOUNTER_HIGH       (0x2C)  /* 75 */
> -#define DMA_DIAG_RECHECKCOUNTER         (0x30)  /* 76  ( Split completions on read ) */
> -#define DMA_DIAG_WAITTIMEOUTINIT        (0x34)  /* 77 */
> -#define DMA_DIAG_WAITOVERFLOWCOUNTER    (0x38)  /* 78 */
> -#define DMA_DIAG_WAITCOUNTER            (0x3C)  /* 79 */
> -
> -/* ------------------------------------------------------------------------- */
> -/* DMA  Buffer */
> -
> -#define TS_INPUT_BASE       (0x200)
> -#define TS_INPUT_CONTROL(i)         (TS_INPUT_BASE + (i) * 16 + 0x00)
> -
> -#define TS_OUTPUT_BASE       (0x280)
> -#define TS_OUTPUT_CONTROL(i)         (TS_OUTPUT_BASE + (i) * 16 + 0x00)
> -
> -#define DMA_BUFFER_BASE     (0x300)
> -
> -#define DMA_BUFFER_CONTROL(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x00)
> -#define DMA_BUFFER_ACK(i)           (DMA_BUFFER_BASE + (i) * 16 + 0x04)
> -#define DMA_BUFFER_CURRENT(i)       (DMA_BUFFER_BASE + (i) * 16 + 0x08)
> -#define DMA_BUFFER_SIZE(i)          (DMA_BUFFER_BASE + (i) * 16 + 0x0c)
> -
> -#define DMA_BASE_ADDRESS_TABLE  (0x2000)
> -#define DMA_BASE_ADDRESS_TABLE_ENTRIES (512)
> -
> diff --git a/drivers/media/pci/ddbridge/ddbridge.h b/drivers/media/pci/ddbridge/ddbridge.h
> deleted file mode 100644
> index 04c56c2..0000000
> --- a/drivers/media/pci/ddbridge/ddbridge.h
> +++ /dev/null
> @@ -1,188 +0,0 @@
> -/*
> - * ddbridge.h: Digital Devices PCIe bridge driver
> - *
> - * Copyright (C) 2010-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
> - */
> -
> -#ifndef _DDBRIDGE_H_
> -#define _DDBRIDGE_H_
> -
> -#include <linux/types.h>
> -#include <linux/sched.h>
> -#include <linux/interrupt.h>
> -#include <linux/i2c.h>
> -#include <linux/mutex.h>
> -#include <asm/dma.h>
> -#include <linux/dvb/frontend.h>
> -#include <linux/dvb/ca.h>
> -#include <linux/socket.h>
> -
> -#include "dmxdev.h"
> -#include "dvbdev.h"
> -#include "dvb_demux.h"
> -#include "dvb_frontend.h"
> -#include "dvb_ringbuffer.h"
> -#include "dvb_ca_en50221.h"
> -#include "dvb_net.h"
> -#include "cxd2099.h"
> -
> -#define DDB_MAX_I2C     4
> -#define DDB_MAX_PORT    4
> -#define DDB_MAX_INPUT   8
> -#define DDB_MAX_OUTPUT  4
> -
> -struct ddb_info {
> -	int   type;
> -#define DDB_NONE         0
> -#define DDB_OCTOPUS      1
> -	char *name;
> -	int   port_num;
> -	u32   port_type[DDB_MAX_PORT];
> -};
> -
> -/* DMA_SIZE MUST be divisible by 188 and 128 !!! */
> -
> -#define INPUT_DMA_MAX_BUFS 32      /* hardware table limit */
> -#define INPUT_DMA_BUFS 8
> -#define INPUT_DMA_SIZE (128*47*21)
> -
> -#define OUTPUT_DMA_MAX_BUFS 32
> -#define OUTPUT_DMA_BUFS 8
> -#define OUTPUT_DMA_SIZE (128*47*21)
> -
> -struct ddb;
> -struct ddb_port;
> -
> -struct ddb_input {
> -	struct ddb_port       *port;
> -	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;
> -
> -	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 dvb_frontend   *fe;
> -	struct dvb_frontend   *fe2;
> -	struct dmxdev          dmxdev;
> -	struct dvb_demux       demux;
> -	struct dvb_net         dvbnet;
> -	struct dmx_frontend    hw_frontend;
> -	struct dmx_frontend    mem_frontend;
> -	int                    users;
> -	int (*gate_ctrl)(struct dvb_frontend *, int);
> -};
> -
> -struct ddb_output {
> -	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_i2c {
> -	struct ddb            *dev;
> -	u32                    nr;
> -	struct i2c_adapter     adap;
> -	struct i2c_adapter     adap2;
> -	u32                    regs;
> -	u32                    rbuf;
> -	u32                    wbuf;
> -	int                    done;
> -	wait_queue_head_t      wq;
> -};
> -
> -struct ddb_port {
> -	struct ddb            *dev;
> -	u32                    nr;
> -	struct ddb_i2c        *i2c;
> -	struct mutex           i2c_gate_lock;
> -	u32                    class;
> -#define DDB_PORT_NONE           0
> -#define DDB_PORT_CI             1
> -#define DDB_PORT_TUNER          2
> -	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_DVBCT2_SONY  18
> -#define DDB_TUNER_ISDBT_SONY   19
> -#define DDB_TUNER_DVBC2T2_SONY 20
> -	u32                    adr;
> -
> -	struct ddb_input      *input[2];
> -	struct ddb_output     *output;
> -	struct dvb_ca_en50221 *en;
> -};
> -
> -struct ddb {
> -	struct pci_dev        *pdev;
> -	unsigned char         *regs;
> -	struct ddb_port        port[DDB_MAX_PORT];
> -	struct ddb_i2c         i2c[DDB_MAX_I2C];
> -	struct ddb_input       input[DDB_MAX_INPUT];
> -	struct ddb_output      output[DDB_MAX_OUTPUT];
> -
> -	struct device         *ddb_dev;
> -	int                    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))
> -
> -/****************************************************************************/
> -
> -#endif

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-09-23 11:33 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-02  3:48 [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Antti Palosaari
2014-08-02  3:48 ` [PATCH 1/5] cxd2843: do not call get_if_frequency() when it is NULL Antti Palosaari
2014-08-02  3:48 ` [PATCH 2/5] ddbridge: disable driver building Antti Palosaari
2014-08-02  3:48 ` [PATCH 3/5] ddbridge: remove driver temporarily Antti Palosaari
2014-09-23 11:33   ` Mauro Carvalho Chehab
2014-08-02  3:48 ` [PATCH 4/5] ddbridge: add needed files from manufacturer driver 0.9.15a Antti Palosaari
2014-08-02  3:48 ` [PATCH 5/5] ddbridge: clean up driver for release Antti Palosaari
2014-08-23 11:50 ` [PATCH 0/5] Digital Devices PCIe bridge update to 0.9.15a Bjoern
2014-08-23 14:05   ` Antti Palosaari
2014-08-23 21:10     ` Bjoern
2014-09-23  8:42 ` Guy Martin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.