1ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/*
2ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * ddbridge.c: Digital Devices PCIe bridge driver
3ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler *
4ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * Copyright (C) 2010-2011 Digital Devices GmbH
5ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler *
6ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * This program is free software; you can redistribute it and/or
7ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * modify it under the terms of the GNU General Public License
8ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * version 2 only, as published by the Free Software Foundation.
9ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler *
10ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler *
11ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * This program is distributed in the hope that it will be useful,
12ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * but WITHOUT ANY WARRANTY; without even the implied warranty of
13ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * GNU General Public License for more details.
15ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler *
16ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler *
17ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * You should have received a copy of the GNU General Public License
18ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * along with this program; if not, write to the Free Software
19ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * 02110-1301, USA
21ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
22ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler */
23ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
24ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/module.h>
25ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/init.h>
26ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/interrupt.h>
27ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/delay.h>
28ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/slab.h>
29ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/poll.h>
3028d45a5d294e3f2beddd355b41fa50a66df726ccMauro Carvalho Chehab#include <linux/io.h>
31ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/pci.h>
32ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/pci_ids.h>
33ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/timer.h>
34ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/version.h>
35ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/i2c.h>
36ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/swab.h>
37ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include <linux/vmalloc.h>
38ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include "ddbridge.h"
39ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
40ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include "ddbridge-regs.h"
41ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
42ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include "tda18271c2dd.h"
43ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include "stv6110x.h"
44ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include "stv090x.h"
45ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include "lnbh24.h"
46ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#include "drxk.h"
47ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
48ccad04578fcbe2678084af0986ac010ab84a023dRalph MetzlerDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
49ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
50ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/* MSI had problems with lost interrupts, fixed but needs testing */
51ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#undef CONFIG_PCI_MSI
52ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
53ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
54ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
55ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int i2c_read(struct i2c_adapter *adapter, u8 adr, u8 *val)
56ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
57ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_msg msgs[1] = {{.addr = adr,  .flags = I2C_M_RD,
584f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss				   .buf  = val,  .len   = 1 } };
59ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return (i2c_transfer(adapter, msgs, 1) == 1) ? 0 : -1;
60ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
61ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
62ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, u8 reg, u8 *val)
63ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
64ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_msg msgs[2] = {{.addr = adr,  .flags = 0,
65ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   .buf  = &reg, .len   = 1 },
66ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				  {.addr = adr,  .flags = I2C_M_RD,
674f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss				   .buf  = val,  .len   = 1 } };
68ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
69ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
70ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
71ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int i2c_read_reg16(struct i2c_adapter *adapter, u8 adr,
72ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			  u16 reg, u8 *val)
73ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
74ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u8 msg[2] = {reg>>8, reg&0xff};
75ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
76ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   .buf  = msg, .len   = 2},
77ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				  {.addr = adr, .flags = I2C_M_RD,
784f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss				   .buf  = val, .len   = 1} };
79ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return (i2c_transfer(adapter, msgs, 2) == 2) ? 0 : -1;
80ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
81ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
82ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
83ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
84ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = i2c->dev;
85ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int stat;
86ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 val;
87ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
88ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	i2c->done = 0;
89ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND);
90ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ);
91ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (stat <= 0) {
924f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "I2C timeout\n");
93ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		{ /* MSI debugging*/
94ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			u32 istat = ddbreadl(INTERRUPT_STATUS);
954f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			printk(KERN_ERR "IRS %08x\n", istat);
96ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			ddbwritel(istat, INTERRUPT_ACK);
97ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
98ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -EIO;
99ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1004f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	val = ddbreadl(i2c->regs+I2C_COMMAND);
101ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (val & 0x70000)
102ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -EIO;
103ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
104ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
105ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
106ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_i2c_master_xfer(struct i2c_adapter *adapter,
107ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			       struct i2c_msg msg[], int num)
108ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
109ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_i2c *i2c = (struct ddb_i2c *)i2c_get_adapdata(adapter);
110ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = i2c->dev;
1114f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	u8 addr = 0;
112ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
113ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (num)
114ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		addr = msg[0].addr;
115ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
116ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (num == 2 && msg[1].flags & I2C_M_RD &&
117ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	    !(msg[0].flags & I2C_M_RD)) {
118ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		memcpy_toio(dev->regs + I2C_TASKMEM_BASE + i2c->wbuf,
1194f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			    msg[0].buf, msg[0].len);
120ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(msg[0].len|(msg[1].len << 16),
121ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			  i2c->regs+I2C_TASKLENGTH);
122ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (!ddb_i2c_cmd(i2c, addr, 1)) {
123ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			memcpy_fromio(msg[1].buf,
124ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				      dev->regs + I2C_TASKMEM_BASE + i2c->rbuf,
125ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				      msg[1].len);
126ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return num;
127ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
128ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
129ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
130ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
1314f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		ddbcpyto(I2C_TASKMEM_BASE + i2c->wbuf, msg[0].buf, msg[0].len);
132ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(msg[0].len, i2c->regs + I2C_TASKLENGTH);
133ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (!ddb_i2c_cmd(i2c, addr, 2))
134ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return num;
135ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
136ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (num == 1 && (msg[0].flags & I2C_M_RD)) {
137ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(msg[0].len << 16, i2c->regs + I2C_TASKLENGTH);
138ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (!ddb_i2c_cmd(i2c, addr, 3)) {
139ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			ddbcpyfrom(msg[0].buf,
140ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   I2C_TASKMEM_BASE + i2c->rbuf, msg[0].len);
141ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return num;
142ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
143ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
144ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return -EIO;
145ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
146ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
147ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
148ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic u32 ddb_i2c_functionality(struct i2c_adapter *adap)
149ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
150ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return I2C_FUNC_SMBUS_EMUL;
151ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
152ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
153ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstruct i2c_algorithm ddb_i2c_algo = {
154ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.master_xfer   = ddb_i2c_master_xfer,
155ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.functionality = ddb_i2c_functionality,
156ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
157ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
158ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_i2c_release(struct ddb *dev)
159ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
160ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
161ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_i2c *i2c;
162ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_adapter *adap;
163ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
164ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
165ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c = &dev->i2c[i];
166ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		adap = &i2c->adap;
167ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c_del_adapter(adap);
168ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
169ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
170ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
171ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_i2c_init(struct ddb *dev)
172ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
173ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i, j, stat = 0;
174ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_i2c *i2c;
175ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_adapter *adap;
176ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
177ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
178ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c = &dev->i2c[i];
179ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c->dev = dev;
180ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c->nr = i;
181ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c->wbuf = i * (I2C_TASKMEM_SIZE / 4);
182ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c->rbuf = i2c->wbuf + (I2C_TASKMEM_SIZE / 8);
183ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c->regs = 0x80 + i * 0x20;
184ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(I2C_SPEED_100, i2c->regs + I2C_TIMING);
185ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel((i2c->rbuf << 16) | i2c->wbuf,
186ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			  i2c->regs + I2C_TASKADDRESS);
187ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		init_waitqueue_head(&i2c->wq);
188ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
189ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		adap = &i2c->adap;
190ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		i2c_set_adapdata(adap, i2c);
191ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#ifdef I2C_ADAP_CLASS_TV_DIGITAL
192ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		adap->class = I2C_ADAP_CLASS_TV_DIGITAL|I2C_CLASS_TV_ANALOG;
193ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#else
194ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#ifdef I2C_CLASS_TV_ANALOG
195ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		adap->class = I2C_CLASS_TV_ANALOG;
196ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#endif
197ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#endif
198ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		strcpy(adap->name, "ddbridge");
199ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		adap->algo = &ddb_i2c_algo;
200ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		adap->algo_data = (void *)i2c;
201ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		adap->dev.parent = &dev->pdev->dev;
202ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		stat = i2c_add_adapter(adap);
203ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (stat)
204ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
205ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
206ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (stat)
207ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		for (j = 0; j < i; j++) {
208ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			i2c = &dev->i2c[j];
209ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			adap = &i2c->adap;
210ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			i2c_del_adapter(adap);
211ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
212ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return stat;
213ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
214ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
215ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
216ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
217ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
218ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
219ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
2204f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss#if 0
221ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void set_table(struct ddb *dev, u32 off,
222ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		      dma_addr_t *pbuf, u32 num)
223ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
224ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 i, base;
225ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u64 mem;
226ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
227ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	base = DMA_BASE_ADDRESS_TABLE + off;
228ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < num; i++) {
229ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		mem = pbuf[i];
230ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(mem & 0xffffffff, base + i * 8);
231ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(mem >> 32, base + i * 8 + 4);
232ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
233ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
2344f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss#endif
235ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
236ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_address_table(struct ddb *dev)
237ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
238ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 i, j, base;
239ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u64 mem;
240ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dma_addr_t *pbuf;
241ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
242ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num * 2; i++) {
243ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		base = DMA_BASE_ADDRESS_TABLE + i * 0x100;
244ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		pbuf = dev->input[i].pbuf;
245ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		for (j = 0; j < dev->input[i].dma_buf_num; j++) {
246ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			mem = pbuf[j];
247ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			ddbwritel(mem & 0xffffffff, base + j * 8);
248ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			ddbwritel(mem >> 32, base + j * 8 + 4);
249ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
250ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
251ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
252ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		base = DMA_BASE_ADDRESS_TABLE + 0x800 + i * 0x100;
253ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		pbuf = dev->output[i].pbuf;
254ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		for (j = 0; j < dev->output[i].dma_buf_num; j++) {
255ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			mem = pbuf[j];
256ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			ddbwritel(mem & 0xffffffff, base + j * 8);
257ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			ddbwritel(mem >> 32, base + j * 8 + 4);
258ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
259ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
260ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
261ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
262ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void io_free(struct pci_dev *pdev, u8 **vbuf,
263ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		    dma_addr_t *pbuf, u32 size, int num)
264ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
265ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
266ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
267ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < num; i++) {
268ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (vbuf[i]) {
269ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			pci_free_consistent(pdev, size, vbuf[i], pbuf[i]);
270ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			vbuf[i] = 0;
271ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
272ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
273ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
274ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
275ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int io_alloc(struct pci_dev *pdev, u8 **vbuf,
276ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		    dma_addr_t *pbuf, u32 size, int num)
277ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
278ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
279ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
280ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < num; i++) {
281ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		vbuf[i] = pci_alloc_consistent(pdev, size, &pbuf[i]);
282ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (!vbuf[i])
283ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return -ENOMEM;
284ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
285ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
286ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
287ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
288ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_buffers_alloc(struct ddb *dev)
289ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
290ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
291ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_port *port;
292ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
293ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
294ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port = &dev->port[i];
295ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		switch (port->class) {
296ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		case DDB_PORT_TUNER:
297ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (io_alloc(dev->pdev, port->input[0]->vbuf,
298ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[0]->pbuf,
299ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[0]->dma_buf_size,
300ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[0]->dma_buf_num) < 0)
301ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				return -1;
302ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (io_alloc(dev->pdev, port->input[1]->vbuf,
303ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[1]->pbuf,
304ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[1]->dma_buf_size,
305ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[1]->dma_buf_num) < 0)
306ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				return -1;
307ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
308ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		case DDB_PORT_CI:
309ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (io_alloc(dev->pdev, port->input[0]->vbuf,
310ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[0]->pbuf,
311ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[0]->dma_buf_size,
312ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->input[0]->dma_buf_num) < 0)
313ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				return -1;
314ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (io_alloc(dev->pdev, port->output->vbuf,
315ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->output->pbuf,
316ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->output->dma_buf_size,
317ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     port->output->dma_buf_num) < 0)
318ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				return -1;
319ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
320ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		default:
321ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
322ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
323ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
324ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_address_table(dev);
325ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
326ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
327ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
328ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_buffers_free(struct ddb *dev)
329ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
330ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
331ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_port *port;
332ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
333ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
334ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port = &dev->port[i];
335ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		io_free(dev->pdev, port->input[0]->vbuf,
336ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->input[0]->pbuf,
337ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->input[0]->dma_buf_size,
338ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->input[0]->dma_buf_num);
339ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		io_free(dev->pdev, port->input[1]->vbuf,
340ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->input[1]->pbuf,
341ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->input[1]->dma_buf_size,
342ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->input[1]->dma_buf_num);
343ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		io_free(dev->pdev, port->output->vbuf,
344ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->output->pbuf,
345ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->output->dma_buf_size,
346ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			port->output->dma_buf_num);
347ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
348ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
349ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
350ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_input_start(struct ddb_input *input)
351ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
352ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = input->port->dev;
353ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
354ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_lock_irq(&input->lock);
355ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->cbuf = 0;
356ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->coff = 0;
357ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
358ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	/* reset */
359ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
360ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(2, TS_INPUT_CONTROL(input->nr));
361ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
362ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
363ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel((1 << 16) |
364ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		  (input->dma_buf_num << 11) |
365ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		  (input->dma_buf_size >> 7),
366ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		  DMA_BUFFER_SIZE(input->nr));
367ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, DMA_BUFFER_ACK(input->nr));
368ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
369ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(1, DMA_BASE_WRITE);
370ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(3, DMA_BUFFER_CONTROL(input->nr));
371ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(9, TS_INPUT_CONTROL(input->nr));
372ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->running = 1;
373ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_unlock_irq(&input->lock);
374ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
375ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
376ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_input_stop(struct ddb_input *input)
377ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
378ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = input->port->dev;
379ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
380ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_lock_irq(&input->lock);
381ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_INPUT_CONTROL(input->nr));
382ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, DMA_BUFFER_CONTROL(input->nr));
383ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->running = 0;
384ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_unlock_irq(&input->lock);
385ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
386ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
387ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_output_start(struct ddb_output *output)
388ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
389ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = output->port->dev;
390ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
391ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_lock_irq(&output->lock);
392ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->cbuf = 0;
393ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->coff = 0;
394ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
395ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(2, TS_OUTPUT_CONTROL(output->nr));
396ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
397ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0x3c, TS_OUTPUT_CONTROL(output->nr));
398ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel((1 << 16) |
399ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		  (output->dma_buf_num << 11) |
400ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		  (output->dma_buf_size >> 7),
401ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		  DMA_BUFFER_SIZE(output->nr + 8));
402ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, DMA_BUFFER_ACK(output->nr + 8));
403ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
404ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(1, DMA_BASE_READ);
405ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(3, DMA_BUFFER_CONTROL(output->nr + 8));
4064f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	/* ddbwritel(0xbd, TS_OUTPUT_CONTROL(output->nr)); */
407ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0x1d, TS_OUTPUT_CONTROL(output->nr));
408ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->running = 1;
409ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_unlock_irq(&output->lock);
410ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
411ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
412ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_output_stop(struct ddb_output *output)
413ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
414ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = output->port->dev;
415ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
416ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_lock_irq(&output->lock);
417ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_OUTPUT_CONTROL(output->nr));
418ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, DMA_BUFFER_CONTROL(output->nr + 8));
419ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->running = 0;
420ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_unlock_irq(&output->lock);
421ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
422ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
423ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic u32 ddb_output_free(struct ddb_output *output)
424ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
425ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 idx, off, stat = output->stat;
426ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	s32 diff;
427ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
428ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	idx = (stat >> 11) & 0x1f;
429ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	off = (stat & 0x7ff) << 7;
430ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
431ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (output->cbuf != idx) {
432ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
433ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		    (output->dma_buf_size - output->coff <= 188))
434ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return 0;
435ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 188;
436ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
437ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	diff = off - output->coff;
438ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (diff <= 0 || diff > 188)
439ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 188;
440ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
441ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
442ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
4434f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endrissstatic ssize_t ddb_output_write(struct ddb_output *output,
444ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				const u8 *buf, size_t count)
445ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
446ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = output->port->dev;
447ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 idx, off, stat = output->stat;
448ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 left = count, len;
449ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
450ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	idx = (stat >> 11) & 0x1f;
451ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	off = (stat & 0x7ff) << 7;
452ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
453ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	while (left) {
454ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		len = output->dma_buf_size - output->coff;
455ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if ((((output->cbuf + 1) % output->dma_buf_num) == idx) &&
456ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		    (off == 0)) {
4574f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			if (len <= 188)
458ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				break;
4594f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			len -= 188;
460ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
461ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (output->cbuf == idx) {
462ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (off > output->coff) {
463ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#if 1
464ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				len = off - output->coff;
465ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				len -= (len % 188);
466ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				if (len <= 188)
467ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
468ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#endif
469ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler					break;
470ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				len -= 188;
471ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			}
472ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
473ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (len > left)
474ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			len = left;
475ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (copy_from_user(output->vbuf[output->cbuf] + output->coff,
476ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   buf, len))
477ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return -EIO;
478ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		left -= len;
479ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		buf += len;
480ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		output->coff += len;
481ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (output->coff == output->dma_buf_size) {
482ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			output->coff = 0;
483ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			output->cbuf = ((output->cbuf + 1) % output->dma_buf_num);
484ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
485ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel((output->cbuf << 11) | (output->coff >> 7),
486ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			  DMA_BUFFER_ACK(output->nr + 8));
487ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
488ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return count - left;
489ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
490ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
491ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic u32 ddb_input_avail(struct ddb_input *input)
492ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
493ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = input->port->dev;
494ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 idx, off, stat = input->stat;
495ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 ctrl = ddbreadl(DMA_BUFFER_CONTROL(input->nr));
496ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
497ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	idx = (stat >> 11) & 0x1f;
498ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	off = (stat & 0x7ff) << 7;
499ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
500ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ctrl & 4) {
5014f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl);
502ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr));
503ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 0;
504ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
505ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (input->cbuf != idx)
506ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 188;
507ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
508ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
509ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
5102122eaf64acd9ca42645b4bf8f222c7d452313f1Hans Verkuilstatic ssize_t ddb_input_read(struct ddb_input *input, u8 *buf, size_t count)
511ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
512ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = input->port->dev;
513ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 left = count;
5142122eaf64acd9ca42645b4bf8f222c7d452313f1Hans Verkuil	u32 idx, free, stat = input->stat;
515ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int ret;
516ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
517ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	idx = (stat >> 11) & 0x1f;
518ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
519ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	while (left) {
520ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (input->cbuf == idx)
521ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return count - left;
522ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		free = input->dma_buf_size - input->coff;
523ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (free > left)
524ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			free = left;
525ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ret = copy_to_user(buf, input->vbuf[input->cbuf] +
526ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   input->coff, free);
5272122eaf64acd9ca42645b4bf8f222c7d452313f1Hans Verkuil		if (ret)
5282122eaf64acd9ca42645b4bf8f222c7d452313f1Hans Verkuil			return -EFAULT;
529ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		input->coff += free;
530ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (input->coff == input->dma_buf_size) {
531ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			input->coff = 0;
532ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			input->cbuf = (input->cbuf+1) % input->dma_buf_num;
533ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
534ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		left -= free;
535ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel((input->cbuf << 11) | (input->coff >> 7),
536ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			  DMA_BUFFER_ACK(input->nr));
537ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
538ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return count;
539ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
540ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
541ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
542ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
543ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
544ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
545ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#if 0
546ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct ddb_input *fe2input(struct ddb *dev, struct dvb_frontend *fe)
547ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
548ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
549ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
550ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num * 2; i++) {
5514f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (dev->input[i].fe == fe)
552ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return &dev->input[i];
553ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
554ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return NULL;
555ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
556ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#endif
557ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
558ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
559ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
560ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_input *input = fe->sec_priv;
561ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_port *port = input->port;
562ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int status;
563ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
564ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (enable) {
565ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		mutex_lock(&port->i2c_gate_lock);
566ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		status = input->gate_ctrl(fe, 1);
567ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	} else {
568ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		status = input->gate_ctrl(fe, 0);
569ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		mutex_unlock(&port->i2c_gate_lock);
570ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
571ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return status;
572ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
573ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
574ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int demod_attach_drxk(struct ddb_input *input)
575ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
576ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_adapter *i2c = &input->port->i2c->adap;
577ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_frontend *fe;
5780fc55e81d3364e6535cacb10b5a579f8c62625b1Mauro Carvalho Chehab	struct drxk_config config;
579ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
5800fc55e81d3364e6535cacb10b5a579f8c62625b1Mauro Carvalho Chehab	memset(&config, 0, sizeof(config));
581da989e0bc7f2b3db3fea417c0bae3c20c6455995Mauro Carvalho Chehab	config.microcode_name = "drxk_a3.mc";
5820fc55e81d3364e6535cacb10b5a579f8c62625b1Mauro Carvalho Chehab	config.adr = 0x29 + (input->nr & 1);
5830fc55e81d3364e6535cacb10b5a579f8c62625b1Mauro Carvalho Chehab
584fa4b2a171d42ffc512b3a86922ad68e1355eb17aMauro Carvalho Chehab	fe = input->fe = dvb_attach(drxk_attach, &config, i2c);
585ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!input->fe) {
5864f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "No DRXK found!\n");
587ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -ENODEV;
588ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
589ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	fe->sec_priv = input;
590ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->gate_ctrl = fe->ops.i2c_gate_ctrl;
591ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
592ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
593ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
594ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
595ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int tuner_attach_tda18271(struct ddb_input *input)
596ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
597ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_adapter *i2c = &input->port->i2c->adap;
598ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_frontend *fe;
599ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
600ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (input->fe->ops.i2c_gate_ctrl)
601ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		input->fe->ops.i2c_gate_ctrl(input->fe, 1);
602ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60);
603ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!fe) {
6044f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "No TDA18271 found!\n");
605ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -ENODEV;
606ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
607ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (input->fe->ops.i2c_gate_ctrl)
608ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		input->fe->ops.i2c_gate_ctrl(input->fe, 0);
609ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
610ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
611ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
612ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
613ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
614ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
615ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
616ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct stv090x_config stv0900 = {
617ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.device         = STV0900,
618ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.demod_mode     = STV090x_DUAL,
619ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.clk_mode       = STV090x_CLK_EXT,
620ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
621ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.xtal           = 27000000,
622ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.address        = 0x69,
623ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
624ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
625ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
626ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
627ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.repeater_level = STV090x_RPTLEVEL_16,
628ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
629ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.adc1_range	= STV090x_ADC_1Vpp,
630ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.adc2_range	= STV090x_ADC_1Vpp,
631ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
632ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.diseqc_envelope_mode = true,
633ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
634ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
635ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct stv090x_config stv0900_aa = {
636ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.device         = STV0900,
637ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.demod_mode     = STV090x_DUAL,
638ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.clk_mode       = STV090x_CLK_EXT,
639ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
640ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.xtal           = 27000000,
641ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.address        = 0x68,
642ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
643ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
644ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
645ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
646ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.repeater_level = STV090x_RPTLEVEL_16,
647ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
648ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.adc1_range	= STV090x_ADC_1Vpp,
649ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.adc2_range	= STV090x_ADC_1Vpp,
650ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
651ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.diseqc_envelope_mode = true,
652ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
653ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
654ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct stv6110x_config stv6110a = {
655ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.addr    = 0x60,
656ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.refclk	 = 27000000,
657ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.clk_div = 1,
658ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
659ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
660ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct stv6110x_config stv6110b = {
661ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.addr    = 0x63,
662ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.refclk	 = 27000000,
663ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.clk_div = 1,
664ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
665ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
666ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int demod_attach_stv0900(struct ddb_input *input, int type)
667ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
668ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_adapter *i2c = &input->port->i2c->adap;
669ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
670ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
6714f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	input->fe = dvb_attach(stv090x_attach, feconf, i2c,
6724f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			       (input->nr & 1) ? STV090x_DEMODULATOR_1
6734f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			       : STV090x_DEMODULATOR_0);
674ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!input->fe) {
6754f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "No STV0900 found!\n");
676ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -ENODEV;
677ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
678ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0,
679ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			0, (input->nr & 1) ?
680ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			(0x09 - type) : (0x0b - type))) {
6814f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "No LNBH24 found!\n");
682ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -ENODEV;
683ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
684ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
685ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
686ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
687ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int tuner_attach_stv6110(struct ddb_input *input, int type)
688ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
689ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct i2c_adapter *i2c = &input->port->i2c->adap;
690ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900;
691ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct stv6110x_config *tunerconf = (input->nr & 1) ?
692ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		&stv6110b : &stv6110a;
693ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct stv6110x_devctl *ctl;
694ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
695ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c);
696ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!ctl) {
6974f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "No STV6110X found!\n");
698ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -ENODEV;
699ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
7004f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_INFO "attach tuner input %d adr %02x\n",
7014f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			 input->nr, tunerconf->addr);
702ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
703ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_init          = ctl->tuner_init;
704ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_sleep         = ctl->tuner_sleep;
705ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_set_mode      = ctl->tuner_set_mode;
706ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
707ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
708ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_set_bandwidth = ctl->tuner_set_bandwidth;
709ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_get_bandwidth = ctl->tuner_get_bandwidth;
710ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_set_bbgain    = ctl->tuner_set_bbgain;
711ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_get_bbgain    = ctl->tuner_get_bbgain;
712ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_set_refclk    = ctl->tuner_set_refclk;
713ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	feconf->tuner_get_status    = ctl->tuner_get_status;
714ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
715ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
716ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
717ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
718805e68743460dd48971d5df2707eb445d980874cMauro Carvalho Chehabstatic int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
719ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			    int (*start_feed)(struct dvb_demux_feed *),
720ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			    int (*stop_feed)(struct dvb_demux_feed *),
721ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			    void *priv)
722ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
723ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->priv = priv;
724ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
725ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->filternum = 256;
726ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->feednum = 256;
727ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->start_feed = start_feed;
728ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->stop_feed = stop_feed;
729ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->write_to_decoder = NULL;
730ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
731ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				      DMX_SECTION_FILTERING |
732ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				      DMX_MEMORY_BASED_FILTERING);
733ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return dvb_dmx_init(dvbdemux);
734ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
735ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
736805e68743460dd48971d5df2707eb445d980874cMauro Carvalho Chehabstatic int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
737ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			       struct dvb_demux *dvbdemux,
738ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			       struct dmx_frontend *hw_frontend,
739ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			       struct dmx_frontend *mem_frontend,
740ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			       struct dvb_adapter *dvb_adapter)
741ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
742ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int ret;
743ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
744ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dmxdev->filternum = 256;
745ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dmxdev->demux = &dvbdemux->dmx;
746ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dmxdev->capabilities = 0;
747ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
748ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ret < 0)
749ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return ret;
750ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
751ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	hw_frontend->source = DMX_FRONTEND_0;
752ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
753ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	mem_frontend->source = DMX_MEMORY_FE;
754ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
755ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
756ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
757ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
758ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int start_feed(struct dvb_demux_feed *dvbdmxfeed)
759ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
760ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
761ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_input *input = dvbdmx->priv;
762ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
763ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!input->users)
764ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddb_input_start(input);
765ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
766ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return ++input->users;
767ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
768ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
769ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int stop_feed(struct dvb_demux_feed *dvbdmxfeed)
770ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
771ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
772ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_input *input = dvbdmx->priv;
773ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
774ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (--input->users)
775ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return input->users;
776ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
777ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_input_stop(input);
778ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
779ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
780ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
781ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
782ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void dvb_input_detach(struct ddb_input *input)
783ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
784ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_adapter *adap = &input->adap;
785ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_demux *dvbdemux = &input->demux;
786ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
787ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	switch (input->attached) {
788ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case 5:
789ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (input->fe2)
790ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			dvb_unregister_frontend(input->fe2);
791ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (input->fe) {
792ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			dvb_unregister_frontend(input->fe);
793ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			dvb_frontend_detach(input->fe);
794ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			input->fe = NULL;
795ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
796ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case 4:
797ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dvb_net_release(&input->dvbnet);
798ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
799ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case 3:
800ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dvbdemux->dmx.close(&dvbdemux->dmx);
801ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
802ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler					      &input->hw_frontend);
803ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
804ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler					      &input->mem_frontend);
805ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dvb_dmxdev_release(&input->dmxdev);
806ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
807ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case 2:
808ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dvb_dmx_release(&input->demux);
809ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
810ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case 1:
811ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dvb_unregister_adapter(adap);
812ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
813ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->attached = 0;
814ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
815ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
816ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int dvb_input_attach(struct ddb_input *input)
817ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
818ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int ret;
819ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_port *port = input->port;
820ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_adapter *adap = &input->adap;
821ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_demux *dvbdemux = &input->demux;
822ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
8234f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE,
824ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   &input->port->dev->pdev->dev,
825ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   adapter_nr);
826ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ret < 0) {
8274f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "ddbridge: Could not register adapter."
828ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		       "Check if you enabled enough adapters in dvb-core!\n");
829ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return ret;
830ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
831ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->attached = 1;
832ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
833ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
834ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				      start_feed,
835ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				      stop_feed, input);
836ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ret < 0)
837ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return ret;
838ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->attached = 2;
839ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
840ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ret = my_dvb_dmxdev_ts_card_init(&input->dmxdev, &input->demux,
841ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler					 &input->hw_frontend,
842ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler					 &input->mem_frontend, adap);
843ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ret < 0)
844ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return ret;
845ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->attached = 3;
846ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
847ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ret = dvb_net_init(adap, &input->dvbnet, input->dmxdev.demux);
848ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ret < 0)
849ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return ret;
850ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->attached = 4;
851ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
852ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->fe = 0;
853ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	switch (port->type) {
854ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case DDB_TUNER_DVBS_ST:
855ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (demod_attach_stv0900(input, 0) < 0)
856ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return -ENODEV;
857ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (tuner_attach_stv6110(input, 0) < 0)
858ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return -ENODEV;
859ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (input->fe) {
860ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (dvb_register_frontend(adap, input->fe) < 0)
861ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				return -ENODEV;
862ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
863ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		break;
864ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case DDB_TUNER_DVBS_ST_AA:
865ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (demod_attach_stv0900(input, 1) < 0)
866ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return -ENODEV;
867ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (tuner_attach_stv6110(input, 1) < 0)
868ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return -ENODEV;
869ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (input->fe) {
870ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (dvb_register_frontend(adap, input->fe) < 0)
871ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				return -ENODEV;
872ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
873ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		break;
874ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case DDB_TUNER_DVBCT_TR:
875ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (demod_attach_drxk(input) < 0)
876ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return -ENODEV;
877ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (tuner_attach_tda18271(input) < 0)
878ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			return -ENODEV;
879ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (input->fe) {
880ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (dvb_register_frontend(adap, input->fe) < 0)
881ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				return -ENODEV;
882ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
883ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (input->fe2) {
884ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (dvb_register_frontend(adap, input->fe2) < 0)
885ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				return -ENODEV;
8864f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			input->fe2->tuner_priv = input->fe->tuner_priv;
887ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			memcpy(&input->fe2->ops.tuner_ops,
888ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			       &input->fe->ops.tuner_ops,
889ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			       sizeof(struct dvb_tuner_ops));
890ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
891ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		break;
892ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
893ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->attached = 5;
894ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
895ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
896ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
897ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
898ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
899ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
900ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic ssize_t ts_write(struct file *file, const char *buf,
901ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			size_t count, loff_t *ppos)
902ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
903ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_device *dvbdev = file->private_data;
904ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_output *output = dvbdev->priv;
905ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	size_t left = count;
906ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int stat;
907ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
908ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	while (left) {
909ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (ddb_output_free(output) < 188) {
910ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (file->f_flags & O_NONBLOCK)
911ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				break;
912ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (wait_event_interruptible(
913ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				    output->wq, ddb_output_free(output) >= 188) < 0)
914ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				break;
915ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
916ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		stat = ddb_output_write(output, buf, left);
917ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (stat < 0)
918ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
919ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		buf += stat;
920ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		left -= stat;
921ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
922ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return (left == count) ? -EAGAIN : (count - left);
923ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
924ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
925ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic ssize_t ts_read(struct file *file, char *buf,
926ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		       size_t count, loff_t *ppos)
927ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
928ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_device *dvbdev = file->private_data;
929ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_output *output = dvbdev->priv;
930ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_input *input = output->port->input[0];
931ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int left, read;
932ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
933ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	count -= count % 188;
934ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	left = count;
935ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	while (left) {
936ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (ddb_input_avail(input) < 188) {
937ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (file->f_flags & O_NONBLOCK)
938ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				break;
939ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (wait_event_interruptible(
940ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				    input->wq, ddb_input_avail(input) >= 188) < 0)
941ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				break;
942ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
943ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		read = ddb_input_read(input, buf, left);
9442122eaf64acd9ca42645b4bf8f222c7d452313f1Hans Verkuil		if (read < 0)
9452122eaf64acd9ca42645b4bf8f222c7d452313f1Hans Verkuil			return read;
946ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		left -= read;
947ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		buf += read;
948ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
949ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return (left == count) ? -EAGAIN : (count - left);
950ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
951ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
952ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic unsigned int ts_poll(struct file *file, poll_table *wait)
953ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
9544f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	/*
955ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct dvb_device *dvbdev = file->private_data;
956ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_output *output = dvbdev->priv;
957ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_input *input = output->port->input[0];
9584f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	*/
959ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	unsigned int mask = 0;
960ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
961ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#if 0
962ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (data_avail_to_read)
963ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		mask |= POLLIN | POLLRDNORM;
964ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (data_avail_to_write)
965ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		mask |= POLLOUT | POLLWRNORM;
966ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
967ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	poll_wait(file, &read_queue, wait);
968ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	poll_wait(file, &write_queue, wait);
969ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#endif
970ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return mask;
971ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
972ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
9734f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endrissstatic const struct file_operations ci_fops = {
974ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.owner   = THIS_MODULE,
975ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.read    = ts_read,
976ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.write   = ts_write,
977ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.open    = dvb_generic_open,
978ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.release = dvb_generic_release,
979ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.poll    = ts_poll,
980ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.mmap    = 0,
981ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
982ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
983ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct dvb_device dvbdev_ci = {
984ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.priv    = 0,
985ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.readers = -1,
986ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.writers = -1,
987ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.users   = -1,
988ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.fops    = &ci_fops,
989ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
990ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
991ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
992ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
993ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
994ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
995ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void input_tasklet(unsigned long data)
996ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
997ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_input *input = (struct ddb_input *) data;
998ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = input->port->dev;
999ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1000ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_lock(&input->lock);
1001ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!input->running) {
1002ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		spin_unlock(&input->lock);
1003ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return;
1004ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1005ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
1006ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1007ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (input->port->class == DDB_PORT_TUNER) {
1008ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))
10094f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			printk(KERN_ERR "Overflow input %d\n", input->nr);
1010ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		while (input->cbuf != ((input->stat >> 11) & 0x1f)
1011ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		       || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) {
1012ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			dvb_dmx_swfilter_packets(&input->demux,
1013ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler						 input->vbuf[input->cbuf],
1014ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler						 input->dma_buf_size / 188);
1015ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1016ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			input->cbuf = (input->cbuf + 1) % input->dma_buf_num;
1017ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			ddbwritel((input->cbuf << 11),
1018ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				  DMA_BUFFER_ACK(input->nr));
1019ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			input->stat = ddbreadl(DMA_BUFFER_CURRENT(input->nr));
1020ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		       }
1021ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1022ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (input->port->class == DDB_PORT_CI)
1023ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		wake_up(&input->wq);
1024ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_unlock(&input->lock);
1025ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1026ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1027ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void output_tasklet(unsigned long data)
1028ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1029ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_output *output = (struct ddb_output *) data;
1030ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = output->port->dev;
1031ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1032ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_lock(&output->lock);
1033ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!output->running) {
1034ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		spin_unlock(&output->lock);
1035ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return;
1036ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1037ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->stat = ddbreadl(DMA_BUFFER_CURRENT(output->nr + 8));
1038ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	wake_up(&output->wq);
1039ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_unlock(&output->lock);
1040ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1041ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1042ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1043ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstruct cxd2099_cfg cxd_cfg = {
1044ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.bitrate =  62000,
1045ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.adr     =  0x40,
1046ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.polarity = 1,
1047ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.clock_mode = 1,
1048ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1049ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1050ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_ci_attach(struct ddb_port *port)
1051ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1052ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int ret;
1053ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1054ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ret = dvb_register_adapter(&port->output->adap,
1055ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   "DDBridge",
1056ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   THIS_MODULE,
1057ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   &port->dev->pdev->dev,
1058ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				   adapter_nr);
1059ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ret < 0)
1060ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return ret;
1061ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	port->en = cxd2099_attach(&cxd_cfg, port, &port->i2c->adap);
1062ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!port->en) {
1063ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dvb_unregister_adapter(&port->output->adap);
1064ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -ENODEV;
1065ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1066ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_input_start(port->input[0]);
1067ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_output_start(port->output);
1068ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dvb_ca_en50221_init(&port->output->adap,
1069ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			    port->en, 0, 1);
10704f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	ret = dvb_register_device(&port->output->adap, &port->output->dev,
10714f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss				  &dvbdev_ci, (void *) port->output,
10724f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss				  DVB_DEVICE_SEC);
1073ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return ret;
1074ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1075ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1076ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_port_attach(struct ddb_port *port)
1077ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1078ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int ret = 0;
1079ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1080ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	switch (port->class) {
1081ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case DDB_PORT_TUNER:
1082ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ret = dvb_input_attach(port->input[0]);
10834f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (ret < 0)
1084ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
1085ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ret = dvb_input_attach(port->input[1]);
1086ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		break;
1087ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case DDB_PORT_CI:
1088ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ret = ddb_ci_attach(port);
1089ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		break;
1090ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	default:
1091ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		break;
1092ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1093ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ret < 0)
10944f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		printk(KERN_ERR "port_attach on port %d failed\n", port->nr);
1095ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return ret;
1096ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1097ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1098ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_ports_attach(struct ddb *dev)
1099ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1100ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i, ret = 0;
1101ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_port *port;
1102ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1103ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
1104ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port = &dev->port[i];
1105ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ret = ddb_port_attach(port);
1106ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (ret < 0)
1107ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
1108ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1109ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return ret;
1110ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1111ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1112ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_ports_detach(struct ddb *dev)
1113ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1114ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
1115ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_port *port;
1116ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1117ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
1118ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port = &dev->port[i];
1119ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		switch (port->class) {
1120ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		case DDB_PORT_TUNER:
1121ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			dvb_input_detach(port->input[0]);
1122ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			dvb_input_detach(port->input[1]);
1123ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
1124ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		case DDB_PORT_CI:
1125ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (port->output->dev)
1126ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				dvb_unregister_device(port->output->dev);
1127ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			if (port->en) {
1128ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				ddb_input_stop(port->input[0]);
1129ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				ddb_output_stop(port->output);
1130ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				dvb_ca_en50221_release(port->en);
1131ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				kfree(port->en);
1132ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				port->en = 0;
1133ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				dvb_unregister_adapter(&port->output->adap);
1134ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			}
1135ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			break;
1136ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		}
1137ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1138ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1139ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1140ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
1141ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
1142ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1143ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int port_has_ci(struct ddb_port *port)
1144ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1145ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u8 val;
11464f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	return i2c_read_reg(&port->i2c->adap, 0x40, 0, &val) ? 0 : 1;
1147ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1148ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1149ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int port_has_stv0900(struct ddb_port *port)
1150ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1151ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u8 val;
1152ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (i2c_read_reg16(&port->i2c->adap, 0x69, 0xf100, &val) < 0)
1153ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 0;
1154ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 1;
1155ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1156ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1157ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int port_has_stv0900_aa(struct ddb_port *port)
1158ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1159ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u8 val;
1160ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (i2c_read_reg16(&port->i2c->adap, 0x68, 0xf100, &val) < 0)
1161ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 0;
1162ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 1;
1163ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1164ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1165ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int port_has_drxks(struct ddb_port *port)
1166ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1167ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u8 val;
1168ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (i2c_read(&port->i2c->adap, 0x29, &val) < 0)
1169ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 0;
1170ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (i2c_read(&port->i2c->adap, 0x2a, &val) < 0)
1171ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 0;
1172ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 1;
1173ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1174ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1175ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_port_probe(struct ddb_port *port)
1176ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1177ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = port->dev;
1178ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	char *modname = "NO MODULE";
1179ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1180ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	port->class = DDB_PORT_NONE;
1181ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1182ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (port_has_ci(port)) {
1183ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		modname = "CI";
1184ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->class = DDB_PORT_CI;
1185ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
1186ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	} else if (port_has_stv0900(port)) {
1187ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		modname = "DUAL DVB-S2";
1188ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->class = DDB_PORT_TUNER;
1189ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->type = DDB_TUNER_DVBS_ST;
1190ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
1191ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	} else if (port_has_stv0900_aa(port)) {
1192ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		modname = "DUAL DVB-S2";
1193ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->class = DDB_PORT_TUNER;
1194ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->type = DDB_TUNER_DVBS_ST_AA;
1195ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING);
1196ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	} else if (port_has_drxks(port)) {
1197ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		modname = "DUAL DVB-C/T";
1198ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->class = DDB_PORT_TUNER;
1199ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->type = DDB_TUNER_DVBCT_TR;
1200ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING);
1201ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
12024f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_INFO "Port %d (TAB %d): %s\n",
12034f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			 port->nr, port->nr+1, modname);
1204ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1205ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1206ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_input_init(struct ddb_port *port, int nr)
1207ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1208ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = port->dev;
1209ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_input *input = &dev->input[nr];
1210ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1211ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->nr = nr;
1212ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->port = port;
1213ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->dma_buf_num = INPUT_DMA_BUFS;
1214ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	input->dma_buf_size = INPUT_DMA_SIZE;
1215ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_INPUT_CONTROL(nr));
1216ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(2, TS_INPUT_CONTROL(nr));
1217ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_INPUT_CONTROL(nr));
1218ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, DMA_BUFFER_ACK(nr));
1219ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	tasklet_init(&input->tasklet, input_tasklet, (unsigned long) input);
1220ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	spin_lock_init(&input->lock);
1221ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	init_waitqueue_head(&input->wq);
1222ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1223ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1224ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_output_init(struct ddb_port *port, int nr)
1225ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1226ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = port->dev;
1227ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_output *output = &dev->output[nr];
1228ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->nr = nr;
1229ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->port = port;
1230ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->dma_buf_num = OUTPUT_DMA_BUFS;
1231ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	output->dma_buf_size = OUTPUT_DMA_SIZE;
1232ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1233ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
1234ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(2, TS_OUTPUT_CONTROL(nr));
1235ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, TS_OUTPUT_CONTROL(nr));
1236ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	tasklet_init(&output->tasklet, output_tasklet, (unsigned long) output);
1237ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	init_waitqueue_head(&output->wq);
1238ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1239ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1240ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_ports_init(struct ddb *dev)
1241ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1242ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
1243ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_port *port;
1244ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1245ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
1246ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port = &dev->port[i];
1247ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->dev = dev;
1248ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->nr = i;
1249ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->i2c = &dev->i2c[i];
1250ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->input[0] = &dev->input[2 * i];
1251ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->input[1] = &dev->input[2 * i + 1];
1252ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->output = &dev->output[i];
1253ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1254ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		mutex_init(&port->i2c_gate_lock);
1255ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddb_port_probe(port);
1256ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddb_input_init(port, 2 * i);
1257ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddb_input_init(port, 2 * i + 1);
1258ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddb_output_init(port, i);
1259ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1260ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1261ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1262ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_ports_release(struct ddb *dev)
1263ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1264ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int i;
1265ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_port *port;
1266ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1267ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	for (i = 0; i < dev->info->port_num; i++) {
1268ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port = &dev->port[i];
1269ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		port->dev = dev;
1270ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		tasklet_kill(&port->input[0]->tasklet);
1271ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		tasklet_kill(&port->input[1]->tasklet);
1272ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		tasklet_kill(&port->output->tasklet);
1273ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1274ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1275ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1276ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
1277ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
1278ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
1279ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1280ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void irq_handle_i2c(struct ddb *dev, int n)
1281ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1282ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb_i2c *i2c = &dev->i2c[n];
1283ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1284ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	i2c->done = 1;
1285ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	wake_up(&i2c->wq);
1286ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1287ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1288ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic irqreturn_t irq_handler(int irq, void *dev_id)
1289ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1290ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = (struct ddb *) dev_id;
1291ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 s = ddbreadl(INTERRUPT_STATUS);
1292ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1293ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!s)
1294ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return IRQ_NONE;
1295ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1296ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	do {
1297ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(s, INTERRUPT_ACK);
1298ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
12994f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00000001)
13004f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			irq_handle_i2c(dev, 0);
13014f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00000002)
13024f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			irq_handle_i2c(dev, 1);
13034f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00000004)
13044f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			irq_handle_i2c(dev, 2);
13054f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00000008)
13064f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			irq_handle_i2c(dev, 3);
13074f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss
13084f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00000100)
13094f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->input[0].tasklet);
13104f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00000200)
13114f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->input[1].tasklet);
13124f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00000400)
13134f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->input[2].tasklet);
13144f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00000800)
13154f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->input[3].tasklet);
13164f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00001000)
13174f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->input[4].tasklet);
13184f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00002000)
13194f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->input[5].tasklet);
13204f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00004000)
13214f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->input[6].tasklet);
13224f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00008000)
13234f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->input[7].tasklet);
13244f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss
13254f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00010000)
13264f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->output[0].tasklet);
13274f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00020000)
13284f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->output[1].tasklet);
13294f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00040000)
13304f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->output[2].tasklet);
13314f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		if (s & 0x00080000)
13324f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			tasklet_schedule(&dev->output[3].tasklet);
13334f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss
13344f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		/* if (s & 0x000f0000)	printk(KERN_DEBUG "%08x\n", istat); */
1335ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	} while ((s = ddbreadl(INTERRUPT_STATUS)));
1336ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1337ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return IRQ_HANDLED;
1338ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1339ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1340ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
1341ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
1342ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
1343ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1344ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen)
1345ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1346ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	u32 data, shift;
1347ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1348ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (wlen > 4)
1349ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(1, SPI_CONTROL);
1350ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	while (wlen > 4) {
1351ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		/* FIXME: check for big-endian */
1352ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		data = swab32(*(u32 *)wbuf);
1353ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		wbuf += 4;
1354ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		wlen -= 4;
1355ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(data, SPI_DATA);
13564f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		while (ddbreadl(SPI_CONTROL) & 0x0004)
13574f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			;
1358ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1359ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1360ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (rlen)
1361ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(0x0001 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
1362ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	else
1363ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(0x0003 | ((wlen << (8 + 3)) & 0x1f00), SPI_CONTROL);
1364ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
13654f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	data = 0;
1366ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	shift = ((4 - wlen) * 8);
1367ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	while (wlen) {
1368ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		data <<= 8;
1369ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		data |= *wbuf;
1370ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		wlen--;
1371ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		wbuf++;
1372ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1373ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (shift)
1374ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		data <<= shift;
1375ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(data, SPI_DATA);
13764f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	while (ddbreadl(SPI_CONTROL) & 0x0004)
13774f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		;
1378ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1379ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!rlen) {
1380ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(0, SPI_CONTROL);
1381ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return 0;
1382ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1383ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (rlen > 4)
1384ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(1, SPI_CONTROL);
1385ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1386ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	while (rlen > 4) {
1387ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		ddbwritel(0xffffffff, SPI_DATA);
13884f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		while (ddbreadl(SPI_CONTROL) & 0x0004)
13894f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			;
1390ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		data = ddbreadl(SPI_DATA);
1391ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		*(u32 *) rbuf = swab32(data);
1392ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		rbuf += 4;
1393ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		rlen -= 4;
1394ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1395ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL);
1396ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0xffffffff, SPI_DATA);
13974f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	while (ddbreadl(SPI_CONTROL) & 0x0004)
13984f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss		;
1399ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1400ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	data = ddbreadl(SPI_DATA);
1401ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, SPI_CONTROL);
1402ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1403ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (rlen < 4)
1404ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		data <<= ((4 - rlen) * 8);
1405ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1406ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	while (rlen > 0) {
1407ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		*rbuf = ((data >> 24) & 0xff);
1408ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		data <<= 8;
1409ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		rbuf++;
1410ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		rlen--;
1411ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1412ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
1413ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1414ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1415ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#define DDB_MAGIC 'd'
1416ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1417ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstruct ddb_flashio {
1418ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	__u8 *write_buf;
1419ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	__u32 write_len;
1420ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	__u8 *read_buf;
1421ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	__u32 read_len;
1422ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1423ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1424ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#define IOCTL_DDB_FLASHIO  _IOWR(DDB_MAGIC, 0x00, struct ddb_flashio)
1425ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1426ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#define DDB_NAME "ddbridge"
1427ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1428ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic u32 ddb_num;
1429ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct ddb *ddbs[32];
1430ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct class *ddb_class;
1431ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_major;
1432ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1433ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_open(struct inode *inode, struct file *file)
1434ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1435ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = ddbs[iminor(inode)];
1436ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1437ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	file->private_data = dev;
1438ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
1439ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1440ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1441ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1442ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1443ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = file->private_data;
1444ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	void *parg = (void *)arg;
1445e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter	int res;
1446ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1447ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	switch (cmd) {
1448ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	case IOCTL_DDB_FLASHIO:
1449ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	{
1450ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		struct ddb_flashio fio;
1451ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		u8 *rbuf, *wbuf;
1452ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1453ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (copy_from_user(&fio, parg, sizeof(fio)))
1454e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter			return -EFAULT;
1455e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter
1456e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter		if (fio.write_len > 1028 || fio.read_len > 1028)
1457e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter			return -EINVAL;
1458e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter		if (fio.write_len + fio.read_len > 1028)
1459e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter			return -EINVAL;
1460e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter
1461ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		wbuf = &dev->iobuf[0];
1462ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		rbuf = wbuf + fio.write_len;
1463e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter
1464e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter		if (copy_from_user(wbuf, fio.write_buf, fio.write_len))
1465e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter			return -EFAULT;
1466e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter		res = flashio(dev, wbuf, fio.write_len, rbuf, fio.read_len);
1467e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter		if (res)
1468e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter			return res;
1469ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		if (copy_to_user(fio.read_buf, rbuf, fio.read_len))
1470e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter			return -EFAULT;
1471ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		break;
1472ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1473ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	default:
1474e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter		return -ENOTTY;
1475ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1476e9013fb6eb397df9fd2e71d4f31a8bad4e65d046Dan Carpenter	return 0;
1477ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1478ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
14794f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endrissstatic const struct file_operations ddb_fops = {
1480ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.unlocked_ioctl = ddb_ioctl,
1481ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.open           = ddb_open,
1482ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1483ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
14842c9ede55ecec58099b72e4bb8eab719f32f72c31Al Virostatic char *ddb_devnode(struct device *device, umode_t *mode)
1485ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1486ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = dev_get_drvdata(device);
1487ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1488ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return kasprintf(GFP_KERNEL, "ddbridge/card%d", dev->nr);
1489ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1490ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1491ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_class_create(void)
1492ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
14934f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	ddb_major = register_chrdev(0, DDB_NAME, &ddb_fops);
14944f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	if (ddb_major < 0)
1495ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return ddb_major;
1496ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1497ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_class = class_create(THIS_MODULE, DDB_NAME);
1498ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (IS_ERR(ddb_class)) {
1499ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		unregister_chrdev(ddb_major, DDB_NAME);
1500ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -1;
1501ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1502ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_class->devnode = ddb_devnode;
1503ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
1504ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1505ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1506ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_class_destroy(void)
1507ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1508ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	class_destroy(ddb_class);
1509ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	unregister_chrdev(ddb_major, DDB_NAME);
1510ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1511ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1512ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int ddb_device_create(struct ddb *dev)
1513ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1514ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dev->nr = ddb_num++;
1515ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dev->ddb_dev = device_create(ddb_class, NULL,
1516ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     MKDEV(ddb_major, dev->nr),
1517ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler				     dev, "ddbridge%d", dev->nr);
1518ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbs[dev->nr] = dev;
1519ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (IS_ERR(dev->ddb_dev))
1520ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -1;
1521ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
1522ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1523ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1524ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_device_destroy(struct ddb *dev)
1525ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1526ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_num--;
1527ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (IS_ERR(dev->ddb_dev))
1528ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return;
1529ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	device_destroy(ddb_class, MKDEV(ddb_major, 0));
1530ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1531ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1532ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1533ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
1534ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
1535ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/****************************************************************************/
1536ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1537ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void ddb_unmap(struct ddb *dev)
1538ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1539ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (dev->regs)
1540ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		iounmap(dev->regs);
1541ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	vfree(dev);
1542ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1543ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1544ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1545ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic void __devexit ddb_remove(struct pci_dev *pdev)
1546ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1547ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev = (struct ddb *) pci_get_drvdata(pdev);
1548ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1549ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_ports_detach(dev);
1550ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_i2c_release(dev);
1551ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1552ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, INTERRUPT_ENABLE);
1553ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	free_irq(dev->pdev->irq, dev);
1554ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#ifdef CONFIG_PCI_MSI
1555ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (dev->msi)
1556ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		pci_disable_msi(dev->pdev);
1557ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#endif
1558ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_ports_release(dev);
1559ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_buffers_free(dev);
1560ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_device_destroy(dev);
1561ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1562ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_unmap(dev);
1563ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	pci_set_drvdata(pdev, 0);
1564ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	pci_disable_device(pdev);
1565ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1566ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1567ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1568ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic int __devinit ddb_probe(struct pci_dev *pdev,
1569ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler			       const struct pci_device_id *id)
1570ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1571ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	struct ddb *dev;
15724f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	int stat = 0;
1573ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	int irq_flag = IRQF_SHARED;
1574ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
15754f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	if (pci_enable_device(pdev) < 0)
1576ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -ENODEV;
1577ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1578ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dev = vmalloc(sizeof(struct ddb));
1579ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (dev == NULL)
1580ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -ENOMEM;
1581ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	memset(dev, 0, sizeof(struct ddb));
1582ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1583ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dev->pdev = pdev;
1584ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	pci_set_drvdata(pdev, dev);
1585ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	dev->info = (struct ddb_info *) id->driver_data;
15864f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name);
1587ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
15884f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	dev->regs = ioremap(pci_resource_start(dev->pdev, 0),
15894f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			    pci_resource_len(dev->pdev, 0));
1590ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (!dev->regs) {
1591ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		stat = -ENOMEM;
1592ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		goto fail;
1593ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
15944f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4));
1595ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1596ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#ifdef CONFIG_PCI_MSI
1597ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (pci_msi_enabled())
1598ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		stat = pci_enable_msi(dev->pdev);
1599ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (stat) {
1600ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		printk(KERN_INFO ": MSI not available.\n");
1601ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	} else {
1602ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		irq_flag = 0;
1603ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		dev->msi = 1;
1604ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1605ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#endif
16064f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	stat = request_irq(dev->pdev->irq, irq_handler,
16074f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss			   irq_flag, "DDBridge", (void *) dev);
16084f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	if (stat < 0)
1609ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		goto fail1;
1610ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, DMA_BASE_WRITE);
1611ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, DMA_BASE_READ);
1612ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0xffffffff, INTERRUPT_ACK);
1613ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0xfff0f, INTERRUPT_ENABLE);
1614ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddbwritel(0, MSI1_ENABLE);
1615ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1616ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ddb_i2c_init(dev) < 0)
1617ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		goto fail1;
1618ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_ports_init(dev);
1619ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ddb_buffers_alloc(dev) < 0) {
1620ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		printk(KERN_INFO ": Could not allocate buffer memory\n");
1621ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		goto fail2;
1622ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	}
1623ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ddb_ports_attach(dev) < 0)
1624ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		goto fail3;
1625ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_device_create(dev);
1626ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return 0;
1627ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1628ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerfail3:
1629ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_ports_detach(dev);
16304f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_ERR "fail3\n");
1631ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_ports_release(dev);
1632ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerfail2:
16334f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_ERR "fail2\n");
1634ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_buffers_free(dev);
1635ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerfail1:
16364f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_ERR "fail1\n");
1637ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (dev->msi)
1638ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		pci_disable_msi(dev->pdev);
1639ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	free_irq(dev->pdev->irq, dev);
1640ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerfail:
16414f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_ERR "fail\n");
1642ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_unmap(dev);
1643ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	pci_set_drvdata(pdev, 0);
1644ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	pci_disable_device(pdev);
1645ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return -1;
1646ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1647ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1648ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
1649ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
1650ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler/******************************************************************************/
1651ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1652ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct ddb_info ddb_none = {
1653ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.type     = DDB_NONE,
1654ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.name     = "Digital Devices PCIe bridge",
1655ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1656ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1657ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct ddb_info ddb_octopus = {
1658ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.type     = DDB_OCTOPUS,
1659ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.name     = "Digital Devices Octopus DVB adapter",
1660ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.port_num = 4,
1661ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1662ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1663ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct ddb_info ddb_octopus_le = {
1664ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.type     = DDB_OCTOPUS,
1665ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.name     = "Digital Devices Octopus LE DVB adapter",
1666ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.port_num = 2,
1667ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1668ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1669ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct ddb_info ddb_v6 = {
1670ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.type     = DDB_OCTOPUS,
1671ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.name     = "Digital Devices Cine S2 V6 DVB adapter",
1672ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.port_num = 3,
1673ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1674ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1675ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler#define DDVID 0xdd01 /* Digital Devices Vendor ID */
1676ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
16774f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss#define DDB_ID(_vend, _dev, _subvend, _subdev, _driverdata) {	\
1678ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.vendor      = _vend,    .device    = _dev, \
1679ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.subvendor   = _subvend, .subdevice = _subdev, \
1680ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.driver_data = (unsigned long)&_driverdata }
1681ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1682ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic const struct pci_device_id ddb_id_tbl[] __devinitdata = {
1683ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	DDB_ID(DDVID, 0x0002, DDVID, 0x0001, ddb_octopus),
1684ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	DDB_ID(DDVID, 0x0003, DDVID, 0x0001, ddb_octopus),
1685ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	DDB_ID(DDVID, 0x0003, DDVID, 0x0002, ddb_octopus_le),
1686ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	DDB_ID(DDVID, 0x0003, DDVID, 0x0010, ddb_octopus),
1687ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	DDB_ID(DDVID, 0x0003, DDVID, 0x0020, ddb_v6),
1688ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	/* in case sub-ids got deleted in flash */
1689ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	DDB_ID(DDVID, 0x0003, PCI_ANY_ID, PCI_ANY_ID, ddb_none),
1690ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	{0}
1691ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1692ccad04578fcbe2678084af0986ac010ab84a023dRalph MetzlerMODULE_DEVICE_TABLE(pci, ddb_id_tbl);
1693ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1694ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1695ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic struct pci_driver ddb_pci_driver = {
1696ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.name        = "DDBridge",
1697ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.id_table    = ddb_id_tbl,
1698ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.probe       = ddb_probe,
1699ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	.remove      = ddb_remove,
1700ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler};
1701ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1702ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic __init int module_init_ddbridge(void)
1703ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
17044f1f31078745b7af73e1a3a718004807cb1b7846Oliver Endriss	printk(KERN_INFO "Digital Devices PCIE bridge driver, "
1705ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	       "Copyright (C) 2010-11 Digital Devices GmbH\n");
1706ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	if (ddb_class_create())
1707ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler		return -1;
1708ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	return pci_register_driver(&ddb_pci_driver);
1709ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1710ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1711ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlerstatic __exit void module_exit_ddbridge(void)
1712ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler{
1713ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	pci_unregister_driver(&ddb_pci_driver);
1714ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler	ddb_class_destroy();
1715ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler}
1716ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1717ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlermodule_init(module_init_ddbridge);
1718ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzlermodule_exit(module_exit_ddbridge);
1719ccad04578fcbe2678084af0986ac010ab84a023dRalph Metzler
1720ccad04578fcbe2678084af0986ac010ab84a023dRalph MetzlerMODULE_DESCRIPTION("Digital Devices PCIe Bridge");
1721ccad04578fcbe2678084af0986ac010ab84a023dRalph MetzlerMODULE_AUTHOR("Ralph Metzler");
1722ccad04578fcbe2678084af0986ac010ab84a023dRalph MetzlerMODULE_LICENSE("GPL");
1723ccad04578fcbe2678084af0986ac010ab84a023dRalph MetzlerMODULE_VERSION("0.5");
1724