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