1c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter/*
2c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * pluto2.c - Satelco Easywatch Mobile Terrestrial Receiver [DVB-T]
3c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter *
4c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * Copyright (C) 2005 Andreas Oberritter <obi@linuxtv.org>
5c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter *
6c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * based on pluto2.c 1.10 - http://instinct-wp8.no-ip.org/pluto/
7c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * 	by Dany Salman <salmandany@yahoo.fr>
8c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter *	Copyright (c) 2004 TDF
9c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter *
10c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * This program is free software; you can redistribute it and/or modify
11c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * it under the terms of the GNU General Public License as published by
12c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * the Free Software Foundation; either version 2 of the License, or
13c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * (at your option) any later version.
14c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter *
15c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * This program is distributed in the hope that it will be useful,
16c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * but WITHOUT ANY WARRANTY; without even the implied warranty of
17c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * GNU General Public License for more details.
19c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter *
20c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * You should have received a copy of the GNU General Public License
21c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * along with this program; if not, write to the Free Software
22c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter *
24c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter */
25c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
26c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include <linux/i2c.h>
27c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include <linux/i2c-algo-bit.h>
28c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include <linux/init.h>
29a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/interrupt.h>
30c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include <linux/kernel.h>
31c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include <linux/module.h>
32c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include <linux/pci.h>
33c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include <linux/dma-mapping.h>
345a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
35c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
36c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include "demux.h"
37c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include "dmxdev.h"
38c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include "dvb_demux.h"
39c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include "dvb_frontend.h"
40c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include "dvb_net.h"
41c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include "dvbdev.h"
42c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#include "tda1004x.h"
43c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
4478e92006f410a4044f8c1760c25ac9d11d259aa2Janne GrunauDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
4578e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau
46c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define DRIVER_NAME		"pluto2"
47c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
48c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_PIDn(n)		((n) << 2)	/* PID n pattern registers */
49c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_PCAR		0x0020		/* PC address register */
50c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_TSCR		0x0024		/* TS ctrl & status */
51c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_MISC		0x0028		/* miscellaneous */
52c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_MMAC		0x002c		/* MSB MAC address */
53c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_IMAC		0x0030		/* ISB MAC address */
54c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_LMAC		0x0034		/* LSB MAC address */
55c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_SPID		0x0038		/* SPI data */
56c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define REG_SLCS		0x003c		/* serial links ctrl/status */
57c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
58c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define PID0_NOFIL		(0x0001 << 16)
59c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define PIDn_ENP		(0x0001 << 15)
60c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define PID0_END		(0x0001 << 14)
61c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define PID0_AFIL		(0x0001 << 13)
62c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define PIDn_PID		(0x1fff <<  0)
63c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
64c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_NBPACKETS		(0x00ff << 24)
65c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_DEM		(0x0001 << 17)
66c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_DE			(0x0001 << 16)
67c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_RSTN		(0x0001 << 15)
68c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_MSKO		(0x0001 << 14)
69c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_MSKA		(0x0001 << 13)
70c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_MSKL		(0x0001 << 12)
71c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_OVR		(0x0001 << 11)
72c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_AFUL		(0x0001 << 10)
73c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_LOCK		(0x0001 <<  9)
74c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_IACK		(0x0001 <<  8)
75c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TSCR_ADEF		(0x007f <<  0)
76c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
77c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define MISC_DVR		(0x0fff <<  4)
78c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define MISC_ALED		(0x0001 <<  3)
79c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define MISC_FRST		(0x0001 <<  2)
80c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define MISC_LED1		(0x0001 <<  1)
81c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define MISC_LED0		(0x0001 <<  0)
82c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
83c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define SPID_SPIDR		(0x00ff <<  0)
84c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
85c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define SLCS_SCL		(0x0001 <<  7)
86c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define SLCS_SDA		(0x0001 <<  6)
87c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define SLCS_CSN		(0x0001 <<  2)
88c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define SLCS_OVR		(0x0001 <<  1)
89c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define SLCS_SWC		(0x0001 <<  0)
90c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
91c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TS_DMA_PACKETS		(8)
92c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define TS_DMA_BYTES		(188 * TS_DMA_PACKETS)
93c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
94c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define I2C_ADDR_TDA10046	0x10
95c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define I2C_ADDR_TUA6034	0xc2
96c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define NHWFILTERS		8
97c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
98c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstruct pluto {
99c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* pci */
100c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pci_dev *pdev;
101c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u8 __iomem *io_mem;
102c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
103c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* dvb */
104c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dmx_frontend hw_frontend;
105c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dmx_frontend mem_frontend;
106c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dmxdev dmxdev;
107c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dvb_adapter dvb_adapter;
108c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dvb_demux demux;
109c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dvb_frontend *fe;
110c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dvb_net dvbnet;
111c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	unsigned int full_ts_users;
112c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	unsigned int users;
113c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
114c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* i2c */
115c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct i2c_algo_bit_data i2c_bit;
116c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct i2c_adapter i2c_adap;
117c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	unsigned int i2cbug;
118c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
119c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* irq */
120c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	unsigned int overflow;
1210b61dca28909bc548581bec75e3b90faaa7f11fdAlan Cox	unsigned int dead;
122c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
123c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* dma */
124c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dma_addr_t dma_addr;
125c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u8 dma_buf[TS_DMA_BYTES];
126c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u8 dummy[4096];
127c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter};
128c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
129c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic inline struct pluto *feed_to_pluto(struct dvb_demux_feed *feed)
130c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
131c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return container_of(feed->demux, struct pluto, demux);
132c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
133c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
134c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic inline struct pluto *frontend_to_pluto(struct dvb_frontend *fe)
135c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
136c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return container_of(fe->dvb, struct pluto, dvb_adapter);
137c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
138c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
139c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic inline u32 pluto_readreg(struct pluto *pluto, u32 reg)
140c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
141c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return readl(&pluto->io_mem[reg]);
142c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
143c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
144c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic inline void pluto_writereg(struct pluto *pluto, u32 reg, u32 val)
145c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
146c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	writel(val, &pluto->io_mem[reg]);
147c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
148c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
149c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic inline void pluto_rw(struct pluto *pluto, u32 reg, u32 mask, u32 bits)
150c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
151c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 val = readl(&pluto->io_mem[reg]);
152c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val &= ~mask;
153c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val |= bits;
154c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	writel(val, &pluto->io_mem[reg]);
155c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
156c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
1571489f90a49f0603a393e1800d729050f6e332becAndreas Oberritterstatic void pluto_write_tscr(struct pluto *pluto, u32 val)
1581489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter{
1591489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter	/* set the number of packets */
1601489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter	val &= ~TSCR_ADEF;
1611489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter	val |= TS_DMA_PACKETS / 2;
1621489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter
1631489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter	pluto_writereg(pluto, REG_TSCR, val);
1641489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter}
1651489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter
166c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_setsda(void *data, int state)
167c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
168c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = data;
169c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
170c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (state)
171c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_SLCS, SLCS_SDA, SLCS_SDA);
172c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	else
173c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_SLCS, SLCS_SDA, 0);
174c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
175c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
176c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_setscl(void *data, int state)
177c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
178c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = data;
179c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
180c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (state)
181c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_SLCS, SLCS_SCL, SLCS_SCL);
182c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	else
183c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_SLCS, SLCS_SCL, 0);
184c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
185c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* try to detect i2c_inb() to workaround hardware bug:
186c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	 * reset SDA to high after SCL has been set to low */
187c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if ((state) && (pluto->i2cbug == 0)) {
188c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto->i2cbug = 1;
189c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	} else {
190c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		if ((!state) && (pluto->i2cbug == 1))
191c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			pluto_setsda(pluto, 1);
192c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto->i2cbug = 0;
193c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
194c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
195c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
196c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int pluto_getsda(void *data)
197c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
198c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = data;
199c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
200c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return pluto_readreg(pluto, REG_SLCS) & SLCS_SDA;
201c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
202c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
203c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int pluto_getscl(void *data)
204c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
205c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = data;
206c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
207c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return pluto_readreg(pluto, REG_SLCS) & SLCS_SCL;
208c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
209c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
210c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_reset_frontend(struct pluto *pluto, int reenable)
211c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
212c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 val = pluto_readreg(pluto, REG_MISC);
213c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
214c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (val & MISC_FRST) {
215c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		val &= ~MISC_FRST;
216c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_writereg(pluto, REG_MISC, val);
217c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
218c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (reenable) {
219c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		val |= MISC_FRST;
220c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_writereg(pluto, REG_MISC, val);
221c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
222c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
223c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
224c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_reset_ts(struct pluto *pluto, int reenable)
225c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
226c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 val = pluto_readreg(pluto, REG_TSCR);
227c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
228c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (val & TSCR_RSTN) {
229c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		val &= ~TSCR_RSTN;
2301489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter		pluto_write_tscr(pluto, val);
231c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
232c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (reenable) {
233c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		val |= TSCR_RSTN;
2341489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter		pluto_write_tscr(pluto, val);
235c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
236c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
237c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
238c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_set_dma_addr(struct pluto *pluto)
239c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
24067778b322780200ac14e95c8089a0bd679a467d9Al Viro	pluto_writereg(pluto, REG_PCAR, pluto->dma_addr);
241c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
242c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
243c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int __devinit pluto_dma_map(struct pluto *pluto)
244c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
245c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->dma_addr = pci_map_single(pluto->pdev, pluto->dma_buf,
246c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
247c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
2488d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori	return pci_dma_mapping_error(pluto->pdev, pluto->dma_addr);
249c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
250c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
251c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_dma_unmap(struct pluto *pluto)
252c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
253c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_unmap_single(pluto->pdev, pluto->dma_addr,
254c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
255c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
256c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
257c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int pluto_start_feed(struct dvb_demux_feed *f)
258c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
259c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = feed_to_pluto(f);
260c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
261c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* enable PID filtering */
262c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (pluto->users++ == 0)
263c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_PIDn(0), PID0_AFIL | PID0_NOFIL, 0);
264c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
265c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if ((f->pid < 0x2000) && (f->index < NHWFILTERS))
266c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_PIDn(f->index), PIDn_ENP | PIDn_PID, PIDn_ENP | f->pid);
267c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	else if (pluto->full_ts_users++ == 0)
268c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_PIDn(0), PID0_NOFIL, PID0_NOFIL);
269c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
270c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return 0;
271c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
272c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
273c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int pluto_stop_feed(struct dvb_demux_feed *f)
274c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
275c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = feed_to_pluto(f);
276c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
277c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* disable PID filtering */
278c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (--pluto->users == 0)
279c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_PIDn(0), PID0_AFIL, PID0_AFIL);
280c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
281c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if ((f->pid < 0x2000) && (f->index < NHWFILTERS))
282c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_PIDn(f->index), PIDn_ENP | PIDn_PID, 0x1fff);
283c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	else if (--pluto->full_ts_users == 0)
284c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_rw(pluto, REG_PIDn(0), PID0_NOFIL, 0);
285c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
286c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return 0;
287c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
288c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
289c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_dma_end(struct pluto *pluto, unsigned int nbpackets)
290c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
291c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* synchronize the DMA transfer with the CPU
292c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	 * first so that we see updated contents. */
293c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_dma_sync_single_for_cpu(pluto->pdev, pluto->dma_addr,
294c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
295c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
296c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* Workaround for broken hardware:
297c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	 * [1] On startup NBPACKETS seems to contain an uninitialized value,
29825985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 *     but no packets have been transferred.
299c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	 * [2] Sometimes (actually very often) NBPACKETS stays at zero
30025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 *     although one packet has been transferred.
3014d8451700171d6bbc254191880f86bfdeec2f74fholger@muscate-magnussen.de	 * [3] Sometimes (actually rarely), the card gets into an erroneous
3024d8451700171d6bbc254191880f86bfdeec2f74fholger@muscate-magnussen.de	 *     mode where it continuously generates interrupts, claiming it
30325985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 *     has received nbpackets>TS_DMA_PACKETS packets, but no packet
30425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 *     has been transferred. Only a reset seems to solve this
305c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	 */
306c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
3076573dd752d50730d44c550ad0467d15871963655Andreas Oberritter		unsigned int i = 0;
308c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		while (pluto->dma_buf[i] == 0x47)
309c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			i += 188;
3106573dd752d50730d44c550ad0467d15871963655Andreas Oberritter		nbpackets = i / 188;
3114d8451700171d6bbc254191880f86bfdeec2f74fholger@muscate-magnussen.de		if (i == 0) {
3124d8451700171d6bbc254191880f86bfdeec2f74fholger@muscate-magnussen.de			pluto_reset_ts(pluto, 1);
3134d8451700171d6bbc254191880f86bfdeec2f74fholger@muscate-magnussen.de			dev_printk(KERN_DEBUG, &pluto->pdev->dev, "resetting TS because of invalid packet counter\n");
3144d8451700171d6bbc254191880f86bfdeec2f74fholger@muscate-magnussen.de		}
315c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
316c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
317c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_dmx_swfilter_packets(&pluto->demux, pluto->dma_buf, nbpackets);
318c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
319c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* clear the dma buffer. this is needed to be able to identify
320c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	 * new valid ts packets above */
321c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	memset(pluto->dma_buf, 0, nbpackets * 188);
322c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
323c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* reset the dma address */
324c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_set_dma_addr(pluto);
325c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
326c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* sync the buffer and give it back to the card */
327c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_dma_sync_single_for_device(pluto->pdev, pluto->dma_addr,
328c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			TS_DMA_BYTES, PCI_DMA_FROMDEVICE);
329c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
330c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
3317d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t pluto_irq(int irq, void *dev_id)
332c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
333c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = dev_id;
334c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 tscr;
335c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
33625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* check whether an interrupt occurred on this device */
337c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	tscr = pluto_readreg(pluto, REG_TSCR);
338c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (!(tscr & (TSCR_DE | TSCR_OVR)))
339c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		return IRQ_NONE;
340c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
341c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (tscr == 0xffffffff) {
3420b61dca28909bc548581bec75e3b90faaa7f11fdAlan Cox		if (pluto->dead == 0)
3430b61dca28909bc548581bec75e3b90faaa7f11fdAlan Cox			dev_err(&pluto->pdev->dev, "card has hung or been ejected.\n");
3440b61dca28909bc548581bec75e3b90faaa7f11fdAlan Cox		/* It's dead Jim */
3450b61dca28909bc548581bec75e3b90faaa7f11fdAlan Cox		pluto->dead = 1;
346c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		return IRQ_HANDLED;
347c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
348c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
349c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* dma end interrupt */
350c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (tscr & TSCR_DE) {
351c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto_dma_end(pluto, (tscr & TSCR_NBPACKETS) >> 24);
352c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		/* overflow interrupt */
353c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		if (tscr & TSCR_OVR)
354c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			pluto->overflow++;
355c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		if (pluto->overflow) {
356c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			dev_err(&pluto->pdev->dev, "overflow irq (%d)\n",
357c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter					pluto->overflow);
358c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			pluto_reset_ts(pluto, 1);
359c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			pluto->overflow = 0;
360c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		}
361c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	} else if (tscr & TSCR_OVR) {
362c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		pluto->overflow++;
363c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
364c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
365c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* ACK the interrupt */
3661489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter	pluto_write_tscr(pluto, tscr | TSCR_IACK);
367c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
368c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return IRQ_HANDLED;
369c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
370c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
371c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void __devinit pluto_enable_irqs(struct pluto *pluto)
372c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
373c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 val = pluto_readreg(pluto, REG_TSCR);
374c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
375c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* disable AFUL and LOCK interrupts */
376c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val |= (TSCR_MSKA | TSCR_MSKL);
377c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* enable DMA and OVERFLOW interrupts */
378c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val &= ~(TSCR_DEM | TSCR_MSKO);
379c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* clear pending interrupts */
380c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val |= TSCR_IACK;
381c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
3821489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter	pluto_write_tscr(pluto, val);
383c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
384c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
385c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_disable_irqs(struct pluto *pluto)
386c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
387c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 val = pluto_readreg(pluto, REG_TSCR);
388c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
389c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* disable all interrupts */
390c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val |= (TSCR_DEM | TSCR_MSKO | TSCR_MSKA | TSCR_MSKL);
391c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* clear pending interrupts */
392c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val |= TSCR_IACK;
393c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
3941489f90a49f0603a393e1800d729050f6e332becAndreas Oberritter	pluto_write_tscr(pluto, val);
395c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
396c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
397c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int __devinit pluto_hw_init(struct pluto *pluto)
398c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
399c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_reset_frontend(pluto, 1);
400c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
401c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* set automatic LED control by FPGA */
402c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_rw(pluto, REG_MISC, MISC_ALED, MISC_ALED);
403c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
404c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* set data endianess */
405c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#ifdef __LITTLE_ENDIAN
406c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_rw(pluto, REG_PIDn(0), PID0_END, PID0_END);
407c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#else
408c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_rw(pluto, REG_PIDn(0), PID0_END, 0);
409c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#endif
410c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* map DMA and set address */
411c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_dma_map(pluto);
412c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_set_dma_addr(pluto);
413c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
414c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* enable interrupts */
415c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_enable_irqs(pluto);
416c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
417c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* reset TS logic */
418c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_reset_ts(pluto, 1);
419c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
420c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return 0;
421c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
422c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
423c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void pluto_hw_exit(struct pluto *pluto)
424c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
425c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* disable interrupts */
426c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_disable_irqs(pluto);
427c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
428c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_reset_ts(pluto, 0);
429c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
430c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* LED: disable automatic control, enable yellow, disable green */
431c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_rw(pluto, REG_MISC, MISC_ALED | MISC_LED1 | MISC_LED0, MISC_LED1);
432c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
433c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* unmap DMA */
434c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_dma_unmap(pluto);
435c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
436c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_reset_frontend(pluto, 0);
437c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
438c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
439c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic inline u32 divide(u32 numerator, u32 denominator)
440c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
441c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (denominator == 0)
442c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		return ~0;
443c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
44475b697f747b14b0c6afae48ee0f5e605abd2df4cJulia Lawall	return DIV_ROUND_CLOSEST(numerator, denominator);
445c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
446c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
447c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter/* LG Innotek TDTE-E001P (Infineon TUA6034) */
44814d24d148c7521b2b88b396652e36f55d061e195Mauro Carvalho Chehabstatic int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe)
449c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
4502f786bbefc2f1cab6e9560476ea69003d19ee5cbMauro Carvalho Chehab	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
451c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = frontend_to_pluto(fe);
452c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct i2c_msg msg;
453c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	int ret;
454c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u8 buf[4];
455c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 div;
456c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
457c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	// Fref = 166.667 Hz
458c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	// Fref * 3 = 500.000 Hz
459c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	// IF = 36166667
460c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	// IF / Fref = 217
461c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	//div = divide(p->frequency + 36166667, 166667);
462c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	div = divide(p->frequency * 3, 500000) + 217;
463c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	buf[0] = (div >> 8) & 0x7f;
464c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	buf[1] = (div >> 0) & 0xff;
465c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
466c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (p->frequency < 611000000)
467c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[2] = 0xb4;
468c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	else if (p->frequency < 811000000)
469c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[2] = 0xbc;
470c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	else
471c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[2] = 0xf4;
472c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
473c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	// VHF: 174-230 MHz
474c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	// center: 350 MHz
475c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	// UHF: 470-862 MHz
476c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (p->frequency < 350000000)
477c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[3] = 0x02;
478c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	else
479c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[3] = 0x04;
480c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
4812f786bbefc2f1cab6e9560476ea69003d19ee5cbMauro Carvalho Chehab	if (p->bandwidth_hz == 8000000)
482c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[3] |= 0x08;
483c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
484c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (sizeof(buf) == 6) {
485c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[4] = buf[2];
486c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[4] &= ~0x1c;
487c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[4] |=  0x18;
488c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
489c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		buf[5] = (0 << 7) | (2 << 4);
490c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
491c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
492c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	msg.addr = I2C_ADDR_TUA6034 >> 1;
493c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	msg.flags = 0;
494c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	msg.buf = buf;
495c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	msg.len = sizeof(buf);
496c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
497dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher	if (fe->ops.i2c_gate_ctrl)
498dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher		fe->ops.i2c_gate_ctrl(fe, 1);
499c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = i2c_transfer(&pluto->i2c_adap, &msg, 1);
500c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
501c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		return ret;
502c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	else if (ret == 0)
503c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		return -EREMOTEIO;
504c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
505c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return 0;
506c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
507c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
508c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int pluto2_request_firmware(struct dvb_frontend *fe,
509c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter				   const struct firmware **fw, char *name)
510c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
511c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = frontend_to_pluto(fe);
512c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
513c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return request_firmware(fw, name, &pluto->pdev->dev);
514c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
515c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
516c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic struct tda1004x_config pluto2_fe_config __devinitdata = {
517c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.demod_address = I2C_ADDR_TDA10046 >> 1,
518c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.invert = 1,
519c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.invert_oclk = 0,
520c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.xtal_freq = TDA10046_XTAL_16M,
521c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.agc_config = TDA10046_AGC_DEFAULT,
522c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.if_freq = TDA10046_FREQ_3617,
523c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.request_firmware = pluto2_request_firmware,
524c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter};
525c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
526c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int __devinit frontend_init(struct pluto *pluto)
527c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
528c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	int ret;
529c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
530c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->fe = tda10046_attach(&pluto2_fe_config, &pluto->i2c_adap);
531c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (!pluto->fe) {
532c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		dev_err(&pluto->pdev->dev, "could not attach frontend\n");
533c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		return -ENODEV;
534c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
535dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher	pluto->fe->ops.tuner_ops.set_params = lg_tdtpe001p_tuner_set_params;
536c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
537c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe);
538c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0) {
539dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher		if (pluto->fe->ops.release)
540dea74869f3c62b0b7addd67017b22b394e942aacPatrick Boettcher			pluto->fe->ops.release(pluto->fe);
541c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		return ret;
542c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
543c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
544c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return 0;
545c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
546c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
547c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void __devinit pluto_read_rev(struct pluto *pluto)
548c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
549c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 val = pluto_readreg(pluto, REG_MISC) & MISC_DVR;
550c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dev_info(&pluto->pdev->dev, "board revision %d.%d\n",
551c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			(val >> 12) & 0x0f, (val >> 4) & 0xff);
552c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
553c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
554c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void __devinit pluto_read_mac(struct pluto *pluto, u8 *mac)
555c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
556c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u32 val = pluto_readreg(pluto, REG_MMAC);
557c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	mac[0] = (val >> 8) & 0xff;
558c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	mac[1] = (val >> 0) & 0xff;
559c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
560c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val = pluto_readreg(pluto, REG_IMAC);
561c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	mac[2] = (val >> 8) & 0xff;
562c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	mac[3] = (val >> 0) & 0xff;
563c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
564c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	val = pluto_readreg(pluto, REG_LMAC);
565c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	mac[4] = (val >> 8) & 0xff;
566c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	mac[5] = (val >> 0) & 0xff;
567c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
5687c510e4b730a92cecf94ada45c989d8be0200d47Johannes Berg	dev_info(&pluto->pdev->dev, "MAC %pM\n", mac);
569c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
570c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
571c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int __devinit pluto_read_serial(struct pluto *pluto)
572c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
573c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pci_dev *pdev = pluto->pdev;
574c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	unsigned int i, j;
575c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	u8 __iomem *cis;
576c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
577c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	cis = pci_iomap(pdev, 1, 0);
578c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (!cis)
579c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		return -EIO;
580c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
581c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dev_info(&pdev->dev, "S/N ");
582c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
583c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	for (i = 0xe0; i < 0x100; i += 4) {
584c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		u32 val = readl(&cis[i]);
585c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		for (j = 0; j < 32; j += 8) {
586c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			if ((val & 0xff) == 0xff)
587c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter				goto out;
588c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			printk("%c", val & 0xff);
589c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			val >>= 8;
590c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		}
591c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
592c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterout:
593c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	printk("\n");
594c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_iounmap(pdev, cis);
595c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
596c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return 0;
597c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
598c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
599c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int __devinit pluto2_probe(struct pci_dev *pdev,
600c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter				  const struct pci_device_id *ent)
601c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
602c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto;
603c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dvb_adapter *dvb_adapter;
604c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dvb_demux *dvbdemux;
605c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dmx_demux *dmx;
606c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	int ret = -ENOMEM;
607c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
6087408187d223f63d46a13b6a35b8f96b032c2f623Panagiotis Issaris	pluto = kzalloc(sizeof(struct pluto), GFP_KERNEL);
609c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (!pluto)
610c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto out;
611c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
612c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->pdev = pdev;
613c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
614c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = pci_enable_device(pdev);
615c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
616c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_kfree;
617c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
618c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* enable interrupts */
619c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_write_config_dword(pdev, 0x6c, 0x8000);
620c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
621284901a90a9e0b812ca3f5f852cbbfb60d10249dYang Hongyang	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
622c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
623c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_pci_disable_device;
624c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
625c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_set_master(pdev);
626c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
627c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = pci_request_regions(pdev, DRIVER_NAME);
628c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
629c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_pci_disable_device;
630c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
631c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->io_mem = pci_iomap(pdev, 0, 0x40);
632c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (!pluto->io_mem) {
633c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		ret = -EIO;
634c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_pci_release_regions;
635c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}
636c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
637c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_set_drvdata(pdev, pluto);
638c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
6398076fe32a7db9a6628589ffa372808e4ba25d222Thomas Gleixner	ret = request_irq(pdev->irq, pluto_irq, IRQF_SHARED, DRIVER_NAME, pluto);
640c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
641c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_pci_iounmap;
642c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
643c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = pluto_hw_init(pluto);
644c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
645c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_free_irq;
646c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
647c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* i2c */
648c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	i2c_set_adapdata(&pluto->i2c_adap, pluto);
649c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	strcpy(pluto->i2c_adap.name, DRIVER_NAME);
650c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_adap.owner = THIS_MODULE;
651c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_adap.dev.parent = &pdev->dev;
652c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_adap.algo_data = &pluto->i2c_bit;
653c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_bit.data = pluto;
654c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_bit.setsda = pluto_setsda;
655c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_bit.setscl = pluto_setscl;
656c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_bit.getsda = pluto_getsda;
657c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_bit.getscl = pluto_getscl;
658c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_bit.udelay = 10;
659c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->i2c_bit.timeout = 10;
660c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
661c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* Raise SCL and SDA */
662c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_setsda(pluto, 1);
663c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_setscl(pluto, 1);
664c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
665c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = i2c_bit_add_bus(&pluto->i2c_adap);
666c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
667c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_pluto_hw_exit;
668c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
669c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	/* dvb */
67078e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau	ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME,
67178e92006f410a4044f8c1760c25ac9d11d259aa2Janne Grunau				   THIS_MODULE, &pdev->dev, adapter_nr);
672c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
6733269711b76ba27b78862c48398b0d313ccaa99c2Jean Delvare		goto err_i2c_del_adapter;
674c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
675c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_adapter = &pluto->dvb_adapter;
676c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
677c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_read_rev(pluto);
678c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_read_serial(pluto);
679c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_read_mac(pluto, dvb_adapter->proposed_mac);
680c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
681c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvbdemux = &pluto->demux;
682c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvbdemux->filternum = 256;
683c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvbdemux->feednum = 256;
684c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvbdemux->start_feed = pluto_start_feed;
685c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvbdemux->stop_feed = pluto_stop_feed;
686c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
687c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter			DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
688c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = dvb_dmx_init(dvbdemux);
689c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
690c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_dvb_unregister_adapter;
691c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
692c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dmx = &dvbdemux->dmx;
693c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
694c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->hw_frontend.source = DMX_FRONTEND_0;
695c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->mem_frontend.source = DMX_MEMORY_FE;
696c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->dmxdev.filternum = NHWFILTERS;
697c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto->dmxdev.demux = dmx;
698c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
699c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = dvb_dmxdev_init(&pluto->dmxdev, dvb_adapter);
700c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
701c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_dvb_dmx_release;
702c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
703c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = dmx->add_frontend(dmx, &pluto->hw_frontend);
704c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
705c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_dvb_dmxdev_release;
706c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
707c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = dmx->add_frontend(dmx, &pluto->mem_frontend);
708c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
709c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_remove_hw_frontend;
710c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
711c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = dmx->connect_frontend(dmx, &pluto->hw_frontend);
712c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
713c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_remove_mem_frontend;
714c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
715c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	ret = frontend_init(pluto);
716c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (ret < 0)
717c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		goto err_disconnect_frontend;
718c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
719c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_net_init(dvb_adapter, &pluto->dvbnet, dmx);
720c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterout:
721c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return ret;
722c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
723c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_disconnect_frontend:
724c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dmx->disconnect_frontend(dmx);
725c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_remove_mem_frontend:
726c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dmx->remove_frontend(dmx, &pluto->mem_frontend);
727c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_remove_hw_frontend:
728c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dmx->remove_frontend(dmx, &pluto->hw_frontend);
729c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_dvb_dmxdev_release:
730c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_dmxdev_release(&pluto->dmxdev);
731c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_dvb_dmx_release:
732c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_dmx_release(dvbdemux);
733c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_dvb_unregister_adapter:
734c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_unregister_adapter(dvb_adapter);
7353269711b76ba27b78862c48398b0d313ccaa99c2Jean Delvareerr_i2c_del_adapter:
7363269711b76ba27b78862c48398b0d313ccaa99c2Jean Delvare	i2c_del_adapter(&pluto->i2c_adap);
737c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_pluto_hw_exit:
738c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_hw_exit(pluto);
739c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_free_irq:
740c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	free_irq(pdev->irq, pluto);
741c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_pci_iounmap:
742c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_iounmap(pdev, pluto->io_mem);
743c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_pci_release_regions:
744c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_release_regions(pdev);
745c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_pci_disable_device:
746c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_disable_device(pdev);
747c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittererr_kfree:
748c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_set_drvdata(pdev, NULL);
749c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	kfree(pluto);
750c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	goto out;
751c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
752c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
753c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void __devexit pluto2_remove(struct pci_dev *pdev)
754c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
755c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct pluto *pluto = pci_get_drvdata(pdev);
756c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dvb_adapter *dvb_adapter = &pluto->dvb_adapter;
757c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dvb_demux *dvbdemux = &pluto->demux;
758c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	struct dmx_demux *dmx = &dvbdemux->dmx;
759c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
760c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dmx->close(dmx);
761c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_net_release(&pluto->dvbnet);
762c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	if (pluto->fe)
763c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		dvb_unregister_frontend(pluto->fe);
764c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
765c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dmx->disconnect_frontend(dmx);
766c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dmx->remove_frontend(dmx, &pluto->mem_frontend);
767c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dmx->remove_frontend(dmx, &pluto->hw_frontend);
768c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_dmxdev_release(&pluto->dmxdev);
769c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_dmx_release(dvbdemux);
770c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	dvb_unregister_adapter(dvb_adapter);
7713269711b76ba27b78862c48398b0d313ccaa99c2Jean Delvare	i2c_del_adapter(&pluto->i2c_adap);
772c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pluto_hw_exit(pluto);
773c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	free_irq(pdev->irq, pluto);
774c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_iounmap(pdev, pluto->io_mem);
775c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_release_regions(pdev);
776c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_disable_device(pdev);
777c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_set_drvdata(pdev, NULL);
778c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	kfree(pluto);
779c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
780c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
781c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#ifndef PCI_VENDOR_ID_SCM
782c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define PCI_VENDOR_ID_SCM	0x0432
783c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#endif
784c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#ifndef PCI_DEVICE_ID_PLUTO2
785c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#define PCI_DEVICE_ID_PLUTO2	0x0001
786c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter#endif
787c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
788c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic struct pci_device_id pluto2_id_table[] __devinitdata = {
789c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	{
790c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		.vendor = PCI_VENDOR_ID_SCM,
791c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		.device = PCI_DEVICE_ID_PLUTO2,
792c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		.subvendor = PCI_ANY_ID,
793c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		.subdevice = PCI_ANY_ID,
794c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	}, {
795c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter		/* empty */
796c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	},
797c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter};
798c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
799c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas OberritterMODULE_DEVICE_TABLE(pci, pluto2_id_table);
800c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
801c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic struct pci_driver pluto2_driver = {
802c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.name = DRIVER_NAME,
803c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.id_table = pluto2_id_table,
804c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.probe = pluto2_probe,
805c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	.remove = __devexit_p(pluto2_remove),
806c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter};
807c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
808c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic int __init pluto2_init(void)
809c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
810c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	return pci_register_driver(&pluto2_driver);
811c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
812c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
813c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritterstatic void __exit pluto2_exit(void)
814c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter{
815c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter	pci_unregister_driver(&pluto2_driver);
816c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter}
817c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
818c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittermodule_init(pluto2_init);
819c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberrittermodule_exit(pluto2_exit);
820c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas Oberritter
821c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas OberritterMODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
822c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas OberritterMODULE_DESCRIPTION("Pluto2 driver");
823c7cadb3a02b5803c2f251b5cd84fbdc8fbec05e9Andreas OberritterMODULE_LICENSE("GPL");
824